Question

(Ok, I've researched a lot and found a few answers but nothing really worked for me.. so I've finally opened an account to post here. Thanks to the community for all your answers earlier!)

Context

I am creating a category selector (ListView with a custom adapter)- each category can have multiple sub-categories and each sub-category can have multiple sub-categories. For the selector, I'm using a ListView with a custom List item - TextView (to display category) and an ImageView (the forward arrow) to indicate if the category has sub-categories - see this image:

image


I want the user to do the following actions
(1) Click on the category name to SELECT that category
(2) Click on the forward arrow to SEE all sub-categories (it will re-populate the ListView with all sub-categories)

Question Starts here

I want the user to see the following highlights/focus on the user does the about two actions (1) and (2)

Highlight on action (1)

See this image:

image


Highlight the row when the user clicks on the category name/row. This happens automatically because I've setup

listView.setOnItemClickListener()

Highlight on action (2)

See this image:

image


I want the user to see the highlight only on the forward-arrow and not the row. I'm able to register the CLICK on the image with

imageView.setOnClickListener()

in my custom adapter but I'm unable to get the highlight on the forward-arrow

How do I get this highlight on the ImageView?

Code

    Activity's onCreate() {
      LayoutInflater inflater = getActivity().getLayoutInflater();
      View categorySelectView = inflater.inflate(R.layout.cat_select, null);
      LinearLayout categorySelectLayout = (LinearLayout) categorySelectView;
      ListView categoryListView = (ListView) categorySelectLayout.findViewById(R.id.list_cat_select);
      CategoryArrayAdapter categoryArrayAdapter = new CategoryArrayAdapter(this.getActivity(), CategoryAdapter.getAllCategories());
      categoryListView.setAdapter(categoryArrayAdapter);
      categoryListView.setOnItemClickListener(categorySelectClickHandler);
    }

CategoryARrayAdapter's getView(int position, View covertView, ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View rowView = inflater.inflate(R.layout.cat_item, parent, false);

    TextView textView = (TextView) rowView.findViewById(R.id.cat_name);
    Category catToDisplay = categories.get(position);
    textView.setText(catToDisplay.getName());

    if(catToDisplay.isParent()) {
        ImageView imageView = (ImageView) rowView.findViewById(R.id.cstrow_cat_expand);
        imageView.setImageResource(R.drawable.cat_expand);
        imageView.setOnClickListener(categoryExpandClickHandler);
        imageView.setFocusable(false); // to make sure the highlight on row shows
        imageView.setFocusableInTouchMode(false); // to make sure the highlight on row shows
    }

    return rowView;
}
Was it helpful?

Solution

So here is what I've done. This should be scalable too.

The CategoryArrayAdapter has the following getView()

    public View getView(int position, View covertView, ViewGroup parent) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View rowView = inflater.inflate(R.layout.cat_select, parent, false);

        TextView textView = (TextView) rowView.findViewById(R.id.cat_name);
        Category catToDisplay = categories.get(position);
        textView.setText(catToDisplay.getName());

        if(catToDisplay.isParent()) {
            ImageView imageView = (ImageView) rowView.findViewById(R.id.cstrow_cat_expand);
            imageView.setImageResource(R.drawable.cat_expand);
            imageView.setOnClickListener(categoryExpandClickHandler);
            imageView.setOnTouchListener(categoryExpandTouchHandler);
            imageView.setFocusable(false); // to make sure the highlight on the item shows
            imageView.setFocusableInTouchMode(false); // to make sure the highlight on the item shows
            imageView.setTag(catToDisplay);
        }

        return rowView;
    }

Two things that made this work

  1. imageView.setOnTouchListener() allows me to set the highlight (thanks Piyush Gupta for pointing out the setBackgroundColor() method
  2. imageView.setOnClickListener() allows me to perform the action when the user clicks on arrow

    /**
     * This method listens to the TOUCH CLICK on the IMAGEVIEW to give it button like feeling
     */
    private View.OnTouchListener categoryExpandTouchHandler = new View.OnTouchListener() {
    
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch(event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                v.setBackgroundColor(getContext().getResources().getColor(R.color.highlight_cat_expand));
                break;
            }
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP: {
                v.setBackgroundColor(getContext().getResources().getColor(android.R.color.transparent));
                break;
            }
        }
        return false;
    }
    };
    
    /**
     * This method listens to EXPAND IMAGEVIEW CLICK in the LISTVIEW of categories
     */
    private View.OnClickListener categoryExpandClickHandler = new View.OnClickListener() {
    
    @Override
    public void onClick(View view) {
        // Expanding this category
        ... expand code here ...
    }
    };
    

To get the HIGHLIGHT and CLICK to work together, return false in onTouchListener(). This will pass the touch event to the onClickListener(). I got this solution from https://stackoverflow.com/a/10376887/3393044 comment by the thin

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top