Android lock checkboxes when not in edit mode in custom array adapter

1.7k views Asked by At

I have a Activity that displays a list of check boxes (Focus Areas) that can be assigned to an activity event in my application. However I want to be able to prevent the user form editing these values until a button is clicked to put the form into edit mode.

Can some one explain or provide code sample how I can implement this into my application?

This list is held in a ListView with a custom ArrayAdapter of a Type FocusArea a class I have created for my application. The xml for the Activity is shown below:

        <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" android:background="@drawable/horizontal_gradient_line_reverse">

    <TextView
        android:id="@+id/textViewCustomerNameNumber"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:text="Customer Name &amp; Number" android:layout_margin="5dp"/>

    <ListView
        android:id="@+id/listViewFocusAreas"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/relativeLayoutControls"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/textViewCustomerNameNumber"
        android:layout_margin="5dp"
        android:background="@drawable/myborder" >

    </ListView>

    <RelativeLayout
        android:id="@+id/relativeLayoutControls"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true" >


        <ImageView
            android:id="@+id/imageViewCancelFocusAreaChanges"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:src="@drawable/ic_mini_undo" />

        <ImageView
            android:id="@+id/imageViewSaveFocusAreaChanges"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_toLeftOf="@+id/imageViewCancelFocusAreaChanges"
            android:src="@drawable/ic_mini_save" />

        <ImageView
            android:id="@+id/imageViewEditFocusArea"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_toLeftOf="@+id/imageViewSaveFocusAreaChanges"
            android:src="@drawable/ic_mini_edit" />

    </RelativeLayout>


    <ImageView
        android:id="@+id/imageViewEditMode"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/textViewCustomerNameNumber"
        android:layout_alignRight="@+id/listViewFocusAreas"
        android:src="@drawable/edit16x16"
        android:visibility="gone" />

</RelativeLayout>

The following is the xml for the focus area row:

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

    <CheckBox
        android:id="@+id/checkBoxFocusArea"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Focus Area" />

</LinearLayout>

The following is the code for the Custom ArrayAdapter:

    public class FocusAreaAdapter extends ArrayAdapter<FocusArea> {

    private ArrayList<FocusArea> focusAreas;
    private Context context;

    public FocusAreaAdapter(Context context, int textViewResourceId, ArrayList<FocusArea> focusAreas) {
        super(context, textViewResourceId, focusAreas);
        this.context = context;
        this.focusAreas = focusAreas;
    }

    @Override
    public View getView(final int position, View convertView, final ViewGroup parent) {
        View v = convertView;
        if(v == null) {
            LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(R.layout.focus_area_menu_item, null);
        }
        FocusArea focusArea = focusAreas.get(position);

        if(focusArea != null) {
            CheckBox cbFocusArea = (CheckBox)v.findViewById(R.id.checkBoxFocusArea);
            cbFocusArea.setText(focusArea.getFocusAreaCodeDescription());
            if(focusArea.isFocusAreaCodeChecked() == 1) {
                cbFocusArea.setChecked(true);
            } else {
                cbFocusArea.setChecked(false);
            }

            cbFocusArea.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    FocusArea focusArea = focusAreas.get(position);
                    if(focusArea.isFocusAreaCodeChecked() == 1) {
                        focusArea.setFocusAreaCodeChecked(0);
                    } else {
                        focusArea.setFocusAreaCodeChecked(1);
                    }
                }
            });
        }       
        return v;
    }
}

Finally I instanciate my custom array adapter with the following code:

    private void assignFocusAreasToAdapter() {
    // get reference to available responsibles list view control
    lvFocusAreas.clearChoices();

    // create an array adapter with the communications data array
    activityFocusAreaAdapter = new FocusAreaAdapter(this, R.layout.focus_area_menu_item, activityFocusAreas);

    // assign the my customers list control the array adapter
    lvFocusAreas.setAdapter(activityFocusAreaAdapter);
    activityFocusAreaAdapter.notifyDataSetChanged();
    Log.i(TAG, "Available Activity Focus Areas Loaded");
}
1

There are 1 answers

1
Comic Coder On BEST ANSWER

Ok i found the solution to this problem for anyone who might have the same issue.

The XML for the Focus Area activity stays the same as posted above.

The XML for the Focus Area row item is modified accordingly:

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

    <CheckBox
        android:id="@+id/checkBoxFocusArea"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Focus Area" />

</LinearLayout>

You can see that this now has the following line added android:descendantFocusability="blocksDescendants" This prevents the checkboxes onClickListener from firing which normally will block the ListViews OnItemClickedListener from firing.

The Custom Adapter code is modified to remove the checkboxes OnClickListener like so:

public class FocusAreaAdapter extends ArrayAdapter<FocusArea> {

    private ArrayList<FocusArea> focusAreas;
    private Context context;

    public FocusAreaAdapter(Context context, int textViewResourceId, ArrayList<FocusArea> focusAreas) {
        super(context, textViewResourceId, focusAreas);
        this.context = context;
        this.focusAreas = focusAreas;
    }

    @Override
    public View getView(final int position, View convertView, final ViewGroup parent) {
        View v = convertView;
        if(v == null) {
            LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(R.layout.focus_area_menu_item, null);
        }
        FocusArea focusArea = focusAreas.get(position);

        if(focusArea != null) {
            CheckBox cbFocusArea = (CheckBox)v.findViewById(R.id.checkBoxFocusArea);
            cbFocusArea.setText(focusArea.getFocusAreaCodeDescription());
            if(focusArea.isFocusAreaCodeChecked() == 1) {
                cbFocusArea.setChecked(true);
            } else {
                cbFocusArea.setChecked(false);
            }

            cbFocusArea.setClickable(false);            
        }       
        return v;
    }
}

The Custom Adapter is instanciated using the same code as posted in above but you must add an OnItemClickListener to the ListView and preform the check of the checkbox inside the OnItemClickListener click event like so:

    lvFocusAreas = (ListView)findViewById(R.id.listViewFocusAreas);
    lvFocusAreas.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
            if(editMode){
                FocusArea focusArea = (FocusArea)lvFocusAreas.getItemAtPosition(position);
                if(focusArea.isFocusAreaCodeChecked() == 0) {
                    focusArea.setFocusAreaCodeChecked(1);
                } else {
                    focusArea.setFocusAreaCodeChecked(0);
                }
                activityFocusAreaAdapter.notifyDataSetChanged();
                setControlsEnabled();
            }               
        }
    });

Hope this helps any one thats having the same problem. :D