簡體   English   中英

Android:如何在自定義適配器中設置偵聽器並獲取圖像按鈕單擊的位置

[英]Android : how to set listener and get position of imagebutton click in a custom adapter

在我的活動中,我的布局是一個列表視圖,包含復雜的行項。 所以我寫了一個自定義ArrayAdapter的類。 從我的活動,我調用我的ArrayAdapter,我試圖設置監聽器並獲取圖像按鈕單擊的位置,但它不起作用。 位置未設置為正確的值,因為它是android需要顯示屏幕的最后一個視圖的位置。但是我如何才能獲得已單擊的行的正確位置? 我的意思是,例如,如果我在listView中有10行,並且我單擊行項目5,我想要的用於吐司的信息是用戶編號5的名稱,但是吐司顯示位置編號10的行的用戶名。請幫忙我找不到解決方案! 謝謝 !

這是我的arrayadpater的代碼:

public class AudioListAdapter extends ArrayAdapter<DonneesListeAudio>  {

// Variables
private Activity activity;
private ArrayList<DonneesListeAudio> DataOfListView;
private static LayoutInflater Inflater = null;
int classPosition=0;

//Constructeur
public AudioListAdapter(Activity activity, int textViewResourceId, ArrayList<DonneesListeAudio> _Liste) {
     super(activity, textViewResourceId, _Liste);
    try {
        this.activity = activity;
        this.DataOfListView = _Liste;
        Inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    } catch (Exception e) {
    }
}

//construction de la vue de l'item
public View getView(int position, View convertView, ViewGroup parent) {
    classPosition = position;
    View ItemView = convertView;
    ViewWrapper Holder;
    try {
        if (convertView == null) {
            ItemView = Inflater.inflate(R.layout.row_liste_audio, null);  /* création de la vue */

            Holder = new ViewWrapper(ItemView);                           /* création d'une instance de wrapper pour conservation des objets de la vue ( textview etc .. )dans le tag de la vue  */

            //  >>>>>>>>>>>>>>>   HERE WAS MY LISTENER BEFORE HASSAN ANSWER
            ImageButton MyImageButton = (ImageButton) Holder.getBase().findViewById(R.drawable.ic_playvert);        /* listner 1 */
            MyImageButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast ToastCourt = Toast.makeText(getContext(), DataOfListView.get(classPosition).getPseudoUser(), Toast.LENGTH_SHORT);
                    ToastCourt.show();
                }
            });
            ItemView.setTag(Holder);                                      /* sauvegarde du Wrapper de nom Holder dans le tag de la vue crée*/
        } else {
            Holder = (ViewWrapper) ItemView.getTag();                     /* récupération des objets de la vue ( textview etc .. ) via le Wrapper stocké dans le tag */
        }
        chargementDesDonneesDeItem(Holder, position);                     /* chargement des données provenants de MyApplication dans le Wrapper de nom Holder */
    } catch (Exception e) {
    }
    return ItemView;
}

這是我的listactivity,它調用我的arrayadapter名稱AudioListAdapter

@Override
public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    requestWindowFeature(Window.FEATURE_NO_TITLE);    /* suppresion barre de titre */
    setContentView(R.layout.activity_audio);

    //footer (pied de page) de la listView ( à appeler avant l'adapteur )
    View footer = getLayoutInflater().inflate(R.layout.footer, null);
    ListView listView = getListView();
    listView.addFooterView(footer);

    //chargement des données de la premeire page de la listview via LA thread
    chargeListe(0, "PremierePage", "aucun");
    setListAdapter(new AudioListAdapter(this, 0, MyApplication.getMyArrayDonneesListeAudio()));

解釋:這是我使用Hassan解決方案修改的arrayadapter代碼(在IF語句之外移動setlistener)和Rick Falck的解決方案(將位置保存在imageview的標記中)。 它的工作原理! 非常感謝 ! (見下面代碼中的評論)

public View getView(int position, View convertView, ViewGroup parent) {
    classPosition = position;
    View ItemView=convertView;

    try {
        if (convertView == null) {
            convertView = Inflater.inflate(R.layout.row_liste_audio, null);  /* création de la vue */

            Holder = new ViewWrapper(convertView);                           /* création d'une instance de wrapper pour conservation des objets de la vue ( textview etc .. )dans le tag de la vue  */

            convertView.setTag(Holder);                                      /* sauvegarde du Wrapper de nom Holder dans le tag de la vue crée*/

        } else {

            Holder = (ViewWrapper) convertView.getTag();                     /* récupération des objets de la vue ( textview etc .. ) via le Wrapper stocké dans le tag */


        };


        chargementDesDonneesDeItem(Holder, position);                        /* chargement des données provenants de MyApplication dans le Wrapper de nom Holder */


        ImageView MyImageView = (ImageView)convertView.findViewById(R.id.image_media_play);     /* get instance of the button */
        PositionObject TagPosition = new PositionObject();                                      /* create a new object for tag ( just save position as an INT */
        TagPosition.setPosition(classPosition);                                                 /* set position in the object for tag */
        MyImageView.setTag(TagPosition);                                                        /* save tag with position  */
        MyImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {                                              /* set the listener here to be sure that listener exist even when items convertview are recycled  */
                int idx;
                PositionObject MyPosition = (PositionObject) view.getTag();                     /* get the tag of the view that was click */
                idx=MyPosition.getPosition();                                                   /* get the position of the view in the listitem ! */
                Toast ToastCourt = Toast.makeText(getContext(), DataOfListView.get(idx).getPseudoUser(), Toast.LENGTH_SHORT);
                ToastCourt.show();


            }
        });




    } catch (Exception e) {
            e.getCause();
            e.getLocalizedMessage();
            e.toString();
            e.printStackTrace();


    }
    return convertView;
}

只需從if語句范圍和else范圍之后取出以下內容即可。

你需要每次都這樣做:

final int positionForListener = position;
ImageButton MyImageButton = (ImageButton) Holder.getBase().findViewById(R.drawable.ic_playvert);        /* listner 1 */
            MyImageButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast ToastCourt = Toast.makeText(getContext(), DataOfListView.get(classPosition).getPseudoUser(), Toast.LENGTH_SHORT);
                    ToastCourt.show();
                    Log.i("position", ""+positionForListener);
                }
            });

基於這種邏輯,您需要重新考慮其他代碼行以及設置它們的位置。 但是,現在這解決了你的問題。

這也有效。 為偵聽器定義最終位置var,然后在偵聽器中使用它。

問題是View.OnClickListener是AudioListAdapter的內部類。 適配器在需要繪制項時調用getView()方法。 它將具有要繪制的項目的位置。

單擊ImageView時將調用onClick()方法。 那時,外部類中的數據將代表最后繪制的項目,而不是單擊的項目。 因此,classPosition將是最后繪制的項目,即#10。

傳遞給onClick()的視圖是ImageView本身。 你需要弄清楚它屬於哪個項目。 我唯一能想到的是將項目的位置放入ImageView.Tag(ImageView.setTag())。 然后在onClick()中獲取位置(ImageView.getTag())。

然后,您可以在該位置調用getItem(posFromTag)以獲取DataOfListView中的項目。 從那里,您可以獲得所需的其他信息。

設置要回收的視圖時,請勿設置偵聽器。 當它被回收時,聽眾也會如此,並且它將具有與之相關的錯誤位置。

各種潛在解決方案

  • 不要回收視圖。 效率較低,但如果每次都對新視圖進行充氣和填充,則回收的回收視圖中的數據不會出現問題。
  • 使用AdapterView.setOnItemClickListener而不是按鈕。 整個列表項是可點擊的而不僅僅是按鈕,並且自動處理正確的位置。
  • 將偵聽器設置為設置循環視圖的一部分,而不是新視圖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM