Domanda

I have a GridView with a bunch of icons and I need to select one. And by select I mean:

  • I need the drawable id to store into a database (so I can access it later)
  • I need to draw some kind of visual cue on the grid to let the user know which icon is currently selected

I found this:
http://groups.google.com/group/android-developers/browse_thread/thread/f08a58167dbaa8c8

So I guess setSelection is out of the picture and I can't use it to select the icon itself nor draw the visual cue. I know the grid item position in the onItemClickListener and I can save it as a private class variable. My biggest problem is drawing that visual cue.

How can I achieve that? How can I draw a visual cue on the clicked item and if the user clicks different items, to "undraw" that visual cue and redraw it in the new item?

È stato utile?

Soluzione

After tackling with this for a couple of hours I think I finally found the solution I was looking for. Although the answers are barely related, the initial edits on Ian solution helped me find this solution :)

I'm not going to explain everything I did, I think it's pretty self explanatory. Just a few remarks:

  • First I tried view.Invalidate() and view.postInvalidate() instead of iconAdapter.notifyDataSetChanged() but neither worked. The documentation stated that the invalidate methods only "asked" to redraw the view "when possible".

  • I was looking for a simpler solution than to merge two drawables. For instance, draw the icon on the ImageView background and the visual cue as the image. For some strange reason, the visual cue started to show randomly all over the other icons when the GridView was scrolled. I don't understand why, but the idea of a visual cue on top of a background image makes perfect sense to me and ImageView allows that, no need for that extra merge method. However, I couldn't make it work without it...

MyActivity.java

public class MyActivity extends Activity {
    private GridView mGridViewIcon;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mGridViewIcon = (GridView)findViewById(R.id.gridview_icon);
        mGridViewIcon.setAdapter(new IconAdapter(this));

        mGridViewIcon.setOnItemClickListener(new GridView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                IconAdapter iconAdapter = (IconAdapter)parent.getAdapter();

                iconAdapter.setSelectedItemPosition(position);
                iconAdapter.notifyDataSetChanged();
            }

        });
    }

}

IconAdapter.java

public class IconAdapter extends BaseAdapter {

    private int mSelectedPosition;
    private Integer[] mThumbIds;
    private int mIconSize;
    private Context mContext;

    public IconAdapter(Context context) {
        mThumbIds = AppHelper.ICON_SET.keySet().iterator().next();
        mIconSize = context.getResources().getDimensionPixelSize(R.dimen.default_icon_size);
        mContext = context;
    }

    @Override
    public int getCount() {
        return mThumbIds.length;
    }

    @Override
    public Object getItem(int position) {
        return mContext.getResources().getDrawable(mThumbIds[position]);
    }

    @Override
    public long getItemId(int position) {
        return mThumbIds[position];
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;

        if(convertView == null) {
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(mIconSize, mIconSize));
        } else {
            imageView = (ImageView)convertView;
        }

        if(mSelectedPosition == position) {
            imageView.setImageDrawable(mergeDrawableLayers(mThumbIds[position],
                    R.drawable.ic_note_selected_mark));
        } else {
            imageView.setImageResource(mThumbIds[position]);
        }

        return imageView;
    }

    public void setSelectedItemPosition(int position) {
        mSelectedPosition = position;
    }

    private Drawable mergeDrawableLayers(int background, int overlay) {
        Drawable[] drawableLayers = new Drawable[2];

        drawableLayers[0] = mContext.getResources().getDrawable(background);
        drawableLayers[1] = mContext.getResources().getDrawable(overlay);

        return new LayerDrawable(drawableLayers);
    }

}

Altri suggerimenti

I believe, that if you want some kind of selection cue, you need a focusable object. However, with a focusable object (such as a Button), attaching OnItemClickListener to the GridView does not work (if i remember correctly). Rather, you must individually attach an OnClickListener to each item at getView() in the adapter.

Adapter:

// create a new ImageView for each item referenced by the Adapter
    public View getView(int position, View convertView, ViewGroup parent) {
        Button button;
        if (convertView == null) {  // if it's not recycled, initialize some attributes
            button = new Button(mContext);
            // set layout params (make sure its GridView.layoutParams)
            // and other stuff

        } 
        else {
            button = (Button) convertView;
        }

        button.setBackgroundResource(mThumbIds[position]); // mThumbIds hold Resource Ids
        button.setOnClickListener(new OnClickListener() {
           onClick(View v) {
             // store directly to database here, or send it with the activity with sharedPreferences (below)

             // We need an Editor object to make preference changes.
             // All objects are from android.context.Context
             SharedPreferences settings = getSharedPreferences("MY_PREFERENCE", 0);
             SharedPreferences.Editor editor = settings.edit();
             editor.putInt("button_id", mThumbIds[position]);

             // Commit the edits!
             editor.commit();
           } 
        });
        return button;
    }
}

On Activity Side, save button onClickListener:

onClick(View v) {
// Restore preferences
       SharedPreferences settings = getSharedPreferences("MY_PREFERENCE", 0);
       int id = settings.getInt("button_id", -1);

       // now safe all stuff to database
}

There may be details missing because a Button is focusable, but i think this should do. Also , you will achieve the selection by using a .xml defined selector resource. That, however, should be addressed in a separate question.

Edit 1: Actually now that i think about it, i'm not sure if a drawable .xml (the selector) can have an ID. I'll have to implement this at home later on and try it.

Edit 2: I added the sharedPreference part

Edit 3: Added activity side querying of sharedPreference.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top