-1

I have a custom adapter set for my ListView. I have also set the default item selection ripple animation to appear when an item is selected (android:background="?android:selectableItemBackground"). However, the animation won't appear when I tap the TextViews. Here's a video.

What I've tried, to no avail:

  • setting the parent LinearLayout's descendantFocusability="blocksDescendants"
  • adding clickable & focusable="false" to the TextViews

Here's my list_item.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawSelectorOnTop="true"
android:background="?android:selectableItemBackground"
android:orientation="vertical"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp">

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:ellipsize="end"
    android:maxLines="1"
    android:textSize="18sp"
    android:textStyle="bold" />

<TextView
    android:id="@+id/textView2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:ellipsize="end"
    android:maxLines="1" />

</LinearLayout>

(Edit) And in getView() method in Adapter class I have these before return convertView:

    holder.title.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
            ((ListView) parent).performItemClick(v, position, 0); // Let the event be handled in onItemClick()
        }
    });

    holder.text.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ((ListView) parent).performItemClick(v, position, 0); // Let the event be handled in onItemClick()
        }
    });

    convertView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ((ListView) parent).performItemClick(v, position, 0);
        }
    });

...to allow onItemClick in MainActivity (if I press the text or the linear layout, it opens up the same thing).

Locdoc01
  • 723
  • 1
  • 5
  • 19
Akres
  • 126
  • 2
  • 16
  • Is there a OnClickListener on that TextView? – Locdoc01 Apr 20 '18 at 20:18
  • @Locdoc01 Yes in the adapter, I've added in that code in my post – Akres Apr 20 '18 at 20:33
  • Do you actually NEED the specific OnClickListeners on the textViews, if they opens up the same thing. – Locdoc01 Apr 20 '18 at 20:37
  • @Locdoc01 If I understand your question correctly, then yes, I do need them. Otherwise I wouldn't be able to open another activity by clicking the textviews. It is a note taking app, so a user taps a note they want to open: they can tap the whole row - either the title, text or empty space surrounding them - and still open the note. – Akres Apr 20 '18 at 20:43

1 Answers1

0

I have a solution to your problem: Try this in your getView():

final RippleDrawable rippleDrawable = (RippleDrawable) convertView.getBackground();
final View finalParent = parent;
final int finalPosition = position;
View.OnTouchListener listener = new View.OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {

        switch (motionEvent.getAction()) {
            case MotionEvent.ACTION_DOWN:
                rippleDrawable.setHotspot(motionEvent.getX(), motionEvent.getY());
                rippleDrawable.setState(new int[] {android.R.attr.state_pressed, android.R.attr.state_enabled});
                return true;
            case MotionEvent.ACTION_UP:
                rippleDrawable.setState(new int[0]);
                ((ListView)finalParent).performItemClick(view, finalPosition, 0);
                return true;
        }
        return false;
    }
};

The first line gets the RippleDrawable of the ListView item which holds the touched TextView.

When the TextView gets touched, you get the coordinates of the touch and set them to the RippleDrawable with setHotSpot, to specify the starting point of the ripple effect.

After that you trigger the ripple effect by setting an int array holding the states android.R.attr.state_pressed and android.R.attr.state_enabled to the RippleDrawable using setState().

When the touch ends, you set the state to an empty int array, the stop the ripple.
It should work!

Locdoc01
  • 723
  • 1
  • 5
  • 19
  • Hmm, that creates the animation, but now I can't click to get to a new activity or to show context menu. How do I still keep those functions? – Akres Apr 21 '18 at 19:01
  • Yes, you can. See my edit on the code. In case of the MotionEvent.ACTION_UP you can do, whatever action you like. So you can do performClick() on another View, or like in your case performItemClick() on the parent ListView – Locdoc01 Apr 21 '18 at 21:20
  • Or maybe I got your problem wrong? Where exactly do you want to click to get a specific function? – Locdoc01 Apr 21 '18 at 21:22