RecyclerView - просмотр в определенном положении
У меня есть активность с RecyclerView
и ImageView
. Я использую RecyclerView
для отображения списка изображений по горизонтали. Когда я нажимаю на изображение в RecyclerView
, в ImageView
в действии должен отображаться больший снимок изображения. Пока все работает нормально.
Теперь в деятельности есть еще два ImageButtons
: imageButton_left
и imageButton_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
Предположим, вы используете LinearLayoutManager
, чтобы отобразить список. Он имеет хороший метод findViewByPosition
, который
Находит вид, который представляет заданную позицию адаптера.
Все, что вам нужно, это позиция адаптера интересующего вас элемента.
edit: как отметил Пол Уиташек в комментариях, findViewByPosition
- это метод LayoutManager
, поэтому он будет работать со всеми макетами LayoutManager (т.е. StaggeredGridLayoutManager
и т.д.)
Ответ 2
Это то, что вы ищете.
У меня тоже была эта проблема. И, как и вы, ответ очень трудно найти. Но есть простой способ получить ViewHolder с определенной позиции (что-то, что вы, вероятно, сделаете много в адаптере).
myRecyclerView.findViewHolderForAdapterPosition(pos);
ПРИМЕЧАНИЕ. Если представление было переработано, это вернет null
. Спасибо Майклу за то, что он быстро поймал мое важное упущение.
Ответ 3
Если вы хотите View
, обязательно получите доступ к свойству itemView
для ViewHolder следующим образом: myRecyclerView.findViewHolderForAdapterPosition(pos).itemView;
Ответ 4
Вы можете использовать как
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();
}
}
});
}
}
}
![fifth element selected and previously selected item becomes unselected]()
Ответ 5
Вы можете создать ArrayList для ViewHolder:
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);
}
и добавьте/удалите другой ViewHolder в ArrayList согласно вашему требованию.
Ответ 6
Вы можете получить представление об определенной позиции в обзоре переработчика, используя следующую
int position = 2;
RecyclerView.ViewHolder viewHolder = recyclerview.findViewHolderForItemId(position);
View view = viewHolder.itemView;
ImageView imageView = (ImageView)view.findViewById(R.id.imageView);
Ответ 7
Имейте в виду, что вам нужно подождать, пока адаптер будет добавлен в список, затем вы можете попытаться получить представление по позиции
final int i = 0;
recyclerView.setAdapter(adapter);
recyclerView.post(new Runnable() {
@Override
public void run() {
View view = recyclerView.getLayoutManager().findViewByPosition(i);
}
});
Ответ 8
Вы можете просто использовать метод findViewHolderForAdapterPosition"для представления рециркулятора, и вы получите объект viewHolder из этого, а затем вставьте этот видовой держатель в свой видоискатель адаптера, чтобы иметь прямой доступ к представлениям своих виджетов
Ниже приведен пример кода для Kotlin
val viewHolder = recyclerView.findViewHolderForAdapterPosition(position)
val textview=(viewHolder as YourViewHolder).yourTextView
Ответ 9
Вы также можете сделать это, это поможет вам, когда вы захотите изменить вид после щелчка по элементу позиции повторного просмотра
@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");
}
Ответ 10
Чтобы получить конкретный вид из списка представлений переработчика, ИЛИ показать ошибку при редактировании текста представления переработчика.
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 !");
}