2013-02-12 30 views
5

我是Android开发新手,我正在编写一个小应用程序以了解它的工作原理。我有所有的工作,但目前我无法得到一个关于自定义可绘制状态的观点......让我来解释一些示例代码。无法理解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> 

所以我放线 “机器人:背景=” @绘制/ 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> 

,使f ar ...为了我能理解....我有一个在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和二传手。用于在其他地方膨胀此视图的构造函数。另一个专用变量:

private static final int[] STATE_ODD_MONTH = { R.attr.oddMonth }; 

其是仅由一个int值的阵列,即属性oddMonth在attrs.xml定义的参考。而继承的方法:

@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> 

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

+0

它似乎与默认选择器一起工作,只设置真值:<?xml version =“1.0”encoding =“utf-8”?> <! - pressed - > <! - 集中 - > <项目安卓!颜色= “#FF000000”/><! - 默认 - > 2013-02-12 08:33:46

+0

等等?我的自定义选择器呢? – Stefano 2013-02-12 10:00:17

+0

我不认为我明白你的问题本身 - 变量mOddmonth设置为true,那么,为什么你最终在onCreateDrawableState STATE_ODD_MONTH状态,多数民众赞成。那么究竟是什么,你的意思是“怎么样的状态值?无处在我的代码设置的值此变量/属性” – 2013-05-13 19:09:38

回答

0

我建议你改写你的问题二/三,目前还不清楚你问什么,直到我读@ kcoppock的回答您的意见,这是 -

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

在任何时候,你可以查询视图中使用View.getDrawableState得到它绘制状态。

如果在此基础上,要重新渲染你的绘制,那么你有几种选择。

首先您可以拨打Drawable.invalidateSelf。但你很少需要这样做,因为通常你的drawable被设置为一个视图的背景drawable,它会在draw方法中自动绘制(不是onDraw,这是你绘制的)。因此,所有你需要在这种情况下,做的是无效的视图(view.invalidate),它会自动重新绘制你的背景绘制(因此拿起你的绘制状态变化)。

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

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 []进行硬编码,但我相信它应该同样工作。

+0

谢谢你的答复! well ...但是TypedArray不用于检索attrs.xml中定义的属性oddMonth的值吗?我想要做的(或我想我应该做的),是根据我的自定义视图的实际状态在某处代码设置此值,然后迫使其再次渲染....或者我不应该? – Stefano 2013-02-12 01:15:08

+0

哦,我明白了;我相信我误解了这个问题,对不起。 – kcoppock 2013-02-12 02:37:44

+0

@Stefano在下面看到我的答案。 – 2013-05-13 19:47:16