2013-02-12 21 views
5

Jestem nowy w rozwoju Androida i piszę małą aplikację, aby zrozumieć, jak to działa. Mam wszystko działa, ale w tej chwili nie mogę uzyskać punktu o niestandardowych stanach do rysowania ... pozwól mi wyjaśnić za pomocą przykładowego kodu.Nie można zrozumieć niestandardowego stanu pobierania z Androidem

Oto mój attrs.xml, w którym Oświadczam atrybut o nazwie "oddMonth", która jest logiczna:

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <declare-styleable name="DayView"> 
     <attr name="oddMonth" format="boolean"/> 
    </declare-styleable> 
</resources> 

Wtedy mam niestandardowy Widok:

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

Więc umieścić wiersz "android: t =" @ rozciągliwej/dayview_state "", który odnosi się do pliku 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> 

więc f ar ... co mogę zrozumieć .... Mam atrybut zdefiniowany w attrs.xml. Ten atrybut reprezentuje stan dla mojego widoku niestandardowego. Według wartości boolowskiej tego atrybutu moja aplikacja załaduje jeden z dwóch różnych xml (które nie są tutaj ważne), każdy z nich definiuje inną opcję losowania. Ostatnim krokiem jest więc zbudowanie mojej niestandardowej klasy! Wynika z ekstraktu z klasy:

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(); 
     } 
    } 
} 

Ok ... więc mam tu prywatną zmienną mOddMonth, whith getter i setter. Konstruktor używany do nadmuchania tego widoku w innym miejscu. Innym zmienny prywatna:

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

która jest tablicą składa się z tylko jednej wartości int, to odniesienie do atrybutu oddMonth określonej w attrs.xml. I dziedziczone metody:

@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); 
     } 
    } 

których nie mogę naprawdę „głęboko” zrozumieć ... Cóż, wydaje mi się, że mogę dodać stan jeśli zmienna lokalna mOddMonth jest prawdą, w przeciwnym razie nie. Tak ... mój kod działa tylko jeśli mogę wymienić mój dayview_state.xml z następujących czynności:

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

W ten sposób pierwszy układ jest ładowany, jeżeli istnieje stan, w przeciwnym razie zostanie załadowany drugi. Ale CO O WARTOŚCI PAŃSTWA? Nigdzie w moim kodzie nie ustawiłem wartości dla tej zmiennej/atrybutu .... gdzie się mylę?

+0

Wygląda na to, że działa z domyślnym selektorem i ustawia tylko prawdziwe wartości:

+0

I tak? co z moim niestandardowym selektorem? – Stefano

+0

Nie sądzę, że rozumiem twoje pytanie jako takie - zmienna mOddmonth jest ustawiona na true, dlatego właśnie kończysz na stanie STATE_ODD_MONTH w onCreateDrawableState. Co dokładnie masz na myśli przez "CO O WARTOŚCI stanu?" Nigdzie w moim kodzie nie ustawiam wartości tej zmiennej/atrybutu " –

Odpowiedz

0

Polecam Ci przeredagować swoje pytanie b/c nie było jasne, co pytałeś dopóki nie przeczytałem komentarz do użytkownika @ kcoppock odpowiedź, która jest -

„co chcę zrobić (lub Myślę, że powinienem zrobić) to ustawić tę wartość gdzieś w kodzie zgodnie z aktualnym statusem mojego widoku niestandardowego, , a następnie zmusić go do renderowania ponownie. Czy nie powinienem? "

W dowolnym momencie można kwerendy widoku, aby to państwo rozciągliwej użyciu View.getDrawableState.

Jeśli na tej podstawie chcesz zrenderować swój wyciąg, to masz kilka opcji.

Przede wszystkim można zadzwonić pod numer Drawable.invalidateSelf. Ale rzadko musisz to robić, ponieważ zazwyczaj Twój draws jest ustawiony jako widok tła w tle, który jest automatycznie narysowany dla ciebie w metodzie rysowania (nie na stronie, którą rysujesz). Więc wszystko, co musisz zrobić w tym przypadku, to unieważnić widok (view.invalidate), to automatycznie przerysuje twoje szuflady tła (stąd podniesienie twojej zmiany stanu rysowania).

Jeśli korzystasz z wyciągu nie jako tła, ale dla głównego rysunku, to narysuj swoje rysunki w onDraw. Prosty plik myDrawable.draw (canvas) powinien wystarczyć. Ale pamiętaj, aby vall view.invalidate wyzwolić metodę onDraw.

0

Masz rację; trzeba przypisać tę wartość w konstruktora ze zmienną AttributeSet:

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

Wierzę, że to powinno wystarczyć. Zwykle używam tag-stylable deklaracji w attrs.xml zamiast hardcoding int [], ale uważam, że powinien działać identycznie.

+0

Dziękuję za odpowiedź! dobrze ... Ale TypedArray nie jest używany do pobierania wartości atrybutu "CzasMont" zdefiniowanego w attrs.xml? co chcę zrobić (lub chyba powinienem zrobić) to ustawić tę wartość gdzieś w kodzie zgodnie z faktycznym statusem mojego widoku niestandardowego, a następnie zmusić go do renderowania ponownie. Czy nie powinienem? – Stefano

+0

Och, widzę; Wierzę, że źle zrozumiałem pytanie, przepraszam. – kcoppock

+0

@Stefano zobacz moją odpowiedź poniżej. –

Powiązane problemy