Ich habe eine Aktivität mit einem RecyclerView
und einem ImageView
. Ich verwende RecyclerView
, um eine Liste von Bildern horizontal anzuzeigen. Wenn ich auf ein Bild in der RecyclerView
klicke, sollte die ImageView
in der Aktivität ein größeres Bild des Bildes zeigen. Bisher funktioniert alles gut.
Nun gibt es zwei weitere ImageButtons
in der Aktivität: imageButton_left
und imageButton_right
. Wenn ich auf imageButton_left
klicke, sollte das Bild in ImageView
nach links abbiegen, und auch das Miniaturbild in RecyclerView
sollte diese Änderung widerspiegeln. Ähnlich ist es bei imageButton_right
.
Ich kann das ImageView
drehen. Aber wie kann ich die Miniaturansicht in RecyclerView
drehen? Wie bekomme ich die ViewHolder
der ImageView
?
Code:
Aktivitäts-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>
Mein Aktivitätscode:
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);
}
}
Mein benutzerdefinierter Adapter für 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());
}
}
}
Ich nehme an, Sie verwenden eine LinearLayoutManager
, um die Liste anzuzeigen. Es hat eine Nice-Methode namens findViewByPosition
das
Sucht die Ansicht, die die angegebene Adapterposition darstellt.
Sie benötigen lediglich die Adapterposition des Artikels, an dem Sie interessiert sind.
edit: Wie in den Kommentaren von Paul Woitaschek festgestellt wurde, ist findViewByPosition
eine Methode von LayoutManager
, also würde es mit allen LayoutManagern funktionieren (d. h. StaggeredGridLayoutManager
usw.).
Das ist was du suchst.
Ich hatte auch dieses Problem. Und wie Sie ist die Antwort sehr schwer zu finden. Aber es gibt IS eine einfache Möglichkeit, den ViewHolder von einer bestimmten Position aus abzurufen (etwas, das Sie im Adapter wahrscheinlich häufig tun werden).
myRecyclerView.findViewHolderForAdapterPosition(pos);
HINWEIS: Wenn die Ansicht wiederverwendet wurde, wird null
zurückgegeben. Vielen Dank an Michael für das schnelle Auffinden meiner wichtigen Lücke.
Wenn Sie die Variable View
wünschen, stellen Sie sicher, dass Sie wie folgt auf die Eigenschaft itemView
des ViewHolder zugreifen: myRecyclerView.findViewHolderForAdapterPosition(pos).itemView;
Sie können beide verwenden
recyclerViewInstance.findViewHolderForAdapterPosition(adapterPosition)
und recyclerViewInstance.findViewHolderForLayoutPosition(layoutPosition)
. Stellen Sie sicher, dass die Ansicht RecyclerView zwei Arten von Positionen verwendet
Adapterposition: Position eines Artikels im Adapter. Dies ist die Position aus der Perspektive des Adapters . Layoutposition: Position eines Elements in der letzten Layoutberechnung. Dies ist die Position aus der Sicht des LayoutManagers .. __ Sie sollten getAdapterPosition()
für findViewHolderForAdapterPosition(adapterPosition)
und getLayoutPosition()
für findViewHolderForLayoutPosition(layoutPosition)
verwenden.
Nehmen Sie eine Membervariable, um die zuvor ausgewählte Artikelposition im Recyclerviewadapter und eine andere Membervariable zu speichern, um zu prüfen, ob der Benutzer zum ersten Mal klickt oder nicht.
Beispielcode und Screenshots für weitere Informationen finden Sie unten.
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();
}
}
});
}
}
Sie können ArrayList aus ViewHolder erstellen:
ArrayList<MyViewHolder> myViewHolders = new ArrayList<>();
ArrayList<MyViewHolder> myViewHolders2 = new ArrayList<>();
und alle ViewHolder in der Liste speichern:
@Override
public void onBindViewHolder(@NonNull final MyViewHolder holder, final int position) {
final String str = arrayList.get(position);
myViewHolders.add(position,holder);
}
und fügen Sie weitere ViewHolder in der ArrayList hinzu bzw. entfernen Sie sie entsprechend Ihrer Anforderung.
Sie können einfach die Methode "findViewHolderForAdapterPosition" der Recycler-Ansicht verwenden, und Sie erhalten ein viewHolder-Objekt, von dem Sie diesen Viewholder in Ihren Adapter-Viewholder typisieren, sodass Sie direkt auf die Views Ihres Viewholder zugreifen können
es folgt der Beispielcode für kotlin
val viewHolder = recyclerView.findViewHolderForAdapterPosition(position)
val textview=(viewHolder as YourViewHolder).yourTextView
Sie können dies auch tun. Dies ist hilfreich, wenn Sie eine Ansicht ändern möchten, nachdem Sie auf ein Recyclingelement geklickt haben
@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");
}
Sie können eine Ansicht für eine bestimmte Position in einer Recyclingübersicht erhalten, indem Sie Folgendes verwenden
int position = 2;
RecyclerView.ViewHolder viewHolder = recyclerview.findViewHolderForItemId(position);
View view = viewHolder.itemView;
ImageView imageView = (ImageView)view.findViewById(R.id.imageView);
Denken Sie daran, dass Sie warten müssen, bis der Adapter zur Liste hinzugefügt wird. Dann können Sie versuchen, die Ansicht nach Position anzuzeigen
final int i = 0;
recyclerView.setAdapter(adapter);
recyclerView.post(new Runnable() {
@Override
public void run() {
View view = recyclerView.getLayoutManager().findViewByPosition(i);
}
});
Um eine bestimmte Ansicht aus der Liste der Recycler-Ansichten zu erhalten, OR zeigt Fehler im nächsten Fenster der Recycler-Ansicht an.
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 !");
}