Search code examples
javaandroidlistviewadapteronitemclicklistener

Alertdialog with a custom listview - click event is not triggered


My goal is to create an alertdialog displaying a list of choices, each one of them represented by an image and a text. The user is supposed to make a choice in the alertdialog and validate it. I have decided to build this alertdialog with a custom ListView inside it. So far, no problem but I can’t find a way to do the selection. I want to create a click event or check boxes but none of these of options seems to work. The most elegant way for me is the click event on a specific row of the list view and here is my code. For now, if I click, it doesn’t do anything. Your help is much appreciated.

MainActivity

    public class MainActivity extends AppCompatActivity implements 
    View.OnClickListener{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button b1 = (Button) this.findViewById(R.id.button);
        b1.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        LayoutInflater inflater = 
    (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View row = inflater.inflate(R.layout.row_item,null);

        ListView LV = (ListView)row.findViewById(R.id.Listview_card);

        Resources res = getApplicationContext().getResources();
        String[] names = res.getStringArray(R.array.image_name);
        int[] images =
    {R.drawable.image01,R.drawable.image02,R.drawable.image03,  
    R.drawable.image04};

        ArrayList<singleRow> array_list = new ArrayList<>();

        for (int i = 0; i < names.length; i++){
            array_list.add(new singleRow(names[i],images[i]));
        }

        CustomAdapter adapter = new CustomAdapter(getApplicationContext(), 
    array_list);
        LV.setAdapter(adapter);
        LV.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                                      @Override
                                      public void onItemClick(AdapterView<?> 
    parent, View view, int position, long id) {
                                         Toast.makeText(getApplicationContext(), 
    "coucou2", Toast.LENGTH_SHORT);
                                      }
                                  });

        builder.setView(row);
        builder.setPositiveButton("Validate Choice",new 
    DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {

            Toast.makeText(getApplicationContext(),"coucou3",Toast.LENGTH_LONG);
            }
        });

        AlertDialog dialog = builder.create();

        dialog.show();
    }}

activity_main xml
    <android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.replics.customlist.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        tools:layout_editor_absoluteX="49dp"
        tools:layout_editor_absoluteY="44dp" /
    </android.support.constraint.ConstraintLayout>

CustomAdapter
    public class CustomAdapter extends BaseAdapter {

    private Context mContext;
    private ArrayList<singleRow> array_list;

    CustomAdapter(Context mContext, ArrayList<singleRow> List_Sent) {
        this.mContext = mContext;
        this.array_list = List_Sent;
    }

    @Override
    public View getView(int i, View View, ViewGroup Viewgroup) {
        LayoutInflater inflater = 
    (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View row = inflater.inflate(R.layout.custom_listview,Viewgroup,false);

        //find objet in each line
        TextView TV = (TextView)row.findViewById(R.id.textview_custo_LV);
        ImageButton IM = 
    (ImageButton)row.findViewById(R.id.image_button_custo_LV);

        //get the position
        singleRow temp_obj = array_list.get(i);

        //set each line
        TV.setText(temp_obj.name);
        IM.setImageResource(temp_obj.image);

        //give the right properties to the image
        IM.setScaleType(ImageView.ScaleType.FIT_XY);
        IM.setAdjustViewBounds(true);
        IM.setPadding(0, 0, 0, 0);

        //return final line
        return row;
    }

    @Override
    public Object getItem(int i) {
        return array_list.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public int getCount() {
        return array_list.size();
    }

    }

row_item xml
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/parent_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/Button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="List all images" />
    <ListView
        android:id="@+id/Listview_card"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true" />
    </RelativeLayout>

singleRow
    public class singleRow {
    String name;
    int image;
    public singleRow(String name, int image) {
        this.name = name;
        this.image = image;
         }
    }

custom_listview xml
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageButton
        android:id="@+id/image_button_custo_LV"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:src="@drawable/image01" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id = "@+id/textview_custo_LV"
        android:layout_weight="1"
        android:text="image01" />

    </LinearLayout>

Solution

  • I have solved my issue.

    What I did is modify each single row of my listview so that each contains a checkbox. When clicking on the validate button, I read the user answer and decide whether or not it is a valid answer. However, I have now another problem but I am posting a new questions as the 2 issues are not really related.

    This is my custom line layout:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <ImageButton
        android:id="@+id/image_button_custo_LV"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:src="@drawable/wonder01" />
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <CheckBox
            android:id="@+id/checkBox_custo_LV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Choisir" />
        <TextView
            android:id="@+id/textview_custo_LV"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Wonder1" />
    </LinearLayout>
    

    This is my listview layout:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/parent_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
        <TextView
                android:id="@+id/Text_Expl_List"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:ems="10"
                android:text="Choose one card: "
                android:textSize="18sp" />
            <ListView
                android:id="@+id/Listview_card"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_alignParentTop="true" />
    

    This is my activity layout:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    tools:context="com.boardgamereplics.customlistforstackflow.MainActivity">
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button" />
    </LinearLayout>
    

    Single Row java class:

    public class singleRow {
    String name;
    int image;
    boolean ischecked;
    
    
    public singleRow(String name, int image, boolean ischecked) {
        this.name = name;
        this.image = image;
        this.ischecked = ischecked;
    }
    

    Custom adapter java class:

    public class CustomAdapter extends BaseAdapter { //implements View.OnClickListener {
    
    private Context mContext;
    private ArrayList<singleRow> array_list;
    //TODO change l'objet singlerow par card et arrange toi pour passer les cartes que tu veux.
    
    CustomAdapter(Context mContext, ArrayList<singleRow> List_Sent) {
        this.mContext = mContext;
        this.array_list = List_Sent;
    }
    
    @Override
    public View getView(int i, View View, ViewGroup Viewgroup) {
        LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View row = inflater.inflate(R.layout.one_line_model,null);
    
        //find objet in each line
        TextView TV = (TextView)row.findViewById(R.id.textview_custo_LV);
        ImageButton IM = (ImageButton)row.findViewById(R.id.image_button_custo_LV);
        CheckBox CB = (CheckBox)row.findViewById(R.id.checkBox_custo_LV);
    
        //get the position
        singleRow temp_obj = array_list.get(i);
    
        //set each line
        TV.setText(temp_obj.name);
        IM.setImageResource(temp_obj.image);
        CB.setChecked(false);
    
        //give the right properties to the image
        IM.setScaleType(ImageView.ScaleType.FIT_XY);
        IM.setAdjustViewBounds(true);
        IM.setPadding(0, 0, 0, 0);
    
        //return final line
        return row;
    }
    
    @Override
    public Object getItem(int i) {
        return array_list.get(i);
    }
    
    @Override
    public long getItemId(int i) {
        return i;
    }
    
    @Override
    public int getCount() {
        return array_list.size();
    }
    

    Main Activity:

    public class MainActivity extends AppCompatActivity {
        Button b1 = null;
        Context ctx = null;
        TextView T_pop1 = null;
        TextView T_pop2 = null;
        AlertDialog.Builder builder_pop2 = null;
        AlertDialog.Builder builder_pop1 = null;
        // ListView LV_pop1 = null;
        // ListView LV_pop2 = null;
        Button Validate_btn_pop1 = null;
        Button Validate_btn_pop2 = null;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        ctx = this;
        b1 = (Button) this.findViewById(R.id.button);
    
        b1.setOnClickListener(new android.view.View.OnClickListener() {
                                  @Override
                                  public void onClick(View arg0) {
                                      displayAlert();
                                  }
                              }
        );
    
    }
    
    public void displayAlert() {
        builder_pop1 = new AlertDialog.Builder(ctx);
    
        LayoutInflater inflater_pop1 = (LayoutInflater) ctx.getSystemService(LAYOUT_INFLATER_SERVICE);
        View listview_lay_pop1 = inflater_pop1.inflate(R.layout.listview_lay, null);
    
        //identify objet in second alertdialog
        final ListView LV_pop1 = (ListView) listview_lay_pop1.findViewById(R.id.Listview_card);
    
        //populate listview
        Resources res = getApplicationContext().getResources();
        String[] names = res.getStringArray(R.array.wonders_name1);
        int[] images = {R.drawable.wonder01, R.drawable.wonder02, R.drawable.wonder03, R.drawable.wonder04};
    
        ArrayList<singleRow> array_list_pop1 = new ArrayList<>();
    
        for (int i = 0; i < names.length; i++) {
            array_list_pop1.add(new singleRow(names[i], images[i], false));
        }
    
        CustomAdapter adapter_pop1 = new CustomAdapter(getApplicationContext(), array_list_pop1);
        LV_pop1.setAdapter(adapter_pop1);
    
        builder_pop1.setView(listview_lay_pop1);
        builder_pop1.setPositiveButton("OK", null);
        final AlertDialog dialog_pop1 = builder_pop1.create();
    
        dialog_pop1.setOnShowListener(new DialogInterface.OnShowListener() {
            @Override
            public void onShow(DialogInterface dialog_ins_pop1) {
                //Overriding the handler immediately after show is probably a better approach than OnShowListener as described below
                T_pop1 = (TextView) ((AlertDialog) dialog_pop1).findViewById(R.id.Text_Expl_List);
                Validate_btn_pop1 = ((AlertDialog) dialog_pop1).getButton(AlertDialog.BUTTON_POSITIVE);
                Validate_btn_pop1.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v_pop1) {
                        Integer choice = 0;
                        Integer counter_ischecked = 0;
                        for (int i = 0; i < 4; i++) {
                            CheckBox CBF_pop1 = (CheckBox) LV_pop1.getChildAt(i).findViewById(R.id.checkBox_custo_LV);
                            boolean isSelected = CBF_pop1.isChecked();
                            if (isSelected == true) {
                                choice = choice + i;
                                counter_ischecked++;
                            }
                        }
                        if (counter_ischecked == 0) {
                            T_pop1.setText("Choose one card");
                        }
                        if (counter_ischecked == 1) {
                            b1.setText("Success");
                            dialog_pop1.dismiss();
                        }
                        if (counter_ischecked != 0 && counter_ischecked != 1) {
                            T_pop1.setText("Choose only one card");
                        }
    
                    }
                }
                );
            }
        });
        dialog_pop1.show();
    }