使用风格

时间:2017-08-10 14:40:40

标签: android android-layout declare-styleable styleable

我想创建一个包含进度视图和按钮的视图。通过视图的xml我想添加定义按钮和porgress栏样式的字段。

到目前为止我做了什么,但它不起作用:

   <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>
有人帮帮我吗?感谢

1 个答案:

答案 0 :(得分:1)

问题在于ButtonProgressBar的构造函数。让我们考虑两个构造函数。 (重点是我的。)(Documentation

  

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,但请耐心等待。

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

<强> styles.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,我认为您必须执行this之类的操作。

我希望这会有所帮助。