2010-05-21 32 views
32

sto imparando sull'utilizzo Visualizzazioni personalizzate dal seguente:Android visualizzazione personalizzata Constructor

http://developer.android.com/guide/topics/ui/custom-components.html#modifying

La descrizione dice:

Classe inizializzazione Come sempre, il Super è chiamato per primo. Inoltre, questo non è un costruttore predefinito, ma uno parametrizzato. EditText è creato con questi parametri quando è gonfiato da un file di layout XML, così, il nostro costruttore ha bisogno sia di prenderli e passarli al costruttore della superclasse pure.

Esiste una descrizione migliore? Ho cercato di capire come dovrebbero apparire i costruttori e ho trovato 4 possibili scelte (vedi esempio alla fine del post). Non sono sicuro di cosa facciano (o non facciano) queste 4 scelte, perché dovrei implementarle o cosa significano i parametri. C'è una descrizione di questi?

public MyCustomView() 
{ 
    super(); 
} 

public MyCustomView(Context context) 
{ 
    super(context); 
} 

public MyCustomView(Context context, AttributeSet attrs) 
{ 
    super(context, attrs); 
} 

public MyCustomView(Context context, AttributeSet attrs, Map params) 
{ 
    super(context, attrs, params); 
} 
+0

Domanda simile qui: http://stackoverflow.com/questions/9195713/do-i-need-all-three-constructors-for-an-android-custom-view – mbonnin

risposta

61

Non è necessario il primo, in quanto non funziona.

Il terzo indica la tua personalizzazione View utilizzabile dai file di layout XML. Se non ti interessa, non ne hai bisogno.

Il quarto è semplicemente sbagliato, AFAIK. Non esiste un costruttore View che prenda un Map come terzo parametro. Ce n'è uno che prende uno int come terzo parametro, usato per sovrascrivere lo stile predefinito per il widget.

tendo a usare la sintassi this() di combinare questi:

public ColorMixer(Context context) { 
    this(context, null); 
} 

public ColorMixer(Context context, AttributeSet attrs) { 
    this(context, attrs, 0); 
} 

public ColorMixer(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    // real work here 
} 

Potete vedere il resto di questo codice nella this book example.

+7

super (context, attrs) e super (context, attrs, 0) funzionano in modo diverso per me. Il primo è ok, ma il secondo rimuove lo stile originale da una vista. È un bug nelle versioni più recenti di Android? – broot

+9

Sì, il mio approccio 'this()' aveva dei difetti. Basta fare una semplice catena alla superclasse (ad esempio, 'super (context, attrs)') e mettere una chiamata a un metodo comune privato (ad es., Init(); ') in ogni costruttore. Vedere https://github.com/commonsguy/cwac-colormixer/blob/master/src/com/commonsware/cwac/colormixer/ColorMixer.java per un esempio. – CommonsWare

+0

Sì, ho fatto esattamente la stessa cosa, ma ho chiamato questo (context, null) nel primo costruttore. Un difetto è che devi inizializzare i campi finali in entrambi i costruttori - non puoi farlo nel metodo init(). – broot

11

Ecco un mio modello di (creando qui un costume ViewGoup, ma ancora):

// CustomView.java 

public class CustomView extends LinearLayout { 

    public CustomView(Context context) { 
     super(context); 
     init(context); 
    } 

    public CustomView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(context); 
    } 

    public CustomView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     init(context); 
    } 

    private void init(Context ctx) { 
     LayoutInflater.from(ctx).inflate(R.layout.view_custom, this, true); 
      // extra init 
    } 

} 

e

// view_custom.xml 

<merge xmlns:android="http://schemas.android.com/apk/res/android"> 
    <!-- Views --> 
</merge> 
+0

Questo non è efficace come la soluzione @CommonsWare perché non consente di avere campi contrassegnati come 'finali', mentre l'uso di una catena di chiamate this() lo farà. – greg7gkb

+3

@ greg7gkb Tuttavia la soluzione @Commonsware è difettosa. Devi chiamare ogni super separato e usare un 'init()' – Blundell

+0

Non c'è bisogno di passare il Contesto a init(), puoi semplicemente chiamare getContext() – Ran

6

Quando si aggiunge la vostra abitudine View da xml come:

<com.mypack.MyView 
     ... 
     /> 

Avrete bisogno dei costruttore pubblicoMyView(Context context, AttributeSet attrs), altrimenti si otterrà un Exception quando Android cerca di inflate tuo View.

E quando si aggiunge il View da xml e anche specificare il android:styleattribute come:

<com.mypack.MyView 
     style="@styles/MyCustomStyle" 
     ... 
     /> 

sarà necessario anche il terzo costruttore pubblicoMyView(Context context, AttributeSet attrs,int defStyle).

Il terzo costruttore è di solito utilizzato quando si estende uno stile e personalizzare, e poi si desidera impostare che style a un dato View nei vostri layout

Modifica dettagli

public MyView(Context context, AttributeSet attrs) { 
      //Called by Android if <com.mypack.MyView/> is in layout xml file without style attribute. 
      //So we need to call MyView(Context context, AttributeSet attrs, int defStyle) 
      // with R.attr.customViewStyle. Thus R.attr.customViewStyle is default style for MyView. 
      this(context, attrs, R.attr.customViewStyle); 
    } 

See this

+0

Ho poche visualizzazioni personalizzate nello stesso layout. Come posso passare al costruttore un indice che indica quale delle viste personalizzate appartiene? – Zvi

+0

Dovresti leggere TypedArray e gli attributi styleable. http://stackoverflow.com/questions/11039829/how-to-pass-view-reference-to-android-custom-view – Nepster

+0

@Nepstar, ho letto quel post e non ho capito come risolverà il mio problema, perché Gli attributi stilizzabili, per quanto ho capito, sono definite proprietà statiche prima che l'app sia in esecuzione. Pertanto tutte le istanze dei miei componenti personalizzati otterranno gli stessi dati, mentre ho bisogno di un ID univoco per ciascuna di quelle in esecuzione. – Zvi

Problemi correlati