单击列表视图中自定义单元格中按钮的侦听器

Posted

技术标签:

【中文标题】单击列表视图中自定义单元格中按钮的侦听器【英文标题】:Click listener for a button in a customised cell in a list view 【发布时间】:2021-01-02 17:40:43 【问题描述】:

我为我的 android 应用创建了一个自定义列表视图,以便为每个单元格添加一个删除按钮,使用户能够从列表中删除行。自定义列表视图运行良好,但是当我为按钮添加单击侦听器时,列表视图显示空单元格,而不是填充来自数组的数据。 这是getView的代码:

public View getView(final int position, View convertView, ViewGroup parent) 
        LayoutInflater inflater = getLayoutInflater();
        View row = inflater.inflate(R.layout.row, parent, false);
        Button deleteButt = (Button) row.findViewById(R.id.deleteButton);
        deleteButt.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                Toast.makeText(getActivity(), "delete me", Toast.LENGTH_SHORT).show();
            
        );
        return row;
    

我认为我应该返回其他东西而不是行,但我不知道要返回什么。当我考虑返回行时,它应该显示填充了数据的行。请注意,当我删除这段代码时,列表视图可以很好地显示数据。

这是适配器类的全部代码

// Our adapter class
class MyAdapter extends ArrayAdapter<String> 
    Context context;
    String rNames[];


    MyAdapter(Context c, String name[]) 
        super(c, R.layout.row, R.id.customerName, name);
        this.context = c;
        this.rNames = name;

    

    public View getView(final int position, View convertView, ViewGroup parent) 
        LayoutInflater inflater = getLayoutInflater();
        View row = inflater.inflate(R.layout.row, parent, false);
        Button deleteButt = (Button) row.findViewById(R.id.deleteButton);
        deleteButt.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                Toast.makeText(getActivity(), "delete me", Toast.LENGTH_SHORT).show();
            
        );
        return row;
    
    

这是首页片段页面的全部代码

public class HomeFragment extends Fragment 

    // creating an empty array. This is an array of objects (array of arrays).
    final ArrayList<String[]> mainObjectsArray = new ArrayList<String[]>();
    //final String[][] myFamily = new String[][];

    // creating another array of the titles. If our main array is an array of strings we will not need this.
    // Why?. ArrayAdapter doesn't accept an array of arrays it only accepts an array of Stings, so we had to create a special array for the titles and bring them from our main array.
    final ArrayList<String> theNames = new ArrayList<String>();

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) 
        final View rootView =  inflater.inflate(R.layout.fragment_home, null);


        // creaing a list view and connect it to the list view we created in the XML file
        // Note: we need to add (final) to be able to access them from inside the loop
        final ListView myListView = (ListView) rootView.findViewById(R.id.myListView);


        // Retrieving the data and filling the array with it
        ParseQuery<ParseObject> query = ParseQuery.getQuery("Orders");
        query.orderByDescending("updatedAt");
        query.findInBackground(new FindCallback<ParseObject>() 
            @Override
            public void done(List<ParseObject> objects, ParseException e) 
                if (e == null) 
                    //Log.i("findInBackground", "Retrieved: " + objects.size() + "objects");
                    if (objects.size() > 0) 
                        for (ParseObject object: objects) 

                            // Converting every object to an array of two itmes, title and body.
                            String[] artical = object.getString("TheSavedOrder"), object.getString("mobileNumber"), object.getString("Name");

                            // Adding the array to our main array so we will have an array of arrays
                            mainObjectsArray.add(artical);

                            //Log.i("This my family array: ", myFamily.toString());

                        

                        // We will add only the names to the array (theNames). theTitles will be an array of strings so we can populate it in the list view.
                        for (int i = 0; i < mainObjectsArray.size(); i++)
                            theNames.add(mainObjectsArray.get(i)[2]);
                            //Log.i("Here are teh title: ", myFamily.get(i)[0]);
                            Log.i("Here is thti: ", theNames.get(i));
                        


                        // Converting theNames from ArrayList to an array
                        String[] namesArray = new String[theNames.size()];
                        namesArray = theNames.toArray(namesArray);

                        // Applaying our adapter
                        MyAdapter adapter = new MyAdapter(getActivity(), namesArray);
                        myListView.setAdapter(adapter);

                    
                
            
        );

        // When clicking on an item in the list view
        myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() 
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
                //Log.i("The body is: ", mainObjectsArray.get(position));
                Intent intent = new Intent(getContext(), TheBody.class);
                intent.putExtra("mobile", mainObjectsArray.get(position)[1]);  // mainObjectsArray.get(position)[1] means we will pass the second item in every array which is the (mobileNumber).
                intent.putExtra("order", mainObjectsArray.get(position)[0]);
                startActivity(intent);
            
        );

        return rootView;

    


    // Our adapter class
    class MyAdapter extends ArrayAdapter<String> 
        Context context;
        String rNames[];


        MyAdapter(Context c, String name[]) 
            super(c, R.layout.row, R.id.customerName, name);
            this.context = c;
            this.rNames = name;

        

        public View getView(final int position, View convertView, ViewGroup parent) 
            LayoutInflater inflater = getLayoutInflater();
            View row = inflater.inflate(R.layout.row, parent, false);
            Button deleteButt = (Button) row.findViewById(R.id.deleteButton);
            deleteButt.setOnClickListener(new View.OnClickListener() 
                @Override
                public void onClick(View view) 
                    Toast.makeText(getActivity(), "delete me", Toast.LENGTH_SHORT).show();
                
            );
            return row;
        
        
    



这是片段的 XML 代码

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_>


    <ListView
        android:id="@+id/myListView"
        android:layout_
        android:layout_ />
</LinearLayout>

最后这是自定义单元格的 XML 代码

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:orientation="horizontal"
    android:padding="16dp"
    android:descendantFocusability="blocksDescendants">


    <TextView
        android:id="@+id/customerName"
        android:layout_
        android:layout_
        android:text="custoemr name"
        android:textColor="#000"
        android:layout_margin="5dp"
        android:textSize="20sp"/>
    <Button
        android:id="@+id/deleteButton"
        android:layout_
        android:layout_
        android:text="Delete"


    />

</LinearLayout>

请帮助我已经为此苦苦挣扎了几天! 非常感谢。

【问题讨论】:

【参考方案1】:
    public View getView(final int position, View convertView, ViewGroup parent) {
       View row = super.getView(position, convertView, parent);
       Button deleteButt = (Button) row.findViewById(R.id.deleteButton); 
       deleteButt.setOnClickListener(new View.OnClickListener()  
            @Override 
             public void onClick(View view)  
                   Toast.makeText(getActivity(), "delete me", Toast.LENGTH_SHORT).show();
          );
         return row; 
    

还请注意,您的列表 rNames 是一个固定大小的数组 [],不能删除单个项目。如果你想实现删除功能,你应该使用ArrayList。

更新:

public class HomeFragment extends Fragment 

// creating an empty array. This is an array of objects (array of arrays).
ArrayList<MainObjects> mainObjectsList = new ArrayList<>();
ListView myListView;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) 
    View rootView = inflater.inflate(R.layout.fragment_home, null);

    // creaing a list view and connect it to the list view we created in the XML file
    // Note: we need to add (final) to be able to access them from inside the loop
    myListView = (ListView) rootView.findViewById(R.id.myListView);

    // Retrieving the data and filling the array with it
    ParseQuery<ParseObject> query = ParseQuery.getQuery("Orders");
    query.orderByDescending("updatedAt");
    query.findInBackground(new FindCallback<ParseObject>() 
        @Override
        public void done(List<ParseObject> objects, ParseException e) 
            if (e == null) 
                //Log.i("findInBackground", "Retrieved: " + objects.size() + "objects");
                if (objects.size() > 0) 
                    for (ParseObject object : objects) 
                        // Converting every object to an array of two items, title and body.
                        //String[] artical = object.getString("TheSavedOrder"), object.getString("mobileNumber"), object.getString("Name");
                        MainObjects article = new MainObjects(object.getString("TheSavedOrder"), object.getString("mobileNumber"), object.getString("Name");
                        // Adding the array to our main array so we will have an array of arrays
                        mainObjectsList.add(article);

                        //Log.i("This my family array: ", myFamily.toString());
                    
                    // Applying our adapter
                    MyAdapter adapter = new MyAdapter(getActivity(), mainObjectsList);
                    myListView.setAdapter(adapter);
                
            
        
    );

    // When clicking on an item in the list view
    myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() 
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
            //Log.i("The body is: ", mainObjectsList.get(position));
            Intent intent = new Intent(getContext(), TheBody.class);
            intent.putExtra("mobile", mainObjectsList.get(position).getMobileNumber());
            intent.putExtra("order", mainObjectsList.get(position).getSavedOrder());
            startActivity(intent);
        
    );
    return rootView;


class MainObjects 
    String savedOrder = "", mobileNumber = "", name = "";

    public MainObjects(String savedOrder, String mobileNumber, String name) 
        this.savedOrder = savedOrder;
        this.mobileNumber = mobileNumber;
        this.name = name;
    

    public String getSavedOrder() 
        return savedOrder;
    

    public String getMobileNumber() 
        return mobileNumber;
    

    public String getName() 
        return name;
    


class MyAdapter extends ArrayAdapter<MainObjects> 
    Context context;
    LayoutInflater inflater;
    ArrayList<MainObjects> rNames;

    MyAdapter(Context c, ArrayList<MainObjects> name) 
        super(c, R.layout.row, R.id.customerName, name);
        this.context = c;
        this.rNames = name;
        inflater = getLayoutInflater();
    

    public View getView(int position, View convertView, ViewGroup parent) 
        View row = inflater.inflate(R.layout.row, parent, false);

        TextView nameTv = (TextView) row.findViewById(R.id.customerName);
        nameTv.setText(getItem(position).getName());

        Button deleteButt = (Button) row.findViewById(R.id.deleteButton);
        deleteButt.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                int pos = (int)view.getTag();
                String msg = "Delete: " + pos + ". " + getItem(pos).getName() + " !!";
                Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
                rNames.remove(pos);
                notifyDataSetChanged();
                //
                // Codes to update permanent storage, e.g. files/server/db.
                //
             );
        deleteButt.setTag(position);
        return row;
    



【讨论】:

以上是关于单击列表视图中自定义单元格中按钮的侦听器的主要内容,如果未能解决你的问题,请参考以下文章

如何为自定义表格视图单元格中的按钮单击获取不同的视图控制器

片段内 Listview 中动态视图的 onClick 侦听器

IOS/Objective-C:检测自定义表格视图单元格中的按钮按下?

在我的自定义列表项中单击书签图像的侦听器,多次更改另一个 row_item 图像

如何在自定义适配器上实现 onClickListener?

如何验证按钮单击侦听器上的视图可见性