2013-02-12 57 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