可翻转移到的自定义卡片

可翻转移到的自定义卡片可翻转移到的自定义卡片可翻转移到的自定义卡片

先建立卡片 xml 。view_card_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >
    <FrameLayout
        android:id="@+id/frame_layout_zm"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        >
        <LinearLayout
            android:orientation="vertical"
            android:layout_gravity="top"
            android:paddingTop="5dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="left"
                android:textColor="@color/default_black"
                android:textSize="20dp"
                android:text="正面小标题"/>
            <TextView
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@color/blue"
                />
        </LinearLayout>
        <TextView
            android:gravity="center"
            android:id="@+id/data_zm_msg"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="left"
            android:textColor="@color/default_black"
            android:textSize="25dp"
            android:text="事件内容正面"/>
    </FrameLayout>
    <FrameLayout
        android:visibility="gone"
        android:id="@+id/frame_layout_bm"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        >
        <LinearLayout
            android:orientation="vertical"
            android:layout_gravity="top"
            android:paddingTop="5dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="left"
                android:textColor="@color/default_black"
                android:textSize="20dp"
                android:text="背面小标题"/>
            <TextView
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@color/blue"
                />
        </LinearLayout>
        <TextView
            android:gravity="center"
            android:id="@+id/data_bm_msg"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="left"
            android:textColor="@color/default_black"
            android:textSize="25dp"
            android:text="背面内容"/>
    </FrameLayout>
</LinearLayout>

创建 CardItem.java

import android.view.View;

/**
 * @author Yzh315
 */
public class CardItem {
    public View getView() {
        return view;
    }

    public View getZmView() {
        return zmView;
    }

    public View getBmView() {
        return bmView;
    }

    public boolean isZm() {
        return isZm;
    }

    public void setZm(boolean zm) {
        isZm = zm;
    }

    private boolean isZm = true;//目前为正面
    private View zmView,bmView;
    public CardItem setView(View zv1,View zv2){
        this.zmView = zv1;
        this.bmView = zv2;
        return this;
    }
    private View view ;
    public CardItem setView(View view){
        this.view = view;
        return this;
    }
    private float lastX;

    public float getLastX() {
        return lastX;
    }

    public void setLastX(float lastX) {
        this.lastX = lastX;
    }

    public float getLastY() {
        return lastY;
    }

    public void setLastY(float lastY) {
        this.lastY = lastY;
    }

    private float lastY;
}

最后创建主要的自定义 ViewGroup ,MyCardsView.java

import android.animation.Animator;import android.animation.AnimatorSet;import android.animation.ObjectAnimator;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.drawable.BitmapDrawable;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.widget.FrameLayout;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;import org.json.JSONArray;import org.json.JSONObject;import java.util.HashMap;import java.util.List;import java.util.Map;public class MyCardsView extends ViewGroup {    public MyCardsView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public MyCardsView(Context context) {        super(context);    }    public void setArrayJson(JSONArray arrayJson) {        this.arrayJson = arrayJson;    }    public JSONObject getJSON(int index){        try {            return arrayJson.getJSONObject(index);        }catch (Exception e){}        return null;    }    private JSONArray arrayJson = null ;    private ItemView itemView = null;    public void setItemView(ItemView itemView) {        this.itemView = itemView;    }    private int paddingLeft = 100 ,paddingTop = 5;//间隔    public void setPadding(int left,int top){        paddingLeft = left;        paddingTop = top;    }    @Override    protected void onLayout( boolean changed, int left, int top, int right, int bottom) {        final int count = getChildCount();        int childMeasureHeight = 0;        for(int i = 0; i<count; i++){            View child = getChildAt(i);            right = this.getWidth() - paddingLeft;            bottom = top + child.getMeasuredHeight();            //确定子控件的位置,四个参数分别代表(左上右下)点的坐标值            child.layout(paddingLeft , paddingTop , right, bottom);        }    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        // 计算出所有的childView的宽和高        measureChildren(widthMeasureSpec, heightMeasureSpec);        setMeasuredDimension( getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));    }    private Map<Integer, CardItem> viewMap = new HashMap<>();    float lastX, lastY;    private int nowIndex = 0 ;//初始化值    private void initLayout(){        for(int i=arrayJson.length()-1;i>=0;i--){            CardItem cardItem = new CardItem();            LinearLayout linearLayout = new LinearLayout(getContext());            View rootView = itemView.getItemView(linearLayout,cardItem,getJSON(i),i);//目前位置            if(rootView!=null){                LayoutParams layoutParams = new LayoutParams(this.getWidth() - 200,this.getHeight()-10);                linearLayout.addView(rootView,layoutParams);            }            viewMap.put(i,cardItem.setView(linearLayout));//添加            addView(linearLayout);        }    }    public void initialize() {        this.post(new Runnable() {            @Override            public void run() {                initLayout();            }        });    }    /////////////////////////////    private void initShow(int x,int y){        for(int i = nowIndex - 1 ; i >= 0 ; i--){            View view = viewMap.get(i).getView();            view.setX(x);            view.setY(y);            view.bringToFront();        }        for(int i=viewMap.size()-1;i>=nowIndex;i--){            View view = viewMap.get(i).getView();            view.setX(x);            view.setY(y);            view.bringToFront();        }    }    private float downX ,downY;//    private long lastUpTime = 0;    @Override    public boolean dispatchTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                downX = event.getX();                downY = event.getY();                lastX = event.getRawX();                lastY = event.getRawY();                return true;            case MotionEvent.ACTION_UP:                try{                    CardItem cardItem = viewMap.get(nowIndex);                    View myView = cardItem.getView();                    float jlX = event.getX()-downX;//设置目前值                    float jlY = event.getY()-downY;//设置目前值                    if(jlY<=1&&jlX<=1){                        //点击//                        if(System.currentTimeMillis()-lastUpTime>500){//                            lastUpTime = System.currentTimeMillis();                            if(cardItem.isZm()){                                AnimUtil.FlipAnimatorXViewShow(cardItem.getZmView(),cardItem.getBmView(),500);                            }else {                                AnimUtil.FlipAnimatorXViewShow(cardItem.getBmView(),cardItem.getZmView(),500);                            }                            cardItem.setZm(!cardItem.isZm());//                        }                    }else if(Math.abs(jlX)>200||Math.abs(jlY)>100){//                        lastUpTime = System.currentTimeMillis();                        AnimUtil.EndBackCallListener endBackCallListener = new AnimUtil.EndBackCallListener() {                            @Override                            public void callBack() {                                //翻转                                if(!cardItem.isZm()){                                    //反正                                    AnimUtil.FlipAnimatorXViewShow(cardItem.getBmView(),cardItem.getZmView(),500);                                    cardItem.setZm(!cardItem.isZm());                                }                                nowIndex ++;                                if(nowIndex<0) nowIndex = 0 ;                                if(nowIndex>=viewMap.size()) nowIndex = 0;//从0开始                                initShow(paddingLeft,paddingTop);                            }                        };                        if(jlX>0){                            AnimUtil.SetViewXyToXy(myView, this.getWidth(), myView.getY(), 500, endBackCallListener);                        }else{                            //右到左                            float toX =  - this.getWidth();                            AnimUtil.SetViewXyToXy(myView, toX, myView.getY(), 500, endBackCallListener);                        }                    }else{//                        lastUpTime = System.currentTimeMillis();                        AnimUtil.SetViewXyToXy(myView,paddingLeft,paddingTop,500,null);                    }                }catch (Exception e){}                break;            case MotionEvent.ACTION_MOVE:                //  不要直接用getX和getY,这两个获取的数据已经是经过处理的,容易出现图片抖动的情况                try{//                    lastUpTime = System.currentTimeMillis();                    float distanceX = lastX - event.getRawX();                    float distanceY = lastY - event.getRawY();                    //////////////////////////////////////////////////////                    View myView = viewMap.get(nowIndex).getView();                    float nextY = myView.getY() - distanceY;                    float nextX = myView.getX() - distanceX;                    AnimUtil.SetViewXyToXy(myView,nextX,nextY,0,null);                    lastX = event.getRawX();                    lastY = event.getRawY();//                    myView.bringToFront();                }catch (Exception e){}        }        return false;    }    public interface ItemView{        public View getItemView(View parentView,CardItem cardItem,JSONObject dataJson,int index);    }}
 

工具类

AnimUtil.java
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.view.View;
import android.view.animation.OvershootInterpolator;

public class AnimUtil {

    public interface EndBackCallListener{
        void callBack();
    };

    public static void SetViewXyToXy(final View view,float toX,float toY,long durationTime,EndBackCallListener endBackCallListener){
        try{
            // 属性动画移动
            ObjectAnimator y = ObjectAnimator.ofFloat(view, "y", view.getY(), toY);
            ObjectAnimator x = ObjectAnimator.ofFloat(view, "x", view.getX(), toX);

            AnimatorSet animatorSet = new AnimatorSet();

            if(endBackCallListener!=null){
                animatorSet.addListener(new Animator.AnimatorListener() {
                    @Override
                    public void onAnimationStart(Animator animation) {}
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        endBackCallListener.callBack();
                    }
                    @Override
                    public void onAnimationCancel(Animator animation) {}
                    @Override
                    public void onAnimationRepeat(Animator animation) {}
                });
            }
            animatorSet.playTogether(x, y);
            animatorSet.setDuration(durationTime);
            animatorSet.start();
        }catch (Exception e){}
    }

    public static void FlipAnimatorXViewShow(final View oldView, final View newView, final long time) {

        try{
            if(oldView==null) return;
            if(newView==null) return;
            ObjectAnimator animator1 = ObjectAnimator.ofFloat(oldView, "rotationY", 0, 90);
            final ObjectAnimator animator2 = ObjectAnimator.ofFloat(newView, "rotationY", -90, 0);
            animator2.setInterpolator(new OvershootInterpolator(2.0f));

            animator1.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    oldView.setVisibility(View.GONE);
                    animator2.setDuration(time).start();
                    newView.setVisibility(View.VISIBLE);
                }
                @Override
                public void onAnimationCancel(Animator animation) {
                }

                @Override
                public void onAnimationRepeat(Animator animation) {
                }
            });
            animator1.setDuration(time).start();
        }catch (Exception e){}

    }
}

调用

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        MyCardsView myCardsView = new MyCardsView(this);

        JSONArray array = new JSONArray();
        for(int i=0;i<20;i++){
            try{
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("msg","正面信息 ............."+i);
                array.put(jsonObject);
            }catch (Exception e){}
        }
        myCardsView.setArrayJson(array);
        myCardsView.setItemView(new MyCardsView.ItemView() {
            @Override
            public View getItemView(View parentView, CardItem cardItem, JSONObject dataJson, int index) {
                try{
                    View rootView = LayoutInflater.from(parentView.getContext()).inflate(R.layout.view_learn_card_item,null);//获取数据
                    TextView textView = rootView.findViewById(R.id.data_zm_msg);
                    if(textView!=null){
                        textView.setText(dataJson.getString("msg") );
                        textView.setTextSize(25);
                    }
                    FrameLayout frame_layout_zm = rootView.findViewById(R.id.frame_layout_zm);
                    FrameLayout frame_layout_bm = rootView.findViewById(R.id.frame_layout_bm);
                    cardItem.setView(frame_layout_zm,frame_layout_bm);
                    return rootView;
                }catch (Exception e){
                }
                return null;
            }
        });
        myCardsView.initialize();

        LinearLayout linearLayout = new LinearLayout(this);
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,600);
        lp.gravity = Gravity.CENTER;
        linearLayout.addView(myCardsView,lp);
        setContentView(linearLayout);

    }

相关推荐