可翻转移到的自定义卡片

Posted yzh315

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可翻转移到的自定义卡片相关的知识,希望对你有一定的参考价值。

技术图片技术图片技术图片

 

先建立卡片 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);

    }

 

以上是关于可翻转移到的自定义卡片的主要内容,如果未能解决你的问题,请参考以下文章

使用Essential Grid的自定义模板

找到我的自定义代码片段 Xcode 6?

SwiftUI 中的自定义模态转换

选项卡片段内的卡片视图

片段内的自定义列表不起作用

带有圆角而不是 100% 屏幕宽度的自定义片段对话框