2014-10-29 10 views
19

Ich versuche, einen Swipe zu implementieren, um Aktion in einem RecyclerView zu verwerfen, aber wenn ich einen OnClickListener auf eine beliebige Ansicht in einem ViewHolder setzt überschreibt es alle OnTouch Ereignisse in dieser Ansicht.Swipe und OnClick Ereignisse in RecyclerView

Ich kann OnClickListener verlassen und alle Klicks in der TouchListener behandeln, aber wenn ich mehrere Schaltflächen in einer untergeordneten Ansicht des RecycleView als das wird eine Menge Code sein und das sieht nicht wie ein richtiger Weg.

In meinem RecyleView Ich gründe Swipe Zuhörer zu entlassen (similar to this):

setOnTouchListener(touchListener); 
    setOnScrollListener(touchListener.makeScrollListener()); 

Es funktioniert in der Listview, aber in den RecycleView die OnClickListener Blöcke OnTouchListner Ereignisse.

Beispiel für das Layout der ViewHolder-Ansicht.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
android:id="@+id/card_title" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:minHeight="72dp" 
android:descendantFocusability="blocksDescendants"> 

<ImageView 
    android:id="@+id/keep_icon" 
    android:layout_width="48dp" 
    android:layout_height="48dp" 
    android:layout_centerInParent="true" 
    android:src="@drawable/ic_received" /> 

im RecyclerView.Adapter Aufpumpen:

@Override 
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { 
    View v = mInflater.inflate(R.layout.push_card_view_compat, viewGroup, false); 
    return new ViewHolder(v, onClickListener, onKeepListener); 
} 

The ViewHolder:

public ViewHolder(final View itemView, 
        final OnViewHolderClickListener onClickListener, 
        final OnKeepListener onKeepListener) { 
    super(itemView); 
    keepButton = (ImageView) itemView.findViewById(R.id.keep_icon); 

    itemView.setOnClickListener(new View.OnClickListener() { 
    @Override 
    public void onClick(View v) { 
     onItemClickListener.onClick(getPosition(), itemView); 
    } 
    }); 
    keepButton.setOnClickListener(new View.OnClickListener() { 
    @Override 
    public void onClick(View v) { 
     onKeepListener.onClick(getPosition(), itemView); 
    } 
    }); 
} 
+1

posten Sie Ihren Code dann – pskink

+0

warum viele Codes? –

+0

Ich habe Code hinzugefügt. –

Antwort

22

I erreicht, dass durch in den ViewHolderOnClickListener für die Tasten Zuweisen und Erstellen eine Schnittstelle für die Berührungsereignisse.

Das Beispielprojekt ist auf GitHub: https://github.com/brnunes/SwipeableRecyclerView.

In meinem Fall jedes Element ist ein CardView mit zwei Tasten, und ich mag die Touch-Ereignisse in den CardView und die Button s erkennen. Das CardView Layout sieht folgendermaßen aus:

<?xml version="1.0" encoding="utf-8"?> 
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:card_view="http://schemas.android.com/apk/res-auto" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_margin="5dp" 
    android:clickable="true" 
    android:foreground="?android:attr/selectableItemBackground" 
    android:orientation="vertical" 
    card_view:cardCornerRadius="5dp"> 

    <RelativeLayout 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"> 

     <TextView 
      android:id="@+id/card_view_title" 
      android:layout_width="match_parent" 
      android:layout_height="50dp" 
      android:layout_alignParentTop="true" 
      android:layout_centerHorizontal="true" 
      android:gravity="center" 
      android:textColor="@android:color/black" 
      android:textSize="24sp" /> 

     <LinearLayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:layout_alignParentBottom="true" 
      android:layout_below="@id/card_view_title" 
      android:layout_centerHorizontal="true" 
      android:gravity="center"> 

      <Button 
       android:id="@+id/card_view_button1" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:text="Button1" /> 

      <Button 
       android:id="@+id/card_view_button2" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:text="Button2" /> 
     </LinearLayout> 
    </RelativeLayout> 

</android.support.v7.widget.CardView> 

Dann in den Activity ich eine Schnittstelle erklärte die Berührungsereignisse zu empfangen:

public interface OnItemTouchListener { 
    public void onCardViewTap(View view, int position); 
    public void onButton1Click(View view, int position); 
    public void onButton2Click(View view, int position); 
} 

Und im ViewHolder ich zuweisen OnClickListeners zu den Objekten, die ich will hören, und rufen Sie meine Gewohnheit Zuhörer:

public class CardViewAdapter extends RecyclerView.Adapter<CardViewAdapter.ViewHolder> { 
    private List<String> cards; 
    private OnItemTouchListener onItemTouchListener; 

    public CardViewAdapter(List<String> cards, OnItemTouchListener onItemTouchListener) { 
     this.cards = cards; 
     this.onItemTouchListener = onItemTouchListener; 
    } 

    @Override 
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { 
     View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_view_layout, viewGroup, false); 
     return new ViewHolder(v); 
    } 

    @Override 
    public void onBindViewHolder(ViewHolder viewHolder, int i) { 
     viewHolder.title.setText(cards.get(i)); 
    } 

    @Override 
    public int getItemCount() { 
     return cards == null ? 0 : cards.size(); 
    } 

    public class ViewHolder extends RecyclerView.ViewHolder { 
     private TextView title; 
     private Button button1; 
     private Button button2; 

     public ViewHolder(View itemView) { 
      super(itemView); 
      title = (TextView) itemView.findViewById(R.id.card_view_title); 
      button1 = (Button) itemView.findViewById(R.id.card_view_button1); 
      button2 = (Button) itemView.findViewById(R.id.card_view_button2); 

      button1.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        onItemTouchListener.onButton1Click(v, getPosition()); 
       } 
      }); 

      button2.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        onItemTouchListener.onButton2Click(v, getPosition()); 
       } 
      }); 

      itemView.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        onItemTouchListener.onCardViewTap(v, getPosition()); 
       } 
      }); 
     } 
    } 
} 

Schließlich instanziiert die benutzerdefinierte OnItemTouchListener und an den CardViewAdapter Konstruktor übergeben:

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

    mItems = new ArrayList<>(30); 
    for (int i = 0; i < 30; i++) { 
     mItems.add(String.format("Card number %2d", i)); 
    } 

    OnItemTouchListener itemTouchListener = new OnItemTouchListener() { 
     @Override 
     public void onCardViewTap(View view, int position) { 
      Toast.makeText(MainActivity.this, "Tapped " + mItems.get(position), Toast.LENGTH_SHORT).show(); 
     } 

     @Override 
     public void onButton1Click(View view, int position) { 
      Toast.makeText(MainActivity.this, "Clicked Button1 in " + mItems.get(position), Toast.LENGTH_SHORT).show(); 
     } 

     @Override 
     public void onButton2Click(View view, int position) { 
      Toast.makeText(MainActivity.this, "Clicked Button2 in " + mItems.get(position), Toast.LENGTH_SHORT).show(); 
     } 
    }; 

    mAdapter = new CardViewAdapter(mItems, itemTouchListener); 

    mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); 

    mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); 
    mRecyclerView.setAdapter(mAdapter); 

    // ... Assign the swipe listener 
} 
+0

Ich wünschte, ich könnte das eine Million Male abstimmen! Mein Scrollen ist immer noch ein wenig gestaffelt, weil Bilder geladen werden ... jeder Rat wäre großartig. : \ – marienke

+1

Die Lösung besteht darin, das Bild asynchron in einer AsyncTask in den Speicher zu laden und es dann in ImageView anzuzeigen. Überprüfen Sie diesen Artikel http://developer.android.com/training/improving-layouts/smooth-scrolling.html#AsyncTask. Dieser Beitrag spricht auch über Async-Laden. Im Beispiel werden die Bilder aus dem Internet heruntergeladen, aber es ist noch einfacher, wenn Sie sie lokal laden: http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html – brnunes

+0

danke dafür . – Tuss

Verwandte Themen