サポートライブラリのリサイクラービューとカードを試しています。カードのリサイクラービューがあります。各カードの右上隅には、削除するための「x」アイコンがあります。
カードxml、list_item.xml
:
<?xml version="1.0" encoding="utf-8"?>
<Android.support.v7.widget.CardView
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_margin="5dp">
<RelativeLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<TextView
Android:id="@+id/taskDesc"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_alignParentBottom="true"
Android:textSize="40sp"
Android:text="hi"/>
<ImageView
Android:id="@+id/xImg"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_alignParentTop="true"
Android:layout_alignParentRight="true"
Android:src="@drawable/ic_remove"/>
</RelativeLayout>
</Android.support.v7.widget.CardView>
TaskAdapter.Java
のnotifyItemRemoved(position)
で使用する位置で行にタグを付けようとしました:
public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.TaskViewHolder> {
private List<Task> taskList;
private TaskAdapter thisAdapter = this;
// cache of views to reduce number of findViewById calls
public static class TaskViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
protected TextView taskTV;
protected ImageView closeBtn;
public TaskViewHolder(View v) {
super(v);
taskTV = (TextView)v.findViewById(R.id.taskDesc);
}
@Override
public void onClick(View v) {
int position = v.getTag();
adapter.notifyItemRemoved(position);
}
}
public TaskAdapter(List<Task> tasks) {
if(tasks == null)
throw new IllegalArgumentException("tasks cannot be null");
taskList = tasks;
}
// onBindViewHolder binds a model to a viewholder
@Override
public void onBindViewHolder(TaskViewHolder taskViewHolder, int pos) {
final int position = pos;
Task currTask = taskList.get(pos);
taskViewHolder.taskTV.setText(currTask.getDescription());
taskViewHolder.closeBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
thisAdapter.notifyItemRemoved(position);
}
});
}
@Override
public int getItemCount() {
return taskList.size();
}
// inflates row to create a viewHolder
@Override
public TaskViewHolder onCreateViewHolder(ViewGroup parent, int pos) {
View itemView = LayoutInflater.from(parent.getContext()).
inflate(R.layout.list_item, parent, false);
return new TaskViewHolder(itemView);
}
}
タグを設定できず、onClick.
からアダプターにアクセスできないため、これは機能しません。
onClickListener
sをonBindViewHolder()
に設定すると、そこからポジションにアクセスできます。それらをViewHolder
に設定すると、その位置もViewHolder
に渡さない限り、どの位置がクリックされたかわかりません。
編集
pskink
が指摘したようにViewHolder
にはgetPosition()
がありますので、元々のやり方は正しかったです。
ビューをクリックすると、ViewHolder
でgetPosition()
を使用でき、位置を返します
更新
getPosition()
は廃止され、getAdapterPosition()
に置き換えられました
Kotlinコード:
override fun onBindViewHolder(holder: MyHolder, position: Int) {
// - get element from your dataset at this position
val item = myDataset.get(holder.adapterPosition)
}
別の方法-setTag()およびgetTag()メソッドの使用Viewクラス。
アダプターのonBindViewHolderメソッドでsetTag()を使用します
@Override
public void onBindViewHolder(myViewHolder viewHolder, int position) {
viewHolder.mCardView.setTag(position);
}
ここで、mCardViewはmyViewHolderクラスで定義されています
private class myViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public View mCardView;
public myViewHolder(View view) {
super(view);
mCardView = (CardView) view.findViewById(R.id.card_view);
mCardView.setOnClickListener(this);
}
}
onClickListener実装でgetTag()を使用します
@Override
public void onClick(View view) {
int position = (int) view.getTag();
//display toast with position of cardview in recyclerview list upon click
Toast.makeText(view.getContext(),Integer.toString(position),Toast.LENGTH_SHORT).show();
}
詳細については、 https://stackoverflow.com/a/33027953/4658957 を参照してください
@tyczjの答えを補完するには:
汎用アダプターPseidoコード:
public abstract class GenericRecycleAdapter<T, K extends RecyclerView.ViewHolder> extends RecyclerView.Adapter{
private List<T> mList;
//default implementation code
public abstract int getLayout();
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(getLayout(), parent, false);
return getCustomHolder(v);
}
public Holders.TextImageHolder getCustomHolder(View v) {
return new Holders.TextImageHolder(v){
@Override
public void onClick(View v) {
onItem(mList.get(this.getAdapterPosition()));
}
};
}
abstract void onItem(T t);
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
onSet(mList.get(position), (K) holder);
}
public abstract void onSet(T item, K holder);
}
ViewHolder:
public class Holders {
public static class TextImageHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public TextView text;
public TextImageHolder(View itemView) {
super(itemView);
text = (TextView) itemView.findViewById(R.id.text);
text.setOnClickListener(this);
}
@Override
public void onClick(View v) {
}
}
}
アダプターの使用:
public class CategoriesAdapter extends GenericRecycleAdapter<Category, Holders.TextImageHolder> {
public CategoriesAdapter(List<Category> list, Context context) {
super(list, context);
}
@Override
void onItem(Category category) {
}
@Override
public int getLayout() {
return R.layout.categories_row;
}
@Override
public void onSet(Category item, Holders.TextImageHolder holder) {
}
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
FrameLayout root;
public ViewHolder(View itemView) {
super(itemView);
root = (FrameLayout) itemView.findViewById(R.id.root);
root.setOnClickListener(this);
}
@Override
public void onClick(View v) {
LogUtils.errorLog("POS_CLICKED: ",""+getAdapterPosition());
}
}
個人的に、私が見つけて、私にとって素晴らしい仕事をする最も簡単な方法は以下の通りです:
「RecycleAdapter」クラス(サブクラス)内にインターフェースを作成します
public interface ClickCallback {
void onItemClick(int position);
}
コンストラクターのパラメーターとしてインターフェイスの変数を追加します。
private String[] items;
private ClickCallback callback;
public RecyclerAdapter(String[] items, ClickCallback clickCallback) {
this.items = items;
this.callback = clickCallback;
}
ViewHolder(別のサブクラス)にクリックリスナーを設定し、インターフェイスを介して「位置」を渡します
AwesomeViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
callback.onItemClick(getAdapterPosition());
}
});
mTextView = (TextView) itemView.findViewById(R.id.mTextView);
}
今、アクティビティ/フラグメントでリサイクラアダプターを初期化するとき、新しい 'ClickCallback'(インターフェイス)を作成するだけです
String[] values = {"Hello","World"};
RecyclerAdapter recyclerAdapter = new RecyclerAdapter(values, new RecyclerAdapter.ClickCallback() {
@Override
public void onItemClick(int position) {
// Do anything with the item position
}
});
これで終わりです。 :)
このように解決しました
class MyOnClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
int itemPosition = mRecyclerView.getChildAdapterPosition(v);
myResult = results.get(itemPosition);
}
}
そしてアダプターで
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_wifi, parent, false);
v.setOnClickListener(new MyOnClickListener());
ViewHolder vh = new ViewHolder(v);
return vh;
}
フォーカスされた子を取得し、それを使用してアダプターの位置を取得します。
mRecyclerView.getChildAdapterPosition(mRecyclerView.getFocusedChild())
1。クラス名RecyclerTouchListener.Javaを作成
import Android.content.Context;
import Android.support.v7.widget.RecyclerView;
import Android.view.GestureDetector;
import Android.view.MotionEvent;
import Android.view.View;
public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener
{
private GestureDetector gestureDetector;
private ClickListener clickListener;
public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ClickListener clickListener) {
this.clickListener = clickListener;
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null) {
clickListener.onLongClick(child, recyclerView.getChildAdapterPosition(child));
}
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
clickListener.onClick(child, rv.getChildAdapterPosition(child));
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
public interface ClickListener {
void onClick(View view, int position);
void onLongClick(View view, int position);
}
}
2。RecyclerTouchListenerを呼び出す
recycleView.addOnItemTouchListener(new RecyclerTouchListener(this, recycleView,
new RecyclerTouchListener.ClickListener() {
@Override
public void onClick(View view, int position) {
Toast.makeText(MainActivity.this,Integer.toString(position),Toast.LENGTH_SHORT).show();
}
@Override
public void onLongClick(View view, int position) {
}
}));
アイテムの位置を取得する最も正しい方法は
View.OnClickListener onClickListener = new View.OnClickListener() {
@Override public void onClick(View v) {
View view = v;
View parent = (View) v.getParent();
while (!(parent instanceof RecyclerView)){
view=parent;
parent = (View) parent.getParent();
}
int position = recyclerView.getChildAdapterPosition(view);
}
表示するため、行レイアウトのルートビューをクリックするとは限りません。ビューがルートビュー(ボタンなど)でない場合、クラスキャスト例外が発生します。したがって、最初にビューを見つける必要があります。これは、reciclerviewの直接の子です。次に、recyclerView.getChildAdapterPosition(view);を使用して位置を見つけます。
@Override
public void onClick(View v) {
int pos = getAdapterPosition();
}
ViewHolder
のように簡単
onBindViewHolder()はすべてのアイテムに対して呼び出され、onBindVieHolder()内でクリックリスナーを設定することは、ViewHolderコンストラクターで一度呼び出すことができる場合に繰り返す必要のないオプションです。
public class MyViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener{
public final TextView textView;
public MyViewHolder(View view){
textView = (TextView) view.findViewById(R.id.text_view);
view.setOnClickListener(this);
// getAdapterPosition() retrieves the position here.
}
@Override
public void onClick(View v){
// Clicked on item
Toast.makeText(mContext, "Clicked on position: " + getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
}
ViewHolderにView.OnClickListenerを実装する必要はありません。 RecyclerView.AdapterのメソッドonCreateViewHolderでクリックリスナーを設定することで、クリックされた位置を直接取得できます。コードのサンプルを次に示します。
public class ItemListAdapterRecycler extends RecyclerView.Adapter<ItemViewHolder>
{
private final List<Item> items;
public ItemListAdapterRecycler(List<Item> items)
{
this.items = items;
}
@Override
public ItemViewHolder onCreateViewHolder(final ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_row, parent, false);
view.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
int currentPosition = getClickedPosition(view);
Log.d("DEBUG", "" + currentPosition);
}
});
return new ItemViewHolder(view);
}
@Override
public void onBindViewHolder(ItemViewHolder itemViewHolder, int position)
{
...
}
@Override
public int getItemCount()
{
return items.size();
}
private int getClickedPosition(View clickedView)
{
RecyclerView recyclerView = (RecyclerView) clickedView.getParent();
ItemViewHolder currentViewHolder = (ItemViewHolder) recyclerView.getChildViewHolder(clickedView);
return currentViewHolder.getAdapterPosition();
}
}