1

我想制作一个包含进度视图和按钮的视图。通过视图的 xml,我想添加定义按钮和入口栏样式的字段。

到目前为止我所做的但它不起作用:

   <io.**.**.view.ButtonLoading android:id="@+id/b_recover_password"
                                       android:layout_width="wrap_content"
                                       android:gravity="center"
                                       app:styleButton="@style/ButtonGrey"
                                       app:styleProgress="@style/ProgressBar"
                                       app:textButton="@string/recover_password"
                                       android:layout_height="wrap_content"/>

代码:

   a = context.getTheme().obtainStyledAttributes(
            attrs,
            R.styleable.ButtonLoading,
            0, 0);

    int buttonId = 0;// R.style.Widget_AppCompat_Button;
    try {
        buttonId = a.getResourceId(R.styleable.ButtonLoading_styleButton, 0);
    } catch (Exception e) {
    }

    button = new Button(getContext(), attrs, buttonId);

    LayoutParams lpButton = createLayoutParams();
    button.setLayoutParams(lpButton);
    color = button.getCurrentTextColor();

    int progressId = 0;// R.style.Widget_AppCompat_ProgressBar;
    try {
        progressId = a.getResourceId(R.styleable.ButtonLoading_styleProgress, 0);
    } catch (Exception e) {
    }

    progressBar = new ProgressBar(getContext(), attrs, progressId);
    LayoutParams lpProgressBar = createLayoutParams();
    lpProgressBar.addRule(RelativeLayout.CENTER_IN_PARENT);
    progressBar.setLayoutParams(lpProgressBar);

    LayoutParams lpRelativeLayout = createLayoutParams();
    setLayoutParams(lpRelativeLayout);

    addView(button);
    addView(progressBar);

    try {
        String value = a.getString(R.styleable.ButtonLoading_textButton);
        button.setText(value);
    } catch (Exception e) {
    }
    a.recycle();

可样式化:

   <declare-styleable name="ButtonLoading">
    <attr name="styleButton" format="reference" />
    <attr name="styleProgress" format="reference" />
    <attr name="textButton" format="string" />
</declare-styleable>

谁来帮帮我?谢谢

4

2 回答 2

2

问题出在你的构造函数中ButtonProgressBar。让我们考虑两个构造函数。(重点是我的。)(文档

View(Context context, AttributeSet attrs, int defStyleAttr) [适用于 API 21 以下]

从 XML 执行膨胀并从主题属性应用特定于类的基本样式。这个 View 的构造函数允许子类在膨胀时使用它们自己的基本样式。例如,Button 类的构造函数将调用此版本的超类构造函数并为 defStyleAttr 提供 R.attr.buttonStyle;这允许主题的按钮样式修改所有基本视图属性(特别是其背景)以及 Button 类的属性。

View(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) [适用于 API 21+]

从 XML 执行膨胀并从主题属性或样式资源应用特定于类的基本样式。这个 View 的构造函数允许子类在膨胀时使用它们自己的基本样式。

专注于最后两个论点。

defStyleAttr int:当前主题中的一个属性,包含对样式资源的引用,该资源为视图提供默认值。可以为 0 以不查找默认值。

defStyleRes int:样式资源的资源标识符,为视图提供默认值,仅在 defStyleAttr 为 0 或在主题中找不到时使用。可以为 0 以不查找默认值。

这很令人困惑,因为有资源 id 指向资源 id,但请耐心等待。

您定义的buttonId内容progressId是指向样式 ( <style...) 的资源 id。此样式资源 id 适合用于和构造函数的defStyleRes属性,如上文所述。您正在尝试将这些资源值中的每一个用作指向当前主题中的属性的 id。换句话说,您是说 R.attr.styleButton ( ) 是当前主题中的一个属性,它不是当前定义的。要解决此问题,请将主题样式更改为以下内容:ButtonProgressBarstyleButton

样式.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="styleButton">@style/ButtonGrey</item>
    ...
</style>        

要使用 API 21+,您可以保留样式和布局文件原样,并将自定义视图代码更改为如下所示。(我只显示按钮的代码,但进度条会类似。)您可能希望为 API 21+ ( styles-v21.xml) 创建一个单独的样式文件。

public CustomViewGroup(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    TypedArray a = context.getTheme().obtainStyledAttributes(
            attrs,
            R.styleable.ButtonLoading,
            0, 0);
    int defStyleRes = 0;
    try {
        defStyleRes = a.getResourceId(R.styleable.ButtonLoading_styleButton, 0);
    } catch (Exception e) {
      // do something
    }
    Button button;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        // defStyleRes is only used if defStyleAttr == 0 
        // or can't be found in the current theme.
        button = new Button(getContext(), attrs, defStyleAttr, defStyleRes);
    } else {
        button = new Button(getContext(), attrs, 
                     (defStyleAttr != 0) ? defStyleAttr : R.attr.styleButton);
    }
    try {
        String value = a.getString(R.styleable.ButtonLoading_textButton);
        button.setText(value);
    } catch (Exception e) {
      // do something
    }
    addView(button);
    a.recycle();
}

按照您的编码设置按钮的文本。样式更棘手。要app:styleButton="@style/ButtonGrey"按照您对所有 API 的预期工作,我认为您必须执行类似的操作

我希望这有帮助。

于 2017-08-11T01:01:05.677 回答
0

我的风格是:

    <!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:buttonStyle">@style/ButtonAppTheme</item>
    <item name="android:progressBarStyle">@style/ProgressBarBase</item>
</style>

<style name="ProgressBarBase" parent="android:Widget.Holo.Light.ProgressBar">
    <item name="android:textColorTertiary">@color/color_grey</item>
</style>

<style name="ProgressBar" parent="android:Widget.Holo.Light.ProgressBar">
    <item name="android:textColorTertiary">@color/color_black</item>
</style>

问题是你总是有“ProgressBarBase”风格。也就是说,它不是压倒一切的。

于 2017-08-11T09:32:05.483 回答