6

我是 Android 开发的新手,我正在编写一个小应用程序来了解它是如何工作的。我已经完成了所有工作,但目前我对自定义可绘制状态一无所知……让我用一些示例代码来解释一下。

这是我的 attrs.xml,我在其中声明了一个名为“oddMonth”的属性,它是布尔值:

<?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 之一(在此不重要),每个都定义一个不同的可绘制对象。所以最后一步是构建我的自定义类!以下是该课程的摘录:

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>

这样,如果有状态,则加载第一个布局,否则将加载第二个布局。但是国家的价值呢?在我的代码中,我没有为这个变量/属性设置值....我错了?

4

2 回答 2

1

我建议您改写您的问题 b/c 在我阅读您对@kcoppock 答案的评论之前,您不清楚您在问什么,即-

“我想要做的(或者我认为我应该做的)是根据我的自定义视图的实际状态在代码中的某个位置设置这个值,然后强制它再次渲染......或者我不应该?”

在任何时候,您都可以使用View.getDrawableState查询视图以获取它的可绘制状态。

如果基于此,你想重新渲染你的drawable,那么你有几个选择。

首先你可以调用Drawable.invalidateSelf。但是您很少需要这样做,因为通常您的可绘制对象被设置为视图的背景可绘制对象,它会在 draw 方法中自动为您绘制(不是 onDraw,这是您绘制的内容)。因此,在这种情况下,您需要做的就是使视图无效(view.invalidate),它会自动重绘您的背景可绘制对象(因此获取可绘制状态的更改)。

如果你使用你的drawable不是作为背景而是作为你的主图,那么你在onDraw中绘制你的drawable 。一个简单的 myDrawable.draw(canvas) 就足够了。但请记住使用 vall view.invalidate 来触发 onDraw 方法。

于 2013-05-13T19:47:00.377 回答
0

你是对的;您需要在构造函数中使用 AttributeSet 变量分配该值:

TypedArray values = context.obtainStyledAttributes(attrs, STATE_ODD_MONTH);
boolean isOddMonth = values.getBoolean(R.attr.oddMonth, false);
mOddmonth = isOddMonth;
values.recycle();

我相信这应该可以解决问题。我通常在 attrs.xml 中使用可声明样式的标签,而不是硬编码 int[],但我相信它应该可以同样工作。

于 2013-02-12T01:00:08.797 回答