2010-12-01 4 views
61

J'essaie de créer une vue personnalisée qui remplacerait une certaine disposition que j'utilise à plusieurs endroits, mais j'ai du mal à le faire.Créer une vue personnalisée en gonflant une mise en page?

Fondamentalement, je veux remplacer:

<RelativeLayout 
android:id="@+id/dolphinLine" 
android:layout_width="fill_parent" 
android:layout_height="wrap_content" 
    android:layout_centerInParent="true" 
android:background="@drawable/background_box_light_blue" 
android:padding="10dip" 
android:layout_margin="10dip"> 
    <TextView 
    android:id="@+id/dolphinTitle" 
    android:layout_width="200dip" 
    android:layout_height="100dip" 
    android:layout_alignParentLeft="true" 
    android:layout_marginLeft="10dip" 
    android:text="@string/my_title" 
    android:textSize="30dip" 
    android:textStyle="bold" 
    android:textColor="#2E4C71" 
    android:gravity="center"/> 
    <Button 
    android:id="@+id/dolphinMinusButton" 
    android:layout_width="100dip" 
    android:layout_height="100dip" 
    android:layout_toRightOf="@+id/dolphinTitle" 
    android:layout_marginLeft="30dip" 
    android:text="@string/minus_button" 
    android:textSize="70dip" 
    android:textStyle="bold" 
    android:gravity="center" 
    android:layout_marginTop="1dip" 
    android:background="@drawable/button_blue_square_selector" 
    android:textColor="#FFFFFF" 
    android:onClick="onClick"/> 
    <TextView 
    android:id="@+id/dolphinValue" 
    android:layout_width="100dip" 
    android:layout_height="100dip" 
    android:layout_marginLeft="15dip" 
    android:background="@android:drawable/editbox_background" 
    android:layout_toRightOf="@+id/dolphinMinusButton" 
    android:text="0" 
    android:textColor="#2E4C71" 
    android:textSize="50dip" 
    android:gravity="center" 
    android:textStyle="bold" 
    android:inputType="none"/> 
    <Button 
    android:id="@+id/dolphinPlusButton" 
    android:layout_width="100dip" 
    android:layout_height="100dip" 
    android:layout_toRightOf="@+id/dolphinValue" 
    android:layout_marginLeft="15dip" 
    android:text="@string/plus_button" 
    android:textSize="70dip" 
    android:textStyle="bold" 
    android:gravity="center" 
    android:layout_marginTop="1dip" 
    android:background="@drawable/button_blue_square_selector" 
    android:textColor="#FFFFFF" 
    android:onClick="onClick"/> 
</RelativeLayout> 

Par ceci:

<view class="com.example.MyQuantityBox" 
    android:id="@+id/dolphinBox" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:myCustomAttribute="@string/my_title"/> 

Alors, je ne veux pas une mise en page personnalisée, je veux une vue personnalisée (il ne devrait pas être possible pour cette vue d'avoir un enfant).

La seule chose qui pourrait changer d'une instance d'un MyQuantityBox à un autre est le titre. J'aimerais beaucoup pouvoir spécifier ceci dans le XML (comme je le fais sur la dernière ligne XML)

Comment est-ce que je peux faire ceci? Devrais-je mettre le RelativeLayout dans un fichier XML dans/res/layout et le gonfler dans ma classe MyBoxQuantity? Si oui, comment puis-je le faire?

Merci!

+0

Voir "Contrôles composés" dans Android, et ce lien: http://stackoverflow.com/questions/1476371/android-writing-a-custom-compound-component – greg7gkb

Répondre

18

Oui, vous pouvez le faire. RelativeLayout, LinearLayout, etc. sont des vues afin qu'une mise en page personnalisée soit une vue personnalisée. Juste quelque chose à considérer parce que si vous vouliez créer une mise en page personnalisée, vous pourriez.

Ce que vous voulez faire est de créer un contrôle composé. Vous allez créer une sous-classe de RelativeLayout, ajouter tous vos composants dans le code (TextView, etc), et dans votre constructeur vous pouvez lire les attributs passés depuis le XML. Vous pouvez ensuite transmettre cet attribut à votre titre TextView.

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

10

Utilisez la mise en page gonfleur, comme je l'ai indiqué ci-dessous

public View myView(){ 
    View v; // Creating an instance for View Object 
    LayoutInflater inflater = (LayoutInflater)getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    v = inflater.inflate(R.layout.myview, null); 

    TextView text1 = (TextView) v.findViewById(R.id.dolphinTitle); 
    Button btn1 = (Button) v.findViewById(R.id.dolphinMinusButton); 
    TextView text2 = (TextView) v.findViewById(R.id. dolphinValue); 
    Button btn2 = (Button) v.findViewById(R.id. dolphinPlusButton); 


    return v; 
} 
+0

vôtre travaillé parfaitement. –

+0

J'ai essayé pareil. ça fonctionne bien.mais, quand je clique sur btn1, il appellera les services Web et après la réponse reçue du serveur, je veux mettre à jour le texte dans le texte particulier de position2..any pls d'aide? – harikrishnan

5

Dans la pratique, j'ai trouvé que vous devez être un peu prudent, surtout si vous utilisez à plusieurs reprises un peu de xml . Supposons, par exemple, que vous ayez une table dans laquelle vous souhaitez créer une ligne de table pour chaque entrée d'une liste. Vous avez mis en place un certain xml:

En my_table_row.xml:

<?xml version="1.0" encoding="utf-8"?> 
<TableRow xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" android:id="@+id/myTableRow"> 
    <ImageButton android:src="@android:drawable/ic_menu_delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/rowButton"/> 
    <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="TextView" android:id="@+id/rowText"></TextView> 
</TableRow> 

Alors, vous voulez créer une fois par ligne avec un code. Il suppose que vous avez défini un parent TableLayout myTable pour attacher les lignes à.

for (int i=0; i<numRows; i++) { 
    /* 
    * 1. Make the row and attach it to myTable. For some reason this doesn't seem 
    * to return the TableRow as you might expect from the xml, so you need to 
    * receive the View it returns and then find the TableRow and other items, as 
    * per step 2. 
    */ 
    LayoutInflater inflater = (LayoutInflater)getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    View v = inflater.inflate(R.layout.my_table_row, myTable, true); 

    // 2. Get all the things that we need to refer to to alter in any way. 
    TableRow tr  = (TableRow) v.findViewById(R.id.profileTableRow); 
    ImageButton rowButton = (ImageButton) v.findViewById(R.id.rowButton); 
    TextView rowText = (TextView) v.findViewById(R.id.rowText); 

    // 3. Configure them out as you need to 
    rowText.setText("Text for this row"); 
    rowButton.setId(i); // So that when it is clicked we know which one has been clicked! 
    rowButton.setOnClickListener(this); // See note below ...   

    /* 
    * To ensure that when finding views by id on the next time round this 
    * loop (or later) gie lots of spurious, unique, ids. 
    */ 
    rowText.setId(1000+i); 
    tr.setId(3000+i); 
} 

Pour un exemple simple et clair sur la manipulation rowButton.setOnClickListener (ce), voir Onclicklistener for a programatically created button.

+0

Bonjour Neil, j'ai essayé pareil. ça fonctionne bien. mais, quand je clique sur rowButton, il va appeler les services Web et après la réponse reçue du serveur, je veux mettre à jour du texte dans la position particulière rowText..any pls d'aide? – harikrishnan

+0

voir aussi ma question. https://stackoverflow.com/questions/48719970/android-adding-view-from-inflate-layout-and-how-to-update-particular-textview-va – harikrishnan

75

Un peu vieux, mais je pensais que le partage de la façon dont je le ferais, basé sur la réponse de chubbsondubs: J'utilise FrameLayout (voir Documentation), car il est utilisé pour contenir une seule vue, et gonfler en elle la vue du xml.

code suivant:

public class MyView extends FrameLayout { 
    public MyView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     initView(); 
    } 

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

    public MyView(Context context) { 
     super(context); 
     initView(); 
    } 

    private void initView() { 
     View view = inflate(getContext(), R.layout.my_view_layout, null); 
     addView(view); 
    } 
} 
+4

Puisque la classe View a une méthode statique gonfler(), il n'y a pas de besoin de LayoutInflater.from() – outlying

+0

merci périphérie, j'ai modifié le code avec votre commentaire –

+1

N'est-ce pas juste la solution de Johannes à partir d'ici: http://stackoverflow.com/questions/17836695/android-custom-view -from-inflated-layout Encore, cela gonfle une autre disposition à l'intérieur. Donc ce n'est pas vraiment la meilleure solution que j'aurais imaginé. –

Questions connexes