2015-11-18 24 views
59

Ho un'attività con uno RecyclerView e uno ImageView. Sto usando il RecyclerView per mostrare un elenco di immagini in orizzontale. Quando clicco su un'immagine nello RecyclerView l'attività ImageView nell'attività dovrebbe mostrare un'immagine più grande dell'immagine. Finora tutto funziona bene.RecyclerView - Visualizza in una posizione particolare

Ora ci sono altri due ImageButtons nell'attività: imageButton_left e imageButton_right. Quando clicco su imageButton_left, l'immagine nel ImageView dovrebbe girare a sinistra e anche, la miniatura nel RecyclerView dovrebbe riflettere questa modifica. Simile è il caso con imageButton_right.

Sono in grado di ruotare lo ImageView. Ma, come posso ruotare la miniatura nello RecyclerView? Come posso ottenere lo ImageViewImageView?

Codice:

XML attività:

<?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 Code attività:

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

mio adattatore personalizzato per 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

Si dovrebbe fare nel costruttore viewHolder, aggiungere una proprietà che vi dirà se l'immagine deve essere ruotata, quindi basta cambiare la proprietà sui dati e chiama notifyDataSetChanged per ricaricare il recyclerView – Nanoc

+0

Una delle risposte risolve il problema? –

+0

ViewHolder deve essere statico per problemi di prestazioni. Tutte le variabili della classe esterna devono essere passate attraverso il costruttore. – AppiDevo

risposta

73

Suppongo che si sta utilizzando un LinearLayoutManager per mostrare la lista. Ha un bel metodo chiamato findViewByPosition che

Trova la vista che rappresenta la posizione dell'adattatore data.

Tutto ciò che serve è la posizione dell'adattatore della voce che si interessa

modificare:. Come osservato da Paul Woitaschek nei commenti, findViewByPosition è un metodo di LayoutManager in modo che avrebbe funzionato con tutti i LayoutManager (es. StaggeredGridLayoutManager, ecc.)

+3

Questo è in realtà un metodo del 'LayoutManager' quindi funzionerà con tutte le sottoclassi di LayoutManager. –

+0

Guardato il codice sorgente. LinearLayoutManger ricerca tramite directAccess sul backing array quando non è in prelayout, mentre il metodo recyclerView esegue sempre il crossover. Quindi questo metodo è probabilmente più efficiente. – NameSpace

123

Questo è quello che stai cercando.

Ho avuto anche questo problema. E come te, la risposta è molto difficile da trovare. Ma c'è un modo semplice per ottenere ViewHolder da una posizione specifica (qualcosa che probabilmente farai molto nell'Adapter).

myRecyclerView.findViewHolderForAdapterPosition(pos);

NOTA: Se la vista è stato riciclato, questo tornerà null. Grazie a Michael per aver colto rapidamente la mia importante omissione.

+3

Questo è esattamente quello che stavo cercando nel LayoutManager –

+3

Questo funziona, tuttavia, se il 'ViewHolder' che si sta tentando di fare riferimento è stato" riciclato ", restituirà' null'. – Michael

+0

@ Michael, buona presa! Questo è un avvertimento per tutti voi là fuori, testare prima null (sì, come tutto il resto in Android)! –

13

Se si desidera che il View, assicurarsi di accedere alla proprietà itemView del ViewHolder in questo modo: myRecyclerView.findViewHolderForAdapterPosition(pos).itemView;

6

È possibile utilizzare l'uso sia

recyclerViewInstance.findViewHolderForAdapterPosition(adapterPosition) e recyclerViewInstance.findViewHolderForLayoutPosition(layoutPosition). Assicurarsi che la vista RecyclerView utilizzi due tipi di posizioni

Posizione adattatore: posizione di un articolo nell'adattatore. Questa è la posizione dalla prospettiva dell'adapter. Posizione layout: posizione di un oggetto nell'ultimo calcolo del layout. Questa è la posizione dal punto di vista di LayoutManager. È necessario utilizzare getAdapterPosition() per findViewHolderForAdapterPosition(adapterPosition) e getLayoutPosition() per findViewHolderForLayoutPosition(layoutPosition).

Prendere una variabile membro per mantenere la posizione dell'elemento selezionato in precedenza nell'adattatore recyclerview e un'altra variabile membro per verificare se l'utente fa clic per la prima volta oppure no.

Il codice di esempio e le schermate sono allegati per ulteriori informazioni nella parte inferiore.

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

E ho pensato che questa discussione fosse esaurita! Grazie per chiarire ulteriormente questo problema. –

Problemi correlati