RecyclerView-특정 위치에서보기


140

나는과 활동이 RecyclerView과를 ImageView. 를 사용하여 RecyclerView이미지 목록을 가로로 표시하고 있습니다. 나는에서 이미지를 클릭하면 활동에 이미지의 큰 그림을 표시해야합니다. 지금까지 모든 것이 잘 작동합니다.RecyclerViewImageView

이제이 두 개 더 있습니다 ImageButtons활동의를 : imageButton_leftimageButton_right. 를 클릭하면 imageButton_left의 이미지가 ImageView왼쪽으로 바뀌고 썸네일의 이미지 RecyclerView가이 변경 사항을 반영해야합니다. 의 경우도 마찬가지입니다 imageButton_right.

를 회전 할 수 ImageView있습니다. 그러나에서 축소판 그림을 어떻게 회전시킬 수 RecyclerView있습니까? 어떻게 얻을 수 ViewHolder의를 ImageView?

암호:

활동 XML :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp" />


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/original_image"
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:scaleType="fitXY"
            android:src="@drawable/image_not_available_2" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:gravity="center_horizontal"
            android:orientation="horizontal">


            <ImageButton
                android:id="@+id/imageButton_left"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="20dp"
                android:background="@drawable/rotate_left_icon" />

            <ImageButton
                android:id="@+id/imageButton_right"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/rotate_right_icon" />

        </LinearLayout>
    </LinearLayout>
</LinearLayout>

내 활동 코드 :

public class SecondActivity extends AppCompatActivity implements IRecyclerViewClickListener {


    RecyclerView mRecyclerView;
    LinearLayoutManager mLayoutManager;
    RecyclerViewAdapter mRecyclerViewAdapter;
    List<String> urls = new ArrayList<String>();
    ImageView mOriginalImageView;
    ImageButton mLeftRotate, mRightRotate;

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

        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
        mLayoutManager = new LinearLayoutManager(this, android.support.v7.widget.LinearLayoutManager.HORIZONTAL, false);
        mLayoutManager.setOrientation(android.support.v7.widget.LinearLayoutManager.HORIZONTAL);
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerViewAdapter = new RecyclerViewAdapter(this, urls);
        mRecyclerView.setAdapter(mRecyclerViewAdapter);

        mOriginalImageView = (ImageView) findViewById(R.id.original_image);
        mLeftRotate = (ImageButton) findViewById(R.id.imageButton_left);
        mLeftRotate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mOriginalImageView.setRotation(mOriginalImageView.getRotation() - 90);
            }
        });


        mRightRotate = (ImageButton) findViewById(R.id.imageButton_right);
        mRightRotate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mOriginalImageView.setRotation(mOriginalImageView.getRotation() + 90);
            }
        });

        Intent intent = getIntent();
        if (intent != null) {

            String portfolio = intent.getStringExtra("portfolio");

            try {

                JSONArray jsonArray = new JSONArray(portfolio);

                for (int i = 0; i < jsonArray.length(); i++) {

                    JSONObject jsonObject = jsonArray.getJSONObject(i);

                    String url = jsonObject.getString("url");
                    urls.add(url);
                }

                Log.d(Const.DEBUG, "URLs: " + urls.toString());

                mRecyclerViewAdapter.notifyDataSetChanged();

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }


    @Override
    public void onItemClick(int position) {
        Picasso.with(this).load(urls.get(position)).into(mOriginalImageView);
    }
}

RecyclerView 용 사용자 정의 어댑터 :

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {

    Context context;
    List<String> mUrls = new ArrayList<String>();

    IRecyclerViewClickListener mIRecyclerViewClickListener;

    public int position;

    public int getPosition() {
        return position;
    }

    public void setPosition(int position) {
        this.position = position;
    }



    public RecyclerViewAdapter(Context context, List<String> urls) {
        this.context = context;
        this.mUrls.clear();
        this.mUrls = urls;

        Log.d(Const.DEBUG, "Urls Size: " + urls.size());
        Log.d(Const.DEBUG, urls.toString());

        if (context instanceof IRecyclerViewClickListener)
            mIRecyclerViewClickListener = (IRecyclerViewClickListener) context;
        else
            Log.d(Const.DEBUG, "Implement IRecyclerViewClickListener in Activity");
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.item_horizontal_recyclerview, parent, false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Picasso.with(context).load(mUrls.get(position)).into(holder.mImageView);
    }

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


    public void rotateThumbnail() {


    }

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        public ImageView mImageView;
        public View v;

        public ViewHolder(View v) {
            super(v);
            v.setTag(getAdapterPosition());
            v.setOnClickListener(this);
            this.mImageView = (ImageView) v.findViewById(R.id.image);
        }

        @Override
        public void onClick(View v) {
            this.v = v;
            mIRecyclerViewClickListener.onItemClick(getAdapterPosition());
        }
    }


}

1
viewHolder 생성자에서 이미지를 회전해야하는지 알려주는 속성을 추가 한 다음 데이터에서 해당 속성을 변경하고 notifyDataSetChanged를 호출하여 recyclerView를 다시로드하십시오
Nanoc

어떤 대답이 문제를 해결합니까?
Scott Biggs

성능 문제로 인해 ViewHolder는 정적이어야합니다. 외부 클래스의 모든 변수는 생성자를 통해 전달되어야합니다.
AppiDevo

답변:


149

LinearLayoutManager목록을 표시 하기 위해 a 를 사용한다고 가정 합니다. 그것은 좋은 방법 findViewByPosition이 있습니다

주어진 어댑터 위치를 나타내는 뷰를 찾습니다.

관심있는 항목의 어댑터 위치 만 있으면됩니다.

편집 : 의견 에 Paul Woitaschek이 언급했듯이 모든 LayoutManager (예 : 등) 와 함께 작동 findViewByPosition하는 방법입니다LayoutManagerStaggeredGridLayoutManager


9
LayoutManager이것이 실제로 메소드 이므로 모든 LayoutManager 서브 클래스에서 작동합니다.
Paul Woitaschek

소스 코드를 보았습니다. linearLayoutManger는 사전 레이아웃이 아닌 경우 백업 배열에서 directAccess를 통해 조회하는 반면 recyclerView 메소드는 항상 순회합니다. 따라서이 방법이 더 효율적일 것입니다.
NameSpace

@stanO 이봐 당신 이이 stackoverflow.com/questions/49952965/…

3
반환 값 :
View--

어댑터가 목록에 추가 될 때까지 기다려야합니다. 자세한 내용은 아래 답변을 참조하십시오.
Konstantin Konopko

241

이것은 당신이 찾고있는 것입니다 .

나도이 문제가 있었다. 그리고 당신처럼 대답을 찾기가 매우 어렵습니다. 그러나 특정 위치에서 ViewHolder를 얻는 쉬운 방법이 있습니다 (어댑터에서 많이 할 수있는 일).

myRecyclerView.findViewHolderForAdapterPosition(pos);

참고 : 보기가 재활용 된 경우을 반환 null합니다. 나의 중요한 누락을 빨리 잡아준 Michael에게 감사합니다.


3
이것은 정확히 LayoutManager에서 찾고 있었던 것입니다
Ed Lee

12
그러나 ViewHolder당신이 참조하려고하는 "재활용 된"경우 반환 null됩니다.
Michael

5
@ 마이클, 잘 잡아! 그것은 여러분 모두에게 경고이며, 먼저 null을 테스트하십시오 (예, Android의 다른 모든 것과 마찬가지로)!
Scott Biggs

1
어댑터 내부에서이 작업을 수행 할 수 있습니까?
Mauker

2
@Mauker : RecyclerView 인스턴스에 액세스 할 수있는 모든 항목에서 사용할 수 있습니다.
Scott Biggs

26

을 원하면 다음 과 같이 ViewHolder ViewitemView속성에 액세스하십시오 .myRecyclerView.findViewHolderForAdapterPosition(pos).itemView;


11

둘 다 사용할 수 있습니다

recyclerViewInstance.findViewHolderForAdapterPosition(adapterPosition) 그리고 recyclerViewInstance.findViewHolderForLayoutPosition(layoutPosition). RecyclerView보기는 두 가지 유형의 위치를 ​​사용하십시오.

어댑터 위치 : 어댑터에서 항목의 위치입니다. 이것이 어댑터의 관점에서의 위치입니다. 레이아웃 위치 : 최신 레이아웃 계산에서 항목의 위치입니다. 이것이 LayoutManager의 관점에서의 위치입니다. 당신은 사용해야 getAdapterPosition()위해 findViewHolderForAdapterPosition(adapterPosition)getLayoutPosition()위해 findViewHolderForLayoutPosition(layoutPosition).

사용자가 처음 클릭하는지 여부를 확인하기 위해 recyclerview 어댑터 및 기타 멤버 변수에서 이전에 선택한 항목 위치를 보유하도록 멤버 변수를 가져 오십시오.

하단에 자세한 정보를 제공하기 위해 샘플 코드와 스크린 샷이 첨부되어 있습니다.

public class MainActivity extends AppCompatActivity {     

private RecyclerView mRecyclerList = null;    
private RecyclerAdapter adapter = null;    

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

    mRecyclerList = (RecyclerView) findViewById(R.id.recyclerList);    
}    

@Override    
protected void onStart() {    
    RecyclerView.LayoutManager layoutManager = null;    
    String[] daysArray = new String[15];    
    String[] datesArray = new String[15];    

    super.onStart();    
    for (int i = 0; i < daysArray.length; i++){    
        daysArray[i] = "Sunday";    
        datesArray[i] = "12 Feb 2017";    
    }    

    adapter = new RecyclerAdapter(mRecyclerList, daysArray, datesArray);    
    layoutManager = new LinearLayoutManager(MainActivity.this);    
    mRecyclerList.setAdapter(adapter);    
    mRecyclerList.setLayoutManager(layoutManager);    
}    
}    


public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyCardViewHolder>{          

private final String TAG = "RecyclerAdapter";        
private Context mContext = null;        
private TextView mDaysTxt = null, mDateTxt = null;    
private LinearLayout mDateContainerLayout = null;    
private String[] daysArray = null, datesArray = null;    
private RecyclerView mRecyclerList = null;    
private int previousPosition = 0;    
private boolean flagFirstItemSelected = false;    

public RecyclerAdapter(RecyclerView mRecyclerList, String[] daysArray, String[] datesArray){    
    this.mRecyclerList = mRecyclerList;    
    this.daysArray = daysArray;    
    this.datesArray = datesArray;    
}    

@Override    
public MyCardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {    
    LayoutInflater layoutInflater = null;    
    View view = null;    
    MyCardViewHolder cardViewHolder = null;    
    mContext = parent.getContext();    
    layoutInflater = LayoutInflater.from(mContext);    
    view = layoutInflater.inflate(R.layout.date_card_row, parent, false);    
    cardViewHolder = new MyCardViewHolder(view);    
    return cardViewHolder;    
}    

@Override    
public void onBindViewHolder(MyCardViewHolder holder, final int position) {    
    mDaysTxt = holder.mDaysTxt;    
    mDateTxt = holder.mDateTxt;    
    mDateContainerLayout = holder.mDateContainerLayout;    

    mDaysTxt.setText(daysArray[position]);    
    mDateTxt.setText(datesArray[position]);    

    if (!flagFirstItemSelected){    
        mDateContainerLayout.setBackgroundColor(Color.GREEN);    
        flagFirstItemSelected = true;    
    }else {    
        mDateContainerLayout.setBackground(null);    
    }    
}    

@Override    
public int getItemCount() {    
    return daysArray.length;    
}    

class MyCardViewHolder extends RecyclerView.ViewHolder{    
    TextView mDaysTxt = null, mDateTxt = null;    
    LinearLayout mDateContainerLayout = null;    
    LinearLayout linearLayout = null;    
    View view = null;    
    MyCardViewHolder myCardViewHolder = null;    

    public MyCardViewHolder(View itemView) {    
        super(itemView);    
        mDaysTxt = (TextView) itemView.findViewById(R.id.daysTxt);    
        mDateTxt = (TextView) itemView.findViewById(R.id.dateTxt);    
        mDateContainerLayout = (LinearLayout) itemView.findViewById(R.id.dateContainerLayout);    

        mDateContainerLayout.setOnClickListener(new View.OnClickListener() {    
            @Override    
            public void onClick(View v) {    
                LinearLayout linearLayout = null;    
                View view = null;    

                if (getAdapterPosition() == previousPosition){    
                    view = mRecyclerList.findViewHolderForAdapterPosition(previousPosition).itemView;    
                    linearLayout = (LinearLayout) view.findViewById(R.id.dateContainerLayout);    
                    linearLayout.setBackgroundColor(Color.GREEN);    
                    previousPosition = getAdapterPosition();    

                }else {    
                    view = mRecyclerList.findViewHolderForAdapterPosition(previousPosition).itemView;    
                    linearLayout = (LinearLayout) view.findViewById(R.id.dateContainerLayout);    
                    linearLayout.setBackground(null);    

                    view = mRecyclerList.findViewHolderForAdapterPosition(getAdapterPosition()).itemView;    
                    linearLayout = (LinearLayout) view.findViewById(R.id.dateContainerLayout);    
                    linearLayout.setBackgroundColor(Color.GREEN);    
                    previousPosition = getAdapterPosition();    
                }    
            }    
        });    
    }    
}       

} 선택된 첫 번째 요소 두 번째 요소가 선택되고 이전에 선택한 항목이 선택되지 않습니다 다섯 번째 요소가 선택되고 이전에 선택한 항목이 선택되지 않습니다


그리고 나는이 토론이 소진되었다고 생각했습니다! 이 문제를 자세히 설명해 주셔서 감사합니다.
Scott Biggs

2
이전 항목의 색상을 변경하려고 할 때 else 블록에 NullPointer 예외가 발생하므로 null 검사를 추가 했으므로 NullPointer 예외가 발생하면 해당 블록에 절대 들어 가지 않으므로 이전 항목 색상 변경되지 않습니다. 이제 Recycler보기에는 여러 색상의 항목이있는 항목이 있습니다. 이 문제를 해결하는 방법
Abhilash Reddy

8

ViewHolder의 ArrayList를 만들 수 있습니다.

 ArrayList<MyViewHolder> myViewHolders = new ArrayList<>();
 ArrayList<MyViewHolder> myViewHolders2 = new ArrayList<>();

모든 ViewHolder를 다음과 같은 목록에 저장합니다.

 @Override
    public void onBindViewHolder(@NonNull final MyViewHolder holder, final int position) {
        final String str = arrayList.get(position);

        myViewHolders.add(position,holder);
}

필요에 따라 ArrayList에 다른 ViewHolder를 추가 / 제거하십시오.


이틀 동안 재활용 보유자를 확보하기 위해 고심 해 주셔서 감사합니다.
nimi0112

5

다음을 사용하여 recyclerview에서 특정 위치를 볼 수 있습니다.

int position = 2;
RecyclerView.ViewHolder viewHolder = recyclerview.findViewHolderForItemId(position);
View view = viewHolder.itemView;
ImageView imageView = (ImageView)view.findViewById(R.id.imageView);

5

리사이클 뷰의 " findViewHolderForAdapterPosition "메소드를 사용 하면 해당 뷰 홀더에서 viewHolder 객체를 가져 와서 해당 뷰 홀더를 어댑터 뷰 홀더에 타입 캐스트하여 뷰 홀더의 뷰에 직접 액세스 할 수 있습니다

다음은 kotlin의 샘플 코드입니다

 val viewHolder = recyclerView.findViewHolderForAdapterPosition(position)
 val textview=(viewHolder as YourViewHolder).yourTextView

4

어댑터가 목록에 추가 될 때까지 기다려야합니다. 그러면 위치별로보기를 시도 할 수 있습니다.

final int i = 0;
recyclerView.setAdapter(adapter);
recyclerView.post(new Runnable() {
    @Override
    public void run() {
        View view = recyclerView.getLayoutManager().findViewByPosition(i);
    }
});

2
여러 항목을 추가하는 경우 (예 : 항목을 추가하고 빠르게 누르는 버튼이있는 경우) 항상 작동하지는 않습니다. 실행 가능 파일을 지연과 함께 추가해야합니다.
Alex Burdusel 19

3

recyclerView의 특정 위치에서보기를 얻으려면 recyclerView.ViewHolder를 반환하는 recyclerView 객체에서 findViewHolderForAdapterPosition (position)을 호출해야합니다

itemView를 사용하여 반환 된 RecyclerView.ViewHolder 객체에서 특정 위치의 모든 뷰에 액세스 할 수 있습니다

RecyclerView.ViewHolder rv_view = recyclerView.findViewHolderForAdapterPosition(position);

ImageView iv_wish = rv_view.itemView.findViewById(R.id.iv_item);

1

이 작업을 수행 할 수도 있습니다. 이것은 recyclerview 위치 항목을 클릭 한 후보기를 수정하려고 할 때 도움이됩니다.

@Override
public void onClick(View view, int position) {

            View v =  rv_notifications.getChildViewHolder(view).itemView;
            TextView content = v.findViewById(R.id.tv_content);
            content.setText("Helloo");

        }

1

리사이클 뷰 목록에서 특정 뷰를 가져 오거나 리사이클 뷰의 편집 텍스트에서 오류를 표시합니다.

private void popupErrorMessageAtPosition(int itemPosition) {

    RecyclerView.ViewHolder viewHolder = recyclerView.findViewHolderForAdapterPosition(itemPosition);
    View view = viewHolder.itemView;
    EditText etDesc = (EditText) view.findViewById(R.id.et_description);
    etDesc.setError("Error message here !");
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.