简体   繁体   中英

No ripple effect on touch in recyclerview

I have a recyclerview with four grid elements (2*2) that work like a menu. However, when i click on them no ripple effect is shown. It just takes me to the next activity without any visual confirmation that the view was pressed. Can anyone help?

MainActivity

public class MainActivity extends AppCompatActivity implements MainMenuAdapter.OnItemClickListener {

    Toolbar toolbar;
    private static List<ViewModel> tileItems = new ArrayList<>();

    static {
        tileItems.add(new ViewModel("Activity", "#3F51B5", R.drawable.activity));
        tileItems.add(new ViewModel("Profile", "#E91E63", R.drawable.profile));
        tileItems.add(new ViewModel("Training", "#FF5722", R.drawable.training));
        tileItems.add(new ViewModel("Diet", "#4CAF50", R.drawable.diet));
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
        MainAdapter adapter = new MainAdapter(tileItems, MainActivity.this);
        recyclerView.setAdapter(adapter);
        adapter.setOnItemClickListener(this);


        // Toolbar
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

    }

    @Override
    public void onBackPressed() {
        this.moveTaskToBack(true);
//        this.finishAffinity();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override public void onItemClick(View view, ViewModel viewModel) {
    }
}

MainAdapter

public class MainAdapter extends RecyclerView.Adapter<MainMenuAdapter.ViewHolder> implements View.OnClickListener {

    private List<ViewModel> items;
    private OnItemClickListener onItemClickListener;
    private Context context;

    // Adapter constructor
    public MainAdapter(List<ViewModel> items, Context context) {
        this.items = items;
        this.context = context;
    }

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.main_item, parent, false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, int position) {

        final ViewModel dataItem = items.get(position);
        viewHolder.colorBlock.setBackgroundColor(dataItem.getColor());
        viewHolder.menuName.setText(dataItem.getName());
        viewHolder.menuIcon.setImageResource(dataItem.getImage());
        viewHolder.itemView.setTag(dataItem);
        if (dataItem.getActivity() != null) {
            viewHolder.colorBlock.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent i = new Intent(context, dataItem.getActivity());
                    context.startActivity(i);

                }
            });
        }
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    @Override public void onClick(final View v) {
        // Give some time to the ripple to finish the effect
        if (onItemClickListener != null) {
            new Handler().postDelayed(new Runnable() {
                @Override public void run() {
                    onItemClickListener.onItemClick(v, (ViewModel) v.getTag());
                }
            }, 200);
        }
    }

    /** This is our ViewHolder class */
    public static class ViewHolder extends RecyclerView.ViewHolder {

        public TextView menuName;
        public View colorBlock;
        public ImageView menuIcon;

        public ViewHolder(View convertView) {
            super(convertView); // Must call super() first

            menuName = (TextView) convertView.findViewById(R.id.menuName);
            colorBlock = (View) convertView.findViewById(R.id.colorBlock);
            menuIcon = (ImageView) convertView.findViewById(R.id.menuItem);
        }
    }

    public interface OnItemClickListener {

        void onItemClick(View view, ViewModel viewModel);

    }
}

activity_main.xml

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <include
        android:id="@+id/toolbar"
        layout="@layout/toolbar"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"/>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_below="@id/toolbar"
        android:layout_width= "match_parent"
        android:layout_height = "match_parent" />

</RelativeLayout>

main_item.xml

<?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:clickable="true"
    android:focusable="true"
    android:foreground="?android:attr/selectableItemBackground">

    <View
        android:id="@+id/colorBlock"
        android:layout_width="match_parent"
        android:layout_height="170dp" />

    <ImageView
        android:id="@+id/menuItem"
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:layout_centerHorizontal="true"
        android:padding="16dp"
        />

    <TextView
        android:id="@+id/menuName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:textColor="@android:color/white"
        android:textSize="16sp"/>
</RelativeLayout>

The Ripple effect will happen (@Budius is wrong in his comment) if you set the background of main_item.xml to ?android:selectableItemBackground or ?selectableItemBackground . I found references to the second one. However, AndroidStudio warned that it was a private in com.android.support:design. My app crashed when trying to use that private version. I guessed at the first one with the "android:" prefix, and voila, it works.

Perhaps you're setting android:foreground by accident? I tried that out but saw nothing happen to my RecyclerView items.

Your updated RelativeLayout would be:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
android:background="?android:selectableItemBackground">

I've also seen android:background="?android:attr/selectableItemBackground" work to initiate the ripple. I'll also mention that the selectableItemBackground does not need to be on the root element of the main_item.xml. I'm using a background color in the root item, then setting selectableItemBackground on a nested ViewGroup.

My answer comes from a frame of reference NOT using the material design appcompat. I suspect there is a difference if you are using the material design appcompat support library.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM