9

This is a follow up to this question where Reimar Twelker suggested using View.setFocusable() and View.setClickable() to enable/disable rows in a list view using an ArrayAdapter.

I tried doing this, but I get the opposite effect to what I would expect. If I use

View.setFocusable(true);
View.setClickable(true);

the row is disabled (no effect when I press it). And if I use the opposite:

View.setFocusable(false);
View.setClickable(false);

the row is enabled (selection applied when I press it).

Any clue about what might be happening?

Here is the contents of my layout:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/row_style"
  android:layout_width="fill_parent"
  android:layout_height="?android:attr/listPreferredItemHeight" 
  android:paddingLeft="5dip"
  android:paddingRight="5dip">

  <ImageView android:id="@+id/row_image_style"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:adjustViewBounds="false"
    android:scaleType="centerCrop"
    android:drawingCacheQuality="low" />
</FrameLayout>

I use it in an alert dialog like this:

dialog = new AlertDialog.Builder(this)
            .setTitle(R.string.templates_dialog)
            .setAdapter(new StyleAdapter(this, R.id.row_style, StyleTemplate.values()), 
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        setTemplate(StyleTemplate.values()[which]);
                    }
                })
            .create();
            dialog.setCanceledOnTouchOutside(true);

and StyleAdapter is defined as follows:

public class StyleAdapter extends ArrayAdapter<StyleTemplate>{

        private final StyleTemplate[] m_objects;
        private final LayoutInflater inflater;

        public StyleAdapter(Context context, int textViewResourceId, StyleTemplate[] objects) {
            super(context, textViewResourceId, objects);
            m_objects = objects;
            inflater = getLayoutInflater();
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View row = convertView;
            if (row == null) { // Reuse the old view if it exists
                row = inflater.inflate(R.layout.row_style, parent, false);
            }

            // Get the selected style data
            StyleTemplate style = m_objects[position];

            // Set the background image to the template background
            ImageView bg = (ImageView) row.findViewById(R.id.row_image_style);
            bg.setImageDrawable(null);
            bg.setBackgroundColor(Color.rgb(style.bR, style.bG, style.bB));

            boolean val = true;
            row.setFocusable(val);
            row.setClickable(val);

            return row;
        }
    }

To test the effect of setFocusable() and setClickable(), I simply change the value of val in StyleAdapter.getView().

Community
  • 1
  • 1
Pooks
  • 2,565
  • 3
  • 37
  • 40
  • The worst is, that even if you disable it, it only pales off, but continues to work and catch events. – Gangnus Mar 02 '12 at 11:08
  • I'm really interested in this, as I'm trying to disable the selector on a listItem. Is calling setClickable(true) (as opposed to setClickable(false)) on that item the only option or there are actually other ways? – doplumi Jan 12 '14 at 21:54
  • @domenicop You might also want to try overriding isEnabled(int position) for your ArrayAdapter and returning false for disabled items. I can't remember why I didn't want to go that way, but it might work for you. – Pooks Jan 15 '14 at 08:25

1 Answers1

3

Actually here I found the explanation of it all. The thing is that if you set the view to be clickable, then it will consume the click and not propagate it to the container.

Thus convertView.setClickable(true) actually disables the clicks.

Community
  • 1
  • 1
Boris Strandjev
  • 46,145
  • 15
  • 108
  • 135