내를 교체하고 ListView
함께 RecyclerView
확인을 보여주는 목록,하지만 난 방법과 유사 클릭 된 항목의 위치를 얻는 방법을 알고 싶습니다 OnItemClickListener.onItemClick(AdapterView parent, View v, int position, long id)
우리가 사용합니다 ListView
.
아이디어 주셔서 감사합니다!
내를 교체하고 ListView
함께 RecyclerView
확인을 보여주는 목록,하지만 난 방법과 유사 클릭 된 항목의 위치를 얻는 방법을 알고 싶습니다 OnItemClickListener.onItemClick(AdapterView parent, View v, int position, long id)
우리가 사용합니다 ListView
.
아이디어 주셔서 감사합니다!
답변:
링크 기반 : RecyclerView에 onItemClickListener ()가없는 이유는 무엇입니까? RecyclerView가 Listview와 어떻게 다른가요? , @Duncan의 일반적인 아이디어도 여기에 내 솔루션을 제공합니다.
RecyclerViewClickListener
어댑터에서 Activity
/로 메시지를 전달하기위한 하나의 인터페이스 를 정의하십시오 Fragment
.
public interface RecyclerViewClickListener {
public void recyclerViewListClicked(View v, int position);
}
에서 것은 Activity
/ Fragment
인터페이스를 구현하고, 또한 어댑터에 리스너를 전달합니다 :
@Override
public void recyclerViewListClicked(View v, int position){... ...}
//set up adapter and pass clicked listener this
myAdapter = new MyRecyclerViewAdapter(context, this);
에서 Adapter
와 ViewHolder
:
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ItemViewHolder> {
... ...
private Context context;
private static RecyclerViewClickListener itemListener;
public MyRecyclerViewAdapter(Context context, RecyclerViewClickListener itemListener) {
this.context = context;
this.itemListener = itemListener;
... ...
}
//ViewHolder class implement OnClickListener,
//set clicklistener to itemView and,
//send message back to Activity/Fragment
public static class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
... ...
public ItemViewHolder(View convertView) {
super(convertView);
... ...
convertView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
itemListener.recyclerViewListClicked(v, this.getPosition());
}
}
}
테스트 후 정상적으로 작동합니다.
[ 업데이트 ]
API 22부터는 RecyclerView.ViewHoler.getPosition()
더 이상 사용되지 않으므로 대신 getLayoutPosition()
.
private static RecyclerViewClickListener itemListener;
생성자에서 정적 방식으로 정적 을 참조하십시오 .
onBindViewHolder
. 또한 내 목록 항목을 모두 클릭 할 수있는 것은 아닙니다 (항목의 일부만).
new MyRecyclerViewAdapter(context, this)
. 이 메모리 누수가 발생할 수 있습니다
public void recyclerViewListClicked(View v, int position);
수정자는 public
인터페이스 메서드에 대해 중복됩니다.
public class MyRvAdapter extends RecyclerView.Adapter<MyRvAdapter.MyViewHolder>{
public Context context;
public ArrayList<RvDataItem> dataItems;
...
constructor
overrides
...
class MyViewHolder extends RecyclerView.ViewHolder{
public TextView textView;
public Context context;
public MyViewHolder(View itemView, Context context) {
super(itemView);
this.context = context;
this.textView = (TextView)itemView.findViewById(R.id.textView);
// on item click
itemView.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
// get position
int pos = getAdapterPosition();
// check if item still exists
if(pos != RecyclerView.NO_POSITION){
RvDataItem clickedDataItem = dataItems.get(pos);
Toast.makeText(v.getContext(), "You clicked " + clickedDataItem.getName(), Toast.LENGTH_SHORT).show();
}
}
});
}
}
}
다음은 클릭 리스너를 설정하는 예입니다.
Adapter extends RecyclerView.Adapter<MessageAdapter.MessageViewHolder> { ... }
public static class MessageViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView tv_msg;
public TextView tv_date;
public TextView tv_sendTime;
public ImageView sharedFile;
public ProgressBar sendingProgressBar;
public MessageViewHolder(View v) {
super(v);
tv_msg = (TextView) v.findViewById(R.id.tv_msg);
tv_date = (TextView) v.findViewById(R.id.tv_date);
tv_sendTime = (TextView) v.findViewById(R.id.tv_sendTime);
sendingProgressBar = (ProgressBar) v.findViewById(R.id.sendingProgressBar);
sharedFile = (ImageView) v.findViewById(R.id.sharedFile);
sharedFile.setOnClickListener(this);
}
@Override
public void onClick(View view) {
int position = getAdapterPosition();
switch (view.getId()){
case R.id.sharedFile:
Log.w("", "Selected"+position);
break;
}
}
}
int position = getAdapterPosition();
활동에서 리사이클 러보기를 정의하는 위치에이 코드를 넣으십시오.
rv_list.addOnItemTouchListener(
new RecyclerItemClickListener(activity, new RecyclerItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(View v, int position) {
Toast.makeText(activity, "" + position, Toast.LENGTH_SHORT).show();
}
})
);
그런 다음 별도의 클래스를 만들고 다음 코드를 넣으십시오.
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
private OnItemClickListener mListener;
public interface OnItemClickListener {
public void onItemClick(View view, int position);
}
GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
View childView = view.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
}
return false;
}
@Override
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
아래 코드로 자바 파일 생성
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
private OnItemClickListener mListener;
public interface OnItemClickListener {
public void onItemClick(View view, int position);
}
GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
}
@Override public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
View childView = view.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildLayoutPosition(childView));
return true;
}
return false;
}
@Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { }
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
RecyclerView 객체에서 리스너를 사용하십시오.
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(context, new RecyclerItemClickListener.OnItemClickListener() {
@Override public void onItemClick(View view, int position) {
// TODO Handle item click
}
}));
RecyclerItemClickListener
기본 Android 클래스가 아니므로 사용중인 라이브러리 또는 클래스 자체를 제공해야합니다.
어댑터 대신 활동 / 조각에서 재활용보기의 클릭 이벤트를 원할 경우 다음과 같은 바로 가기 방법을 사용할 수도 있습니다.
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
final TextView txtStatusChange = (TextView)v.findViewById(R.id.txt_key_status);
txtStatusChange.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "hello text " + txtStatusChange.getText().toString() + " TAG " + txtStatusChange.getTag().toString());
Util.showToast(CampaignLiveActivity.this,"hello");
}
});
return false;
}
});
인터페이스 사용과 같은 다른 긴 방법을 사용할 수도 있습니다.
recyclerViewObject.addOnItemTouchListener(
new RecyclerItemClickListener(
getContext(),
recyclerViewObject,
new RecyclerItemClickListener.OnItemClickListener() {
@Override public void onItemClick(View view, int position) {
// view is the clicked view (the one you wanted
// position is its position in the adapter
}
@Override public void onLongItemClick(View view, int position) {
}
}
)
);
아래 코드를 사용하십시오.
public class SergejAdapter extends RecyclerView.Adapter<SergejAdapter.MyViewHolder>{
...
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
@Override
public void onClick(View v) {
// here you use position
int position = getAdapterPosition();
...
}
}
}
클릭 한 항목의 위치를 찾는 가장 간단하고 쉬운 방법은 다음과 같습니다.
나는 또한 같은 문제에 직면했다.
RecyclerView ()에서 클릭 / 선택된 항목의 위치를 찾고 특정 항목에 대해 몇 가지 특정 작업을 수행하고 싶었습니다.
getAdapterPosition () 메서드는 이러한 종류의 매력처럼 작동합니다. 나는 긴 연구 끝에이 방법을 발견했고 다른 많은 방법을 시도한 후에 발견했다.
int position = getAdapterPosition();
Toast.makeText(this, "Position is: "+position, Toast.LENGTH_SHORT).show();
추가 방법을 사용할 필요가 없습니다. 'position'이라는 전역 변수를 만들고 어댑터의 주요 메서드 (클래스 또는 유사)에서 getAdapterPosition ()으로 초기화하면됩니다.
이 링크 의 간단한 문서는 다음과 같습니다. .
버전 22.1.0에 추가 된 getAdapterPosition int getAdapterPosition ()이 ViewHolder가 나타내는 항목의 어댑터 위치를 리턴합니다. 보류중인 어댑터 업데이트가 있지만 새 레이아웃 패스가 아직 발생하지 않은 경우 이는 getLayoutPosition ()과 다를 수 있습니다. RecyclerView는 다음 레이아웃 순회까지 어댑터 업데이트를 처리하지 않습니다. 이로 인해 사용자가 화면에서 보는 내용과 어댑터 내용에 일시적인 불일치가 발생할 수 있습니다. 이 불일치는 16ms 미만이므로 중요하지 않지만 ViewHolder 위치를 사용하여 어댑터에 액세스하려는 경우 문제가 될 수 있습니다. 때로는 사용자 이벤트에 대한 응답으로 일부 작업을 수행하기 위해 정확한 어댑터 위치를 가져와야 할 수 있습니다. 이 경우 ViewHolder의 어댑터 위치를 계산하는이 메서드를 사용해야합니다.
도와 줄 수있어서 기뻐. 의심을 자유롭게 물어보십시오.
내 간단한 솔루션
Make a position holder:
public class PositionHolder {
private int position;
public PositionHolder(int position) {
this.position = position;
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
}
활동에서 얻는 데 필요한 데이터를 배치하거나 입력하십시오.
어댑터 생성자 :
public ItemsAdapter(Context context, List<Item> items, PositionHolder positionHolder){
this.context = context;
this.items = items;
this.positionHolder = positionHolder;
}
활동 중 :
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
selectedPosition = 0;
positionHolder = new PositionHolder(selectedPosition);
initView();
}
onBindViewHolder 의 항목 에 있는 어댑터 onClickLictener에서
holder.holderButton.setOnClickListener(v -> {
positionHolder.setPosition(position);
notifyDataSetChanged();
});
이제 RecyclerView에서 위치를 변경할 때마다 홀더에 유지됩니다 (또는 리스너라고 불러야 함).
도움이 되길 바랍니다
내 첫 게시물; P
//Create below methods into the Activity which contains RecyclerView.
private void createRecyclerView() {
final RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
MyAdapter myAdapter=new MyAdapter(dataAray,MianActivity.this);
recyclerView.setAdapter(myAdapter);
recyclerView.setItemAnimator(new DefaultItemAnimator());
setRecyclerViewClickListner(recyclerView);
}
private void setRecyclerViewClickListner(RecyclerView recyclerView){
final GestureDetector gestureDetector = new GestureDetector(MainActivity.this,new GestureDetector.SimpleOnGestureListener() {
@Override public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
View child =recyclerView.findChildViewUnder(motionEvent.getX(),motionEvent.getY());
if(child!=null && gestureDetector.onTouchEvent(motionEvent)){
int position=recyclerView.getChildLayoutPosition(child);
String name=itemArray.get(position).name;
return true;
}
@Override
public void onTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean b) {
}
});
}
이런 식으로 시도
어댑터 클래스 :
public class ContentAdapter extends RecyclerView.Adapter<ContentAdapter.ViewHolder> {
public interface OnItemClickListener {
void onItemClick(ContentItem item);
}
private final List<ContentItem> items;
private final OnItemClickListener listener;
public ContentAdapter(List<ContentItem> items, OnItemClickListener listener) {
this.items = items;
this.listener = listener;
}
@Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_item, parent, false);
return new ViewHolder(v);
}
@Override public void onBindViewHolder(ViewHolder holder, int position) {
holder.bind(items.get(position), listener);
}
@Override public int getItemCount() {
return items.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
private TextView name;
private ImageView image;
public ViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.name);
image = (ImageView) itemView.findViewById(R.id.image);
}
public void bind(final ContentItem item, final OnItemClickListener listener) {
name.setText(item.name);
itemView.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
listener.onItemClick(item);
}
});
}
}
}
활동 또는 조각에서 :
ContentAdapter adapter = new ContentAdapter(itemList, this);
참고 : 활동 또는 프래그먼트 및 오버라이드 메소드에서 제공 한 컨텍스트를 기반으로 OnItemClickListener를 구현하십시오.
다른 접근 방식을 사용할 때마다. 사람들은 ViewHolder에 의해 표시되는 개체에 대한 참조를 저장하는 대신보기에 저장하거나 위치를 얻는 것처럼 보입니다.
대신이 방법을 사용하고 onBindViewHolder ()가 호출 될 때 ViewHolder에 저장하고 onViewRecycled ()에서 참조를 null로 설정합니다.
ViewHolder가 보이지 않게 될 때마다 재활용됩니다. 따라서 이것은 대용량 메모리 소비에 영향을 미치지 않습니다.
@Override
public void onBindViewHolder(final ItemViewHolder holder, int position) {
...
holder.displayedItem = adapterItemsList.get(i);
...
}
@Override
public void onViewRecycled(ItemViewHolder holder) {
...
holder.displayedItem = null;
...
}
class ItemViewHolder extends RecyclerView.ViewHolder {
...
MySuperItemObject displayedItem = null;
...
}
사용자 정의 인터페이스 Java 메소드에서 getLayoutPosition ()을 사용하십시오. 항목의 선택한 위치를 반환합니다.
https://becody.com/get-clicked-item-and-its-position-in-recyclerview/
디자이너 onClick
에서 listItem 의 속성을 단일 매개 변수로 정의 된 메서드로 설정할 수 있습니다 . 아래에 정의 된 예제 방법이 있습니다. getAdapterPosition 메소드는 선택한 listItem의 색인을 제공합니다.
public void exampleOnClickMethod(View view){
myRecyclerView.getChildViewHolder(view).getAdapterPosition());
}
RecyclerView 설정에 대한 자세한 내용은 https://developer.android.com/guide/topics/ui/layout/recyclerview 의 설명서를 참조하십시오.
//simply check if the adapter position you get not less than zero
holder.btnDelItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(holder.getAdapterPosition()>=0){
list.remove(holder.getAdapterPosition());
notifyDataSetChanged();
}
}
});
많은 시행 착오 끝에 어댑터 클래스에서 인터페이스를 만들고 조각으로 구현하는 것이 매우 쉬운 방법이 있음을 발견했습니다. 이제 여기에 비틀림이 있습니다. 내 재정의 함수 내부에 뷰 모델을 인스턴스화했습니다. 조각 이제 해당 함수에서 viemodel로 데이터를 보낼 수 있습니다.
이 방법이 좋은 코딩 방법인지는 모르겠지만 댓글로 알려주세요. 댓글 섹션에서 알려주세요. 정기적으로 스택 오버 흐름을 엽니 다.
recyclerView.addOnItemTouchListener(object : AdapterView.OnItemClickListener,
RecyclerView.OnItemTouchListener {
override fun onItemClick(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
TODO("Not yet implemented")
}
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {
TODO("Not yet implemented")
}
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
TODO("Not yet implemented")
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
TODO("Not yet implemented")
}
})
Kotlin을 사용하는 경우
onViewHolder에서 onClickListiner를 모든 뷰로 설정하고 사이드 클릭에서 다음 코드를 사용하십시오.
Toast.makeText (Drawer_bar.this, "위치"+ 위치, Toast.LENGTH_SHORT) .show ();
Drawer_Bar
활동 이름으로 바꿉니다 .