2011-09-06 2 views
2

J'ai une application super TestUI. Il a un gridview avec des boutons en eux.La meilleure façon de passer un boutonCliquez sur l'activité principale?

Je veux que le mot du bouton clique pour être passé à l'activité principale, afin qu'il puisse mettre à jour son état.

Malheureusement les boutons volent les clics. Ainsi, le typique:

 gridview.setOnItemClickListener(new OnItemClickListener() { 
      public void onItemClick(AdapterView<?> parent, View v, int position, long id) { 
       Toast.makeText(TestUI.this, "" + position, Toast.LENGTH_SHORT).show(); 
      } 
     }); 

Ne reçoit pas d'appel.

lieu dans la définition de l'adaptateur:

public View getView(int position, View convertView, ViewGroup parent) { 

    Button gridItem; 

    if (convertView == null) { // if it's not recycled, initialize some attributes 
     gridItem = new Button(mContext); 
    } else { 
     gridItem = (Button) convertView; 
    } 
    gridItem.setText("button " + String.valueOf(position)); 
    gridItem.setClickable(true); 
    gridItem.setFocusable(false); 
    gridItem.setOnClickListener(new MyOnClickListener(position, mContext)); 

    return gridItem; 

Ce qui est soutenu avec une MyOnClickListener de classe qui implémente l'interface OnClickListener. Cependant, si je le fais de cette façon, j'ai encore besoin d'un rappel à l'activité principale, d'une certaine manière, il doit savoir que quelque chose a été fait car il contrôle l'état du programme.

Alors, quelle est la meilleure façon de mettre à jour l'état de la classe/activités "root" à partir d'un clic sur un bouton?

Je sais que c'est une question de base OO mais je écris surtout en ASM et C donc je ne sais pas franchement.

Répondre

0

Comme vous l'avez dit, votre méthode getView se trouve dans la classe de l'adaptateur. Mais l'adaptateur obtient une copie du "contexte" auquel votre méthode getView a accès. Le contexte est une super classe de toutes les activités et services. Grâce à cet objet, vous pouvez effectuer de nombreuses opérations de base d'une activité. D'après votre exemple, je comprends que vous aimeriez montrer un toast. Cela peut être fait en utilisant

public View getView(int position, View convertView, ViewGroup parent) { 
    //usual getView stuff goes first 

    gridItem.setOnClickListener(new OnClickListener(){ 
     public onClick(View v){ 
      Toast.makeText(mContext, "" + position, Toast.LENGTH_SHORT).show(); 
     } 
    } 
} 

Donc en bref, votre classe MyOnClickListener doit utiliser la variable mContext pour interagir avec l'activité racine.

Modifier J'ai réalisé que j'ai fait une erreur dans la réponse ci-dessus. J'ai regardé l'échantillon sur http://developer.android.com/resources/tutorials/views/hello-gridview.html et j'ai réalisé que vous n'êtes pas limité à l'utilisation de Context. Vous pouvez utiliser quelque chose comme

public class MyActivity extends Activity { 
    public int a = 0; 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     GridView gridview = (GridView) findViewById(R.id.gridview); 
     gridview.setAdapter(new ImageAdapter(this)); 
    } 
} 

public class ImageAdapter extends BaseAdapter { 
    private MyActivity myAct; 
    public ImageAdapter(MyActivity c) { 
     myAct= c; 
    } 
    public View getView(int position, View convertView, ViewGroup parent) { 
     //usual getView stuff goes first 

     gridItem.setOnClickListener(new OnClickListener(){ 
      public onClick(View v){ 
       myAct.a = position; 
      } 
     } 
    } 
} 

Espérons que c'est ce que vous vouliez faire.

+0

Je peux faire Toast c'est bien. Je l'ai fait exactement comme tu le dis. Je veux définir une variable publique dans l'activité principale. Dites-le public void setFlagVar (int leFlag) {this.privateFlag = theFlag} – Brian

+0

Est-ce que je veux appeler une méthode publique dans l'activité principale? Je ne peux pas, sauf si elle est statique. Ok, d'accord. Il y a des "Handlers" mais un tel mécanisme est extrêmement complexe pour tout ce que je veux faire. Si les boutons sont textViews je peux le faire de la première façon sans couche sur couche de classes et de rappels ... Ou je peux juste abandonner Gridview et utiliser LinearLayout + Scroll + quelques vecteurs pour contenir les boutons ... Cependant Pour indiquer clairement le problème, vous avez une activité principale, elle crée un GridView de boutons, vous voulez que le bouton clique pour changer une variable locale dans l'activité principale ou sinon envoyer un rappel. – Brian

+0

Merci! Je n'ai pas réalisé à partir de l'exemple que je pouvais passer autre chose que le contexte! Je regardais cet exemple ... Je pense que tout va bien avec le monde ... Je peux rappeler n'importe quelle fonction publique dans l'objet principal en la passant comme vous l'avez fait, c'est tout ce que je voulais. – Brian

1

Pourquoi avez-vous besoin de 2 onClickListeners. De la onItemClickListener vous avez à l'activité principale ne pouvez-vous faire tout le travail que vous devez faire? Est-il nécessaire que l'adaptateur effectue le travail MyOnClickListener?

Vous pouvez définir gridItem.setOnClickListener à partir de l'activité principale. Pas besoin de créer un nouvel objet ListenerObject à chaque fois.

Vous avez juste besoin d'un xml pour gonfler à getView contenant un bouton

<Button android:text="Handle me" 
    android:id="@+id/btnHandleMe" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:onClick="buttonHandler" 
    android:clickable="true"> 

et de créer cette fonction à votre activité.

public void buttonHandler(View v) { 
     // Do your stuff here that new MyOnClickListener(position, mContext) whould do. 
    } 

Vous pouvez obtenir la position de la ligne/colonne que ce bouton est renseigné dans la liste/grille en ajoutant une balise à l'adaptateur.

En getView ajouter

gridItem.setTag(position) 

et pour récupérer à partir buttonHandler

if(v.getTag instance of Integer) 
int position = (Integer)v.getTag(); 

Alors maintenant, vous gérez tous les clics de l'activité et par défaut l'activité est notifiée.

+0

Je suis désolé de ne pas le suivre entièrement. La raison pour laquelle il y a deux gestionnaires de clics dans le message ci-dessus est parce que la première façon ne fonctionne pas ... En ce qui concerne gonfler avec un fichier XML, je pense que c'est hors limites ... C'est une interface générée par programme qu'il obtient hors de Bluetooth à partir d'un système distant ... Pas besoin d'y aller, mais le nombre d'objets est inconnu à l'exécution. Comme écrit avec des boutons dans une grilleView onItemClickListener n'est pas appelé parce que le bouton écoute le clic et l'absorbe. – Brian

+0

alors je voudrais créer un eventListener personnalisé que je lie à la gridView et a tiré sur le bouton clic. http://tseng-blog.nge-web.net/blog/2009/02/17/how-implement-your-own-listener-android-java/. Vous avez dit la "bonne façon". Le moyen rapide serait d'appeler une fonction personnalisée de l'activité de l'adaptateur, mais alors vous devez utiliser statique ou passer toute l'activité de l'adaptateur, ce qui n'est pas la bonne technique. S'il n'y a pas d'autres suggestions par moi ou un autre aller avec la méthode "Créer votre propre eventlistener" – weakwire

+0

Merci. Je suis sûr que cela pourrait fonctionner. J'espère qu'il existe une solution encore robuste mais moins complexe. J'utiliserai probablement LinearLayout + Buttons directement pour le moment à moins que quelqu'un ne me donne un meilleur moyen d'utiliser le gridView comme un conteneur pour les boutons avec Callback ... Il y a beaucoup de posts sur ListView et les boutons FWIW. Je n'ai pas encore trouvé de solution. – Brian

Questions connexes