2017-08-09 2 views
0

Je reviens à Android après un long moment et je suis un peu coincé avec un problème.
L'application consiste en une liste de mises en page, chacune étant soutenue par un modèle via l'adaptateur.
Chaque mise en page a plusieurs vues, l'une d'entre elles étant un spinner.
Je veux modifier les données dans l'adaptateur lorsque vous modifiez la valeur du Spinner, mais je ne sais pas comment référencer l'objet dans l'adaptateur.Comment accéder à un objet adaptateur à partir d'une vue dans le ListView

public class MainActivity extends AppCompatActivity { 
    ArrayList<Troop> values = new ArrayList<Troop>(); 
    MySimpleArrayAdapter adapter; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     values.add(new Troop()); 

     final ListView listView =(ListView) findViewById(R.id.listview); 

     adapter = new MySimpleArrayAdapter(
       this, 
       values); 
     listView.setAdapter(adapter); 
    } 

    public class Troop { 
     private String weapon; 
     private int bs; 
     private int total_modifier; 

     public Troop() { 

     } 

     public int getBs() { 
      return bs; 
     } 

     public void setBs(int bs) { 
      this.bs = bs; 
     } 
    } 

    public class MySimpleArrayAdapter extends ArrayAdapter { 
     private final Context context; 
     private ArrayList<Troop> troopers; 
     private String[] possible_bs = new String[] {"10", "11", "12", "13", "15", "16"}; 

     public MySimpleArrayAdapter(Context context, ArrayList<Troop> values) { 
      super(context, -1, values); 
      this.context = context; 
      this.troopers = values; 
     } 

     @Override 
     public View getView(int position, View convertView, ViewGroup parent) { 
       LayoutInflater inflater = (LayoutInflater) context 
         .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
       View rowView = inflater.inflate(R.layout.rowlayout, parent, false); 

       Spinner bs_spinner = rowView.findViewById(R.id.bs_spinner); 
       ArrayAdapter<String> bs_adapter = new ArrayAdapter<String>(
         context, 
         android.R.layout.simple_spinner_dropdown_item, 
         possible_bs); 
       bs_spinner.setOnItemSelectedListener(new CustomOnItemSelectedListener()); 
       bs_spinner.setAdapter(bs_adapter); 
      return rowView; 
     } 

    } 

    public class CustomOnItemSelectedListener implements AdapterView.OnItemSelectedListener { 

     public void onItemSelected(AdapterView<?> parent, View view, int pos,long id) { 
     // I want to call getBs on the Trooper correspoding to this view here 
     } 

     @Override 
     public void onNothingSelected(AdapterView<?> arg0) { 
      // TODO Auto-generated method stub 
     } 

    } 
} 
+0

Vous devez '' étend ArrayAdapter

+0

Merci pour votre réponse. La question est, comment accéder à l'adaptateur à partir de la méthode onItemSelected? –

+0

C'est un commentaire, pas une réponse;) Quel adaptateur? –

Répondre

0

Il y a beaucoup de choses qui se passent ici. Parlons d'abord de votre sous-classe ArrayAdapter.

Comme mentionné dans un commentaire sur votre question, vous devriez le changer en extends ArrayAdapter<Troop>. Cela entraînera getItem() pour retourner Troop au lieu de Object. Vous n'avez pas besoin de stocker vos propres champs context ou troopers. L'implémentation de base ArrayAdapter stocke un contexte dans le champ mContext et vous pouvez y accéder via getContext(). En outre, il stocke les données de sauvegarde dans le champ mObjects et vous pouvez y accéder via getItem().

Enfin, si tous les éléments de votre carte partagent la même valeur possible_bs, vous devriez en faire une constante.

Ensuite, parlons du AdapterView.OnItemSelectedListener.

Vous avez besoin d'un moyen de savoir quelle position (de votre MySimpleArrayAdapter) votre Spinner vit dans (par opposition à la position de l'élément à l'intérieur l'Spinner l'utilisateur a sélectionné). Je recommande de passer cette position dans un constructeur et de l'enregistrer comme un champ final privé.

Pour obtenir à l'adaptateur à l'intérieur du Spinner, vous pouvez accéder au Adapter sauvegarde l'argument AdapterView en appelant parent.getAdapter(), puis le jeter à votre type désiré.

Tous ensemble, vous vous retrouvez avec ceci:

public static class MySimpleArrayAdapter extends ArrayAdapter { 

    private static final String[] POSSIBLE_BS = new String[] {"10", "11", "12", "13", "15", "16"}; 

    public MySimpleArrayAdapter(Context context, ArrayList<Troop> values) { 
     super(context, -1, values); 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     LayoutInflater inflater = (LayoutInflater) getContext() 
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     View rowView = inflater.inflate(R.layout.rowlayout, parent, false); 

     Spinner bs_spinner = rowView.findViewById(R.id.bs_spinner); 
     ArrayAdapter<String> bs_adapter = new ArrayAdapter<>(
       getContext(), 
       android.R.layout.simple_spinner_dropdown_item, 
       POSSIBLE_BS); 
     bs_spinner.setOnItemSelectedListener(new CustomOnItemSelectedListener(position)); 
     bs_spinner.setAdapter(bs_adapter); 
     return rowView; 
    } 

} 

private static class CustomOnItemSelectedListener implements AdapterView.OnItemSelectedListener { 

    private final int troopPosition; 

    private CustomOnItemSelectedListener(int troopPosition) { 
     this.troopPosition = troopPosition; 
    } 

    @Override 
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 
     MySimpleArrayAdapter adapter = (MySimpleArrayAdapter) parent.getAdapter(); 
     int bs = adapter.getItem(troopPosition).getBs(); 
    } 

    @Override 
    public void onNothingSelected(AdapterView<?> parent) { 

    } 
} 
+0

Le paramètre position ne serait-il pas la position de l'élément sélectionné sur le spinner au lieu de la position de l'élément dans la vue de liste? –

+0

Oui, le paramètre 'position' de' onItemSelected() 'est la position de l'élément sélectionné dans' Spinner'. C'est pourquoi vous devez passer 'troopPosition' à' OnItemSelectedListener' et l'utiliser à la place. –

0

Vous pouvez déplacer dans la classe anonyme.

Vous souhaitez obtenir les deux éléments de position si vous souhaitez l'élément ListView actuel ainsi que la position de l'adaptateur interne.

Il y a probablement des moyens propres à faire, mais il est la première idée que j'avais

public class MySimpleArrayAdapter extends ArrayAdapter<Troop> { 
    private final Context context; 
    private ArrayList<Troop> troopers; 
    private String[] possible_bs = new String[] {"10", "11", "12", "13", "15", "16"}; 

    @Override 
    public View getView(final int position, View convertView, ViewGroup parent) { 
      LayoutInflater inflater = (LayoutInflater) context 
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      View rowView = inflater.inflate(R.layout.rowlayout, parent, false); 
      Spinner bs_spinner = rowView.findViewById(R.id.bs_spinner); 

      final ArrayAdapter<String> bs_adapter = new ArrayAdapter<String>(
        context, 
        android.R.layout.simple_spinner_dropdown_item, 
        possible_bs); 
      bs_spinner.setAdapter(bs_adapter); 

      bs_spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 

       @Override 
       public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { 
        // You can access MySimpleArrayAdapter.this or bs_adapter 
        Troop t = troopers.get(position); // or getItem(position); 
        String bs = possible_bs[pos]; 
       } 

       @Override 
       public void onNothingSelected(AdapterView<?> arg0) { 
        // TODO Auto-generated method stub 
       } 

      }); 

     return rowView; 
    }