2015-11-18 11 views
59

Ich habe eine Aktivität mit einem RecyclerView und einem ImageView. Ich verwende die 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. Bis jetzt funktioniert alles gut.RecyclerView - Holen Sie sich Blick auf bestimmte Position

Jetzt gibt es zwei weitere ImageButtons in der Aktivität: imageButton_left und imageButton_right. Wenn ich auf imageButton_left klicke, sollte das Bild in der ImageView nach links abbiegen und auch das Thumbnail in der RecyclerView sollte diese Änderung widerspiegeln. Ähnlich ist der Fall mit imageButton_right.

Ich bin in der Lage, die ImageView zu drehen. Aber wie kann ich das Thumbnail in der RecyclerView drehen? Wie kann ich die ViewHolderImageView bekommen?

Code:

XML Aktivität:

<?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> 

My Activity-Code:

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); 
    } 
} 

My Custom 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()); 
     } 
    } 


} 
+1

Sie sollten es in Ihrem viewHolder Konstruktor machen, eine Eigenschaft hinzufügen, die Ihnen sagen, wenn das Bild gedreht werden muss, dann ändern Sie einfach diese Eigenschaft auf Ihre Daten und Rufen Sie notifyDataSetChanged auf, um das recyclerView neu laden zu lassen. – Nanoc

+0

Führt eine der Antworten zu Ihrem Problem? –

+0

ViewHolder sollte für Leistungsprobleme statisch sein. Alle Variablen aus der äußeren Klasse sollten über den Konstruktor übergeben werden. – AppiDevo

Antwort

73

Ich nehme an, Sie ein verwenden LinearLayoutManager um die Liste zu zeigen. Es hat eine schöne Methode namens findViewByPosition, dass

Findet die Ansicht, die die angegebene Adapterposition darstellt.

Alles, was Sie brauchen, ist die Adapterposition des Elements Sie interessiert sind

bearbeiten. Wie Paul Woitaschek in den Kommentaren erwähnt, findViewByPosition ein Verfahren zur Herstellung LayoutManager ist so würde es funktionieren mit allen LayoutManagern (zB StaggeredGridLayoutManager, usw.)

+3

Das ist eigentlich eine Methode der 'LayoutManager', so dass dies für alle LayoutManager-Unterklassen funktioniert. –

+0

Blick auf den Quellcode. LinearLayoutManger sucht über directAccess nach dem Backing-Array, wenn es nicht im Prelayout ist, während die RecyclerView-Methode immer eine Traversierung durchführt. Also ist diese Methode wahrscheinlich effizienter. – NameSpace

123

Das ist es, was Sie suchen.

Ich hatte dieses Problem auch. Und wie Sie ist die Antwort sehr schwer zu finden. Aber es gibt einen einfachen Weg, um den ViewHolder von einer bestimmten Position zu bekommen (etwas, das Sie wahrscheinlich viel im Adapter tun werden).

myRecyclerView.findViewHolderForAdapterPosition(pos);

HINWEIS: Wenn die Ansicht recycelt wurde, wird dies null zurück. Danke an Michael, dass er meine wichtige Lücke schnell gefunden hat.

+3

Dies ist genau das, was ich im LayoutManager gesucht habe –

+3

Dies funktioniert jedoch, wenn der 'ViewHolder', auf den Sie verweisen möchten," recycelt "wurde, wird' null' zurückgegeben. – Michael

+0

@Michael, guter Fang! Das ist eine Warnung an euch alle, testet zuerst auf null (ja, wie alles andere in Android)! –

13

Wenn Sie die View wollen, stellen Sie sicher, wie so die itemView Eigenschaft des ViewHolder zuzugreifen: myRecyclerView.findViewHolderForAdapterPosition(pos).itemView;

6

Sie sowohl

recyclerViewInstance.findViewHolderForAdapterPosition(adapterPosition) und recyclerViewInstance.findViewHolderForLayoutPosition(layoutPosition) verwenden können. Stellen Sie sicher, dass die RecyclerView-Ansicht zwei Arten von Positionen verwendet:

Adapterposition: Position eines Elements im Adapter. Dies ist die Position aus der Sicht des Adapters. Layoutposition: Position eines Artikels in der letzten Layoutberechnung. Dies ist die Position aus der Perspektive des LayoutManagers. Sie sollten getAdapterPosition() für findViewHolderForAdapterPosition(adapterPosition) und getLayoutPosition() für findViewHolderForLayoutPosition(layoutPosition) verwenden.

Verwenden Sie eine Elementvariable, um die zuvor ausgewählte Elementposition im recyclerview-Adapter und anderen Elementvariablen zu speichern, um zu überprüfen, ob der Benutzer zum ersten Mal klickt oder nicht.

Beispielcode und Screenshots sind für weitere Informationen am unteren Rand beigefügt.

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();  
       }  
      }  
     });  
    }  
}  

} first element selected second element selected and previously selected item becomes unselected fifth element selected and previously selected item becomes unselected

+0

Und ich dachte, diese Diskussion war erschöpft! Vielen Dank für die weitere Klärung dieses Problems. –

Verwandte Themen