2016-08-01 34 views
-2

In diesem picture können Sie eine CardView sehen, in der jedes Element nacheinander angezeigt wird. Ich habe eine Touch-Funktionalität implementiert, die durch den Datensatz scrollt. Ich möchte nun die Funktionalität der zufälligen Auswahl eines Gegenstands implementieren. Hier ist, wo die CardView gesetzt:Wählen Sie ein beliebiges Element in CardView

package com.chiemy.cardview.view; 

import android.content.Context; 
import android.database.DataSetObserver; 
import android.graphics.Rect; 
import android.util.AttributeSet; 
import android.util.SparseArray; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.ViewConfiguration; 
import android.view.animation.AccelerateInterpolator; 
import android.widget.FrameLayout; 
import android.widget.ListAdapter; 

import com.nineoldandroids.animation.Animator; 
import com.nineoldandroids.animation.AnimatorListenerAdapter; 
import com.nineoldandroids.view.ViewHelper; 
import com.nineoldandroids.view.ViewPropertyAnimator; 

/** 
* @author chiemy 
* 
*/ 
public class CardView extends FrameLayout { 
    private static final int ITEM_SPACE = 40; 
    private static final int DEF_MAX_VISIBLE = 4; 

    private int mMaxVisible = DEF_MAX_VISIBLE; 
    private int itemSpace = ITEM_SPACE; 

    private float mTouchSlop; 
    private ListAdapter mListAdapter; 
    private int mNextAdapterPosition; 
    private SparseArray<View> viewHolder = new SparseArray<View>(); 
    private OnCardClickListener mListener; 
    private int topPosition; 
    private Rect topRect; 

    public interface OnCardClickListener { 
     void onCardClick(View view, int position); 
    } 

    public CardView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     init(); 
    } 

    public CardView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(); 
    } 

    public CardView(Context context) { 
     super(context); 
     init(); 
    } 

    private void init() { 
     topRect = new Rect(); 
     ViewConfiguration con = ViewConfiguration.get(getContext()); 
     mTouchSlop = con.getScaledTouchSlop(); 
    } 

    public void setMaxVisibleCount(int count) { 
     mMaxVisible = count; 
    } 

    public int getMaxVisibleCount() { 
     return mMaxVisible; 
    } 

    public void setItemSpace(int itemSpace) { 
     this.itemSpace = itemSpace; 
    } 

    public int getItemSpace() { 
     return itemSpace; 
    } 

    public ListAdapter getAdapter() { 
     return mListAdapter; 
    } 

    public void setAdapter(ListAdapter adapter) { 
     if (mListAdapter != null) { 
      mListAdapter.unregisterDataSetObserver(mDataSetObserver); 
     } 
     mNextAdapterPosition = 0; 
     mListAdapter = adapter; 
     adapter.registerDataSetObserver(mDataSetObserver); 
     removeAllViews(); 
     ensureFull(); 
    } 

    public void setOnCardClickListener(OnCardClickListener listener) { 
     mListener = listener; 
    } 

    private void ensureFull() { 
     while (mNextAdapterPosition < mListAdapter.getCount() 
       && getChildCount() < mMaxVisible) { 
      int index = mNextAdapterPosition % mMaxVisible; 
      View convertView = viewHolder.get(index); 
      final View view = mListAdapter.getView(mNextAdapterPosition, 
        convertView, this); 
      view.setOnClickListener(null); 
      viewHolder.put(index, view); 

      index = Math.min(mNextAdapterPosition, mMaxVisible - 1); 
      ViewHelper.setScaleX(view,((mMaxVisible - index - 1)/(float) mMaxVisible) * 0.2f + 0.8f); 
      int topMargin = (mMaxVisible - index - 1) * itemSpace; 
      ViewHelper.setTranslationY(view, topMargin); 
      ViewHelper.setAlpha(view, mNextAdapterPosition == 0 ? 1 : 0.5f); 

      LayoutParams params = (LayoutParams) view.getLayoutParams(); 
      if (params == null) { 
       params = new LayoutParams(LayoutParams.MATCH_PARENT, 
         LayoutParams.WRAP_CONTENT); 
      } 
      addViewInLayout(view, 0, params); 

      mNextAdapterPosition += 1; 
     } 
     // requestLayout(); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     int widthMode = MeasureSpec.getMode(widthMeasureSpec); 
     int heightMode = MeasureSpec.getMode(heightMeasureSpec); 
     int widthSize = MeasureSpec.getSize(widthMeasureSpec); 
     int heightSize = MeasureSpec.getSize(heightMeasureSpec); 

     int childCount = getChildCount(); 
     int maxHeight = 0; 
     int maxWidth = 0; 
     for (int i = 0; i < childCount; i++) { 
      View child = getChildAt(i); 
      this.measureChild(child, widthMeasureSpec, heightMeasureSpec); 
      int height = child.getMeasuredHeight(); 
      int width = child.getMeasuredWidth(); 
      if (height > maxHeight) { 
       maxHeight = height; 
      } 
      if (width > maxWidth) { 
       maxWidth = width; 
      } 
     } 
     int desireWidth = widthSize; 
     int desireHeight = heightSize; 
     if (widthMode == MeasureSpec.AT_MOST) { 
      desireWidth = maxWidth + getPaddingLeft() + getPaddingRight(); 
     } 
     if (heightMode == MeasureSpec.AT_MOST) { 
      desireHeight = maxHeight + (mMaxVisible - 1) * itemSpace + getPaddingTop() + getPaddingBottom(); 
     } 
     setMeasuredDimension(desireWidth, desireHeight); 
    } 

    @Override 
    protected void onLayout(boolean changed, int left, int top, int right, 
      int bottom) { 
     super.onLayout(changed, left, top, right, bottom); 
     View topView = getChildAt(getChildCount() - 1); 
     if (topView != null) { 
      topView.setOnClickListener(listener); 
     } 
    } 

    float downX, downY; 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     switch (event.getAction()) { 
     case MotionEvent.ACTION_MOVE: 
      if (goDown()) { 
       downY = -1; 
      } 
      break; 
     } 
     return super.onTouchEvent(event); 
    } 

    /** 
    * 下移所有视图 
    */ 
    private boolean goDown() { 
     final View topView = getChildAt(getChildCount() - 1); 
     if(!topView.isEnabled()){ 
      return false; 
     } 
     // topView.getHitRect(topRect); 在4.3以前有bug,用以下方法代替 
     topRect = getHitRect(topRect, topView); 
     // 如果按下的位置不在顶部视图上,则不移动 
     if (!topRect.contains((int) downX, (int) downY)) { 
      return false; 
     } 
     topView.setEnabled(false); 
     ViewPropertyAnimator anim = ViewPropertyAnimator 
       .animate(topView) 
       .translationY(
         ViewHelper.getTranslationY(topView) 
           + topView.getHeight()).alpha(0).scaleX(1) 
       .setListener(null).setDuration(200); 
     anim.setListener(new AnimatorListenerAdapter() { 
      @Override 
      public void onAnimationEnd(Animator animation) { 
       topView.setEnabled(true); 
       removeView(topView); 
       ensureFull(); 
       final int count = getChildCount(); 
       for (int i = 0; i < count; i++) { 
        final View view = getChildAt(i); 
        float scaleX = ViewHelper.getScaleX(view) 
          + ((float) 1/mMaxVisible) * 0.2f; 
        float tranlateY = ViewHelper.getTranslationY(view) 
          + itemSpace; 
        if (i == count - 1) { 
         bringToTop(view); 
        } else { 
         if ((count == mMaxVisible && i != 0) 
           || count < mMaxVisible) { 
          ViewPropertyAnimator 
            .animate(view) 
            .translationY(tranlateY) 
            .setInterpolator(
              new AccelerateInterpolator()) 
            .setListener(null).scaleX(scaleX) 
            .setDuration(200); 
         } 
        } 
       } 
      } 
     }); 
     return true; 
    } 

    private void bringToTop(final View view) { 
     topPosition++; 
     float scaleX = ViewHelper.getScaleX(view) + ((float) 1/mMaxVisible) 
       * 0.2f; 
     float tranlateY = ViewHelper.getTranslationY(view) + itemSpace; 
     ViewPropertyAnimator.animate(view).translationY(tranlateY) 
       .scaleX(scaleX).setDuration(200).alpha(1) 
       .setInterpolator(new AccelerateInterpolator()); 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
     float currentY = ev.getY(); 
     switch (ev.getAction()) { 
     case MotionEvent.ACTION_DOWN: 
      downX = ev.getX(); 
      downY = ev.getY(); 
      break; 
     case MotionEvent.ACTION_MOVE: 
      float distance = currentY - downY; 
      if (distance > mTouchSlop) { 
       return true; 
      } 
      break; 
     } 
     return false; 
    } 

    public static Rect getHitRect(Rect rect, View child) { 
     rect.left = child.getLeft(); 
     rect.right = child.getRight(); 
     rect.top = (int) (child.getTop() + ViewHelper.getTranslationY(child)); 
     rect.bottom = (int) (child.getBottom() + ViewHelper 
       .getTranslationY(child)); 
     return rect; 
    } 

    private final DataSetObserver mDataSetObserver = new DataSetObserver() { 
     @Override 
     public void onChanged() { 
      super.onChanged(); 
     } 

     @Override 
     public void onInvalidated() { 
      super.onInvalidated(); 
     } 
    }; 

    private OnClickListener listener = new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      if (mListener != null) { 
       mListener.onCardClick(v, topPosition); 
      } 
     } 
    }; 
} 

Hier ist meine CardView Adapterklasse:

package com.chiemy.cardview.view; 

import java.util.ArrayList; 
import java.util.Collection; 
import java.util.List; 

import android.content.Context; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.FrameLayout; 

import com.chiemy.cardview.R; 

public abstract class CardAdapter<T> extends BaseCardAdapter { 
    private final Context mContext; 

    private ArrayList<T> mData; 

    public CardAdapter(Context context) { 
     mContext = context; 
     mData = new ArrayList<T>(); 
    } 

    public CardAdapter(Context context, Collection<? extends T> items) { 
     mContext = context; 
     mData = new ArrayList<T>(items); 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     FrameLayout wrapper = (FrameLayout) convertView; 
     View cardView; 
     View convertedCardView; 
     if (wrapper == null) { 
      wrapper = new FrameLayout(mContext); 
      wrapper.setBackgroundResource(R.drawable.card_background_shadow); 
      cardView = getCardView(position, null, wrapper); 
      wrapper.addView(cardView); 
     } else { 
      cardView = wrapper.getChildAt(0); 
      convertedCardView = getCardView(position, cardView, wrapper); 

      wrapper.removeView(cardView); 
      wrapper.addView(convertedCardView); 
      if (convertedCardView != cardView) { 
      } 
     } 
     return wrapper; 
    } 

    protected abstract View getCardView(int position, View convertView, ViewGroup parent); 

    public void addAll(List<T> items){ 
     mData.addAll(items); 
    } 

    @Override 
    public T getItem(int position) { 
     return mData.get(position); 
    } 

    @Override 
    public int getCount() { 
     return mData.size(); 
    } 

    @Override 
    public long getItemId(int position) { 
     return getItem(position).hashCode(); 
    } 

    public Context getContext() { 
     return mContext; 
    } 

    public void clear(){ 
     if(mData != null){ 
      mData.clear(); 
     } 
    } 
} 

Vorschläge, wie dies zu erreichen?

+0

Bitte, alle relevanten Informationen in dieser Frage zu stellen und aviod Links zu anderen externen Ressourcen hinzufügen – HCarrasko

+0

Können Sie bitte Ihre Fragen klären, wie es ein wenig unklar – Razor

+0

Auch ist, bieten einige Code – Razor

Antwort

1

Um ein ArrayList<>, in Ihrem Fall randomise, ist dies die schlurfenden Lösung sein würde, können Sie diesen Code verwenden:

long seed = System.nanoTime(); 
Collections.shuffle(list_of_items, new Random(seed)); 

Sie das ArrayList<> zurück zum CardView und Ihre Artikel werden zufällig einstellen müssen gemischt. Um ein zufälliges Objekt abzurufen, besuchen Sie die Seite this, um mehr über das Abrufen eines zufälligen Elements aus einer ArrayList<> zu erfahren. Sehen Sie, wie Sie gehen und fragen Sie nach mehr Hilfe, wenn nötig.

+0

Sorry, wenn die Antwort ein wenig eilig ist. Ich tippe von einem Tablet und das Hinzufügen von Code ist ein bisschen schwierig. – Razor

+0

Vielen Dank für Ihre Hilfe. Aber das erste Problem, das ich habe, ist, dass ich automatisch Scroll-Elemente sein möchte. Wie http://i.stack.imgur.com/WXyzC.gif @Razor – hosein

+0

Sie müssen Animationen implementieren, die sehr schwierig sein können, wenn Sie das wollen Art von Scrollen. In Bezug auf Ihre Shuffling-Fähigkeiten schlage ich vor, dass Sie die 'ArrayList <>' Ihrer Artikel zufällig auswählen und dann eine zufällig auswählen, wie ich oben gezeigt habe. – Razor