我想创建一个包含进度视图和按钮的视图。通过视图的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>
有人帮帮我吗?感谢
答案 0 :(得分:1)
问题在于Button
和ProgressBar
的构造函数。让我们考虑两个构造函数。 (重点是我的。)(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,但请耐心等待。
您为buttonId
和progressId
定义的内容是指向样式(<style...
)的资源ID。此样式资源ID适用于defStyleRes
和Button
构造函数的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之类的操作。
我希望这会有所帮助。