水波紋+仿探探卡片滑動+飄贊動畫

本篇文章主要記錄一下開發過程通過網上搜索和本項目需求結合最終實現效果做個記錄,
本人比較賴,就不抽demo了,關鍵代碼已貼,仿探探卡片相關文件附git 下載鏈接,避免以後再各種搜索
附上最終效果圖

項目效果圖

一、水波紋

  //水波紋
  implementation 'com.github.onlynight:WaveView:1.0.0'

    <com.github.onlynight.waveview.WaveView
        android:id="@+id/waveView"
        android:layout_width="match_parent"
        android:layout_height="@dimen/base440dp"
        app:isCircle="false"
        app:layout_constraintBottom_toBottomOf="parent"
        app:period="2"
        app:wave1Color="#80C3EEE1"
        app:wave2Color="#80C3EEE1"
        app:waveHeightPercent="0.5"
        app:waveRange="10dp"
        app:waveSpeed="7"
        app:waveStrokeWidth="3dp" />

	//初始化開啓
     waveView.start();//開啓水波紋
   @Override
    public void onDestroy() {
        super.onDestroy();
        waveView.stop();
    }

二、仿探探滑動卡片

點擊跳轉相關自定義類(swip_card)

可自選變量(已上傳)

public final class CardConfig {
    /**
     * 顯示可見的卡片數量
     */
    public static final int DEFAULT_SHOW_ITEM = 3;
    /**
     * 默認縮放的比例
     */
    public static final float DEFAULT_SCALE = 0.1f;
    /**
     * 卡片Y軸偏移量時按照14等分計算
     */
//    public static final int DEFAULT_TRANSLATE_Y = 14;
    public static final int DEFAULT_TRANSLATE_Y = -10; //重疊方向 正數向下
    /**
     * 卡片滑動時默認傾斜的角度
     */
    public static final float DEFAULT_ROTATE_DEGREE = 15f;
    /**
     * 卡片滑動時不偏左也不偏右
     */
    public static final int SWIPING_NONE = 1;
    /**
     * 卡片向左滑動時
     */
    public static final int SWIPING_LEFT = 1 << 2;
    /**
     * 卡片向右滑動時
     */
    public static final int SWIPING_RIGHT = 1 << 3;
    /**
     * 卡片從左邊滑出
     */
    public static final int SWIPED_LEFT = 1;
    /**
     * 卡片從右邊滑出
     */
    public static final int SWIPED_RIGHT = 1 << 2;
}

  <android.support.v7.widget.RecyclerView
        android:id="@+id/recy_sound_card"
        android:layout_width="match_parent"
        android:layout_height="@dimen/base300dp"
        app:layout_constraintTop_toBottomOf="@+id/tv_sound_card" />
	//滑動卡片初始化
    private void initCardView() {
        soundPublishCardAdapter = new SoundPublishCardAdapter(mActivity);
        recySoundCard.setItemAnimator(new DefaultItemAnimator());
        recySoundCard.setAdapter(soundPublishCardAdapter);
        soundPublishCardAdapter.setNewData(cardList);
        CardItemTouchHelperCallback cardCallback = new CardItemTouchHelperCallback(recySoundCard.getAdapter(), cardList);
        final ItemTouchHelper touchHelper = new ItemTouchHelper(cardCallback);
        final CardLayoutManager cardLayoutManager = new CardLayoutManager(recySoundCard, touchHelper);
        recySoundCard.setLayoutManager(cardLayoutManager);
        touchHelper.attachToRecyclerView(recySoundCard);
        cardCallback.setOnSwipedListener(new OnSwipeListener() {
            @Override
            public void onSwiping(RecyclerView.ViewHolder viewHolder, float ratio, int direction) {
                BaseViewHolder myHolder = (BaseViewHolder) viewHolder;
                myHolder.itemView.setAlpha(1 - Math.abs(ratio) * 0.2f);
            }

            @Override
            public void onSwiped(RecyclerView.ViewHolder viewHolder, Object o, int direction) {
                viewHolder.itemView.setAlpha(1f);
                int position = viewHolder.getAdapterPosition()+1;
                if (soundPublishCardAdapter.getData().size()>0){
                    currentCardBean = soundPublishCardAdapter.getData().get(position);
                    tvCardContent.setText(currentCardBean.getContent());
                    tvCardBelong.setText(StringUtil.getHTMLStr(currentCardBean.getWriter(),"\u2014\u2014"));
                    view_card_belong.setVisibility(TextUtils.isEmpty(currentCardBean.getWriter()) ? View.GONE : View.VISIBLE);
                }
            }

            @Override
            public void onSwipedClear() {
                LogUtils.e("debug+onSwipedClear");
                recySoundCard.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        presenter.getSoundCards(page,type_id);//循環
                        recySoundCard.getAdapter().notifyDataSetChanged();
                    }
                }, 1000L);
            }
        });
    }


//卡片Adapter展示
public class SoundPublishCardAdapter extends BaseQuickAdapter<SoundCardListBean, BaseViewHolder> {

    private BaseActivity context;

    public SoundPublishCardAdapter(BaseActivity activity) {
        super(R.layout.item_sound_publish_card, new ArrayList<>());
        this.context = activity;
    }

    @Override
    protected void convert(final BaseViewHolder holder, final SoundCardListBean data) {
        holder.setText(R.id.tv_card_content, data.getContent());
		//getHTMLStr 遇到安卓手機修改系統字體後————顯示斷— — ,所以過濾本地處理替換View
        holder.setText(R.id.tv_card_belong, StringUtil.getHTMLStr(data.getWriter(),"\u2014\u2014"));
        View view_card_belong = holder.getView(R.id.view_card_belong);
        view_card_belong.setVisibility(TextUtils.isEmpty(data.getWriter()) ? View.GONE : View.VISIBLE);
        ConstraintLayout cl_layout = holder.getView(R.id.cl_layout);
        if (holder.getAdapterPosition() == 0) {
            cl_layout.setBackgroundResource(R.mipmap.icon_card_bg);
        } else if (holder.getAdapterPosition() == 1) {
            cl_layout.setBackgroundResource(R.drawable.shape_gradient_sound_card2);
        } else {
        	//有透明度,所以二三層得文字不顯示,
            holder.setGone(R.id.tv_card_content,false);
            holder.setGone(R.id.tv_card_belong,false);
            holder.setGone(R.id.view_card_belong,false);
            holder.setGone(R.id.tv_card_swip,false);
            cl_layout.setBackgroundResource(R.drawable.shape_gradient_sound_card3);
        }
    }
}

    /**
     * 過濾html標籤(——)
     * @param htmlStr
     * @return
     */
    public static String getHTMLStr(String htmlStr,String regix){
        Pattern p_html = Pattern.compile(regix, Pattern.CASE_INSENSITIVE);
        Matcher m_html = p_html.matcher(htmlStr);
        return  m_html.replaceAll("");
    }

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tool="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="@dimen/base250dp"
    android:padding="@dimen/base15dp">


    <android.support.constraint.ConstraintLayout
        android:id="@+id/cl_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@mipmap/icon_card_bg"
        android:padding="@dimen/base15dp">

        <TextView
            android:id="@+id/tv_card_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:lineSpacingMultiplier="1.5"
            android:padding="@dimen/base5dp"
            android:textColor="@color/color_33615D"
            android:textSize="@dimen/text16sp"
            android:textStyle="bold"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tool:text="別怪我心狠,爲了聖教主的垂憐,我什麼都可爲了聖教主的垂憐" />

        <TextView
            android:id="@+id/tv_card_belong"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/base45dp"
            tool:text="劍網3·牡丹"
            android:textStyle="bold"
            android:layout_marginEnd="@dimen/base8dp"
            android:textColor="@color/color_33615D"
            android:textSize="@dimen/text16sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent" />


        <View
            android:id="@+id/view_card_belong"
            android:layout_width="@dimen/base25dp"
            android:layout_height="1dp"
            app:layout_constraintEnd_toStartOf="@+id/tv_card_belong"
            app:layout_constraintTop_toTopOf="@+id/tv_card_belong"
            app:layout_constraintBottom_toBottomOf="@+id/tv_card_belong"
            android:background="@color/color_33615D"/>


        <TextView
            android:id="@+id/tv_card_swip"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="左右滑動可以更換卡片哦~"
            android:textColor="@color/color_33615D"
            android:textSize="@dimen/text12sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
    </android.support.constraint.ConstraintLayout>

</android.support.constraint.ConstraintLayout>

三、飄贊動畫

點擊跳轉相關圖片(photo)

在這裏插入圖片描述

package com.huanqiu.miudeal.mvp.ui.view.card;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.huanqiu.miudeal.R;

import java.util.Random;

/**
 * 定義我們自己的佈局
 * */
public class LoveLayout extends RelativeLayout {

    private Context context;
    private LayoutParams params;
    private Drawable[] icons = new Drawable[6];  //圖片數量對應
    private Interpolator[] interpolators = new Interpolator[4];
    private int mWidth;
    private int mHeight;

    public LoveLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

        this.context = context;
        initView();
    }

    private void initView() {
        // 圖片資源
        icons[0] = getResources().getDrawable(R.mipmap.icon_sound_anim1);
        icons[1] = getResources().getDrawable(R.mipmap.icon_sound_anim2);
        icons[2] = getResources().getDrawable(R.mipmap.icon_sound_anim3);
        icons[3] = getResources().getDrawable(R.mipmap.icon_sound_anim4);
        icons[4] = getResources().getDrawable(R.mipmap.icon_sound_anim5);

        // 插值器
        interpolators[0] = new AccelerateDecelerateInterpolator(); // 在動畫開始與結束的地方速率改變比較慢,在中間的時候加速
        interpolators[1] = new AccelerateInterpolator();  // 在動畫開始的地方速率改變比較慢,然後開始加速
        interpolators[2] = new DecelerateInterpolator(); // 在動畫開始的地方快然後慢
        interpolators[3] = new LinearInterpolator();  // 以常量速率改變

        int width = icons[0].getIntrinsicWidth();
        int height = icons[0].getIntrinsicWidth();
        params = new LayoutParams(width, height);
        params.addRule(CENTER_HORIZONTAL, TRUE);
        params.addRule(ALIGN_PARENT_BOTTOM, TRUE);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // TODO Auto-generated method stub
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();
    }

    public void addLoveView() {
        // TODO Auto-generated method stub
        final ImageView iv = new ImageView(context);
        iv.setLayoutParams(params);
        iv.setImageDrawable(icons[new Random().nextInt(4)]);
        addView(iv);
        // 開啓動畫,並且用完銷燬
        AnimatorSet set = getAnimatorSet(iv);
        set.start();
        set.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                // TODO Auto-generated method stub
                super.onAnimationEnd(animation);
                removeView(iv);
            }
        });
    }


    /**
     * 獲取動畫集合
     * @param iv
     * */
    private AnimatorSet getAnimatorSet(ImageView iv) {

        // 1.alpha動畫
        ObjectAnimator alpha = ObjectAnimator.ofFloat(iv, "alpha", 0.3f, 1f);

        // 2.縮放動畫
        ObjectAnimator scaleX = ObjectAnimator.ofFloat(iv, "scaleX", 0.2f, 1f);
        ObjectAnimator scaleY = ObjectAnimator.ofFloat(iv, "scaleY", 0.2f, 1f);

        // 動畫集合
        AnimatorSet set = new AnimatorSet();
        set.playTogether(alpha, scaleX, scaleY);
        set.setDuration(500);

        // 貝塞爾曲線動畫
        ValueAnimator bzier = getBzierAnimator(iv);

        AnimatorSet set2 = new AnimatorSet();
        set2.playSequentially(set, bzier);
        set2.setTarget(iv);
        return set2;
    }

    /**
     * 貝塞爾動畫
     * */
    private ValueAnimator getBzierAnimator(final ImageView iv) {
        // TODO Auto-generated method stub
        PointF[] PointFs = getPointFs(iv); // 4個點的座標
        BasEvaluator evaluator = new BasEvaluator(PointFs[1], PointFs[2]);
        ValueAnimator valueAnim = ValueAnimator.ofObject(evaluator, PointFs[0], PointFs[3]);
        valueAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // TODO Auto-generated method stub
                PointF p = (PointF) animation.getAnimatedValue();
                iv.setX(p.x);
                iv.setY(p.y);
                iv.setAlpha(1- animation.getAnimatedFraction()); // 透明度
            }
        });
        valueAnim.setTarget(iv);
        valueAnim.setDuration(3000);
        valueAnim.setInterpolator(interpolators[new Random().nextInt(4)]);
        return valueAnim;
    }

    private PointF[] getPointFs(ImageView iv) {
        // TODO Auto-generated method stub
        PointF[] PointFs = new PointF[4];
        PointFs[0] = new PointF(); // p0
        PointFs[0].x = (mWidth- params.width)/ 2;
        PointFs[0].y = mHeight - params.height;

        PointFs[1] = new PointF(); // p1
        PointFs[1].x = new Random().nextInt(mWidth);
        PointFs[1].y = new Random().nextInt(mHeight /2) + mHeight / 2 + params.height;

        PointFs[2] = new PointF(); // p2
        PointFs[2].x = new Random().nextInt(mWidth);
        PointFs[2].y = new Random().nextInt(mHeight /2);

        PointFs[3] = new PointF(); // p3
        PointFs[3].x = new Random().nextInt(mWidth);
        PointFs[3].y = 0;
        return PointFs;
    }
}

                 *   注:  自定義部分代碼來源於網絡*
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章