我是Android开发的新手,我正在编写一个小应用程序来了解它是如何工作的。我已经全部工作了,但目前我无法得到关于自定义可绘制状态的观点......让我用一些示例代码解释一下。
这是我的attrs.xml,其中我声明了一个名为“oddMonth”的属性,它是boolean:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="DayView">
<attr name="oddMonth" format="boolean"/>
</declare-styleable>
</resources>
然后我有一个自定义视图:
<?xml version="1.0" encoding="utf-8"?>
<com.example.calendar.DayView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="90dp"
android:background="@drawable/dayview_state" >
<TextView android:id="@+id/day_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:paddingRight="3dp" />
</com.example.calendar.DayView>
所以我把行“android:background =”@ drawable / dayview_state“”,它引用文件dayview_state.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:easycalendar="http://schemas.android.com/apk/res/com.example.calendar">
<item easycalendar:oddMonth ="true" android:drawable="@drawable/customborder_odd" />
<item easycalendar:oddMonth ="false" android:drawable="@drawable/customborder_even"/>
</selector>
到目前为止......我能理解......我在attrs.xml中定义了一个属性。此属性表示我的自定义视图的状态。根据这个属性的布尔值,我的应用程序将加载两个不同的xml中的一个(这里不重要),每个都定义一个不同的drawable。所以最后一步是构建我的自定义类!跟随课程摘录:
public class DayView extends RelativeLayout {
private static final int[] STATE_ODD_MONTH = { R.attr.oddMonth };
private boolean mOddmonth = true;
public DayView(Context mContext, AttributeSet attrs) {
super(mContext, attrs);
}
@Override
protected int[] onCreateDrawableState(int extraSpace) {
if (mOddmonth) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
mergeDrawableStates(drawableState, STATE_ODD_MONTH);
return drawableState;
} else {
return super.onCreateDrawableState(extraSpace);
}
}
public boolean isOddMonth() {
return mOddmonth;
}
public void setOddMonth(boolean oddMonth) {
if (mOddmonth != oddMonth) {
mOddmonth = oddMonth;
refreshDrawableState();
}
}
}
好的......所以我这里有一个私有变量mOddMonth,有getter和setter。用于在其他地方膨胀此视图的构造函数。另一个私人变量:
private static final int[] STATE_ODD_MONTH = { R.attr.oddMonth };
这是一个只由一个int值组成的数组,它是对attrs.xml中定义的oddMonth属性的引用。和继承的方法:
@Override
protected int[] onCreateDrawableState(int extraSpace) {
if (mOddmonth) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
mergeDrawableStates(drawableState, STATE_ODD_MONTH);
return drawableState;
} else {
return super.onCreateDrawableState(extraSpace);
}
}
我无法“深入”理解......好吧,在我看来,如果局部变量mOddMonth为真,我会添加一个状态,否则不会。所以...我的代码只有在我用以下内容替换dayview_state.xml时才有效:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:easycalendar="http://schemas.android.com/apk/res/com.example.calendar">
<item easycalendar:oddMonth ="true" android:drawable="@drawable/customborder_odd" />
<item android:drawable="@drawable/customborder_even"/>
</selector>
这样,如果THERE是状态,则加载第一个布局,否则将加载第二个布局。但关于国家价值的是什么?我的代码中没有任何地方设置此变量/属性的值....我错了吗?
答案 0 :(得分:0)
你是对的;您需要使用AttributeSet变量在构造函数中分配该值:
TypedArray values = context.obtainStyledAttributes(attrs, STATE_ODD_MONTH);
boolean isOddMonth = values.getBoolean(R.attr.oddMonth, false);
mOddmonth = isOddMonth;
values.recycle();
我相信这应该可以解决问题。我通常在attrs.xml中使用declare-styleable标签而不是硬编码int [],但我相信它应该完全相同。
答案 1 :(得分:0)
我建议你改写你的问题b / c我不清楚你问的是什么,直到我读到你对@ kcoppock的回答的评论,这是 -
“我想做什么(或者我认为我应该做的)是设置这个值 根据我的自定义视图的实际状态在代码中的某处, 然后强制它再次渲染....或者我不应该?“
在任何时候,您都可以使用 View.getDrawableState 查询视图以获取可绘制状态。
如果基于此,您想要重新渲染您的drawable,那么您有几个选项。
首先,您可以调用 Drawable.invalidateSelf 。但是你很少需要这样做,因为通常你的drawable被设置为一个视图的背景drawable,它是在draw方法中自动绘制的(而不是onDraw,这是你绘制的)。因此,在这种情况下您需要做的就是使视图无效( view.invalidate ),它会自动重绘您的背景可绘制(因此拾取您的可绘制状态更改)。
如果您使用的是drawable而不是背景而是主画,那么您可以在 onDraw 中绘制您的drawable。一个简单的myDrawable.draw(canvas)就足够了。但请记住vall view.invalidate来触发onDraw方法。