自定义AutoTextView实现公告栏 文字3D 翻转动画

对于抽奖页 我们都用到了公告栏循环播放中奖名单的动画效果;一下介绍下自定义AutoTextView 实现了公告栏 文字 3D 翻转动画效果,无限循环播放,具有向上或者向下翻转特效。

现在先上效果图:

自定义AutoTextView实现公告栏 文字3D 翻转动画_第1张图片

下面附上代码介绍:

自定义AutoTextView继承自TextSwitcher,实现文字切换,自定义动画,实现3d动画效果;

  class Rotate3dAnimation extends Animation {
        private final float mFromDegrees; //初始值
        private final float mToDegrees; //最终值
        private final boolean mTurnIn; //进
        private final boolean mTurnUp; //出
        private float mCenterX;
        private float mCenterY;
        private Camera mCamera;

        public Rotate3dAnimation(float fromDegrees, float toDegrees, boolean turnIn, boolean turnUp) {

            mFromDegrees = fromDegrees;
            mToDegrees = toDegrees;
            mTurnIn = turnIn;
            mTurnUp = turnUp;
        }
        //初始化动作
        @Override
        public void initialize(int width, int height, int parentWidth, int parentHeight) {
            super.initialize(width, height, parentWidth, parentHeight);
            mCamera = new Camera();
            mCenterY = getHeight() / 2;
            mCenterX = getWidth() / 2;
        }
        //定义动画效果
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {

            final float fromDegrees = mFromDegrees;
            //当前值 = 初始值 + (最终值 - 初始值) * interpolatedTime;
            float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);

            final float centerX = mCenterX;
            final float centerY = mCenterY;
            final Camera camera = mCamera;
            final int derection = mTurnUp ? 1 : -1;

            //通过camera进行一些矩阵操作,最后对matrix进行变化
            final Matrix matrix = t.getMatrix();

            camera.save();
            if (mTurnIn) {
                camera.translate(0.0f, derection * mCenterY * (interpolatedTime - 1.0f), 0.0f);
            } else {
                camera.translate(0.0f, derection * mCenterY * (interpolatedTime), 0.0f);
            }
            camera.rotateX(degrees);
            camera.getMatrix(matrix);
            camera.restore();

            matrix.preTranslate(-centerX, -centerY);
            matrix.postTranslate(centerX, centerY);
        }
    }

重新定义了一个Animation,覆写了initialize和applyTransformation方法,利用矩阵实现3D翻页特效

下面附上整体代码:

public class AutoTextView extends TextSwitcher implements ViewFactory {

    private float mHeight;
    private Context mContext;
    //mInUp,mOutUp分别构成向上翻页的进出动画
    private Rotate3dAnimation mInUp;
    private Rotate3dAnimation mOutUp;

    //mInDown,mOutDown分别构成向下翻页的进出动画
    private Rotate3dAnimation mInDown;
    private Rotate3dAnimation mOutDown;

    public AutoTextView(Context context) {
        this(context, null);
    }

    public AutoTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.auto3d);
        mHeight = a.getDimension(R.styleable.auto3d_textSize, 36);
        a.recycle();
        mContext = context;
        init();
    }

    private void init() {
        setFactory(this);
        //向上翻页的进出动画
        mInUp = createAnim(-90, 0, true, true);//进动画
        mOutUp = createAnim(0, 90, false, true);//出动画
        //向下翻页的进出动画
        mInDown = createAnim(90, 0, true, false);
        mOutDown = createAnim(0, -90, false, false);
        //继承TextSwitcher主要用于文件切换,比如 从文字A 切换到 文字 B,
        //setInAnimation()后,A将执行inAnimation,
        //setOutAnimation()后,B将执行OutAnimation
        setInAnimation(mInUp);
        setOutAnimation(mOutUp);
    }

    //动画
    private Rotate3dAnimation createAnim(float start, float end, boolean turnIn, boolean turnUp) {
        final Rotate3dAnimation rotation = new Rotate3dAnimation(start, end, turnIn, turnUp);
        //设置动画持续时间
        rotation.setDuration(300);
        //fillAfter设为true,则动画执行后,控件将停留在动画结束的状态,false 则不停留
        rotation.setFillAfter(false);
        //设置动画的变化速度  加速
        rotation.setInterpolator(new AccelerateInterpolator());
        return rotation;
    }

    //这里返回的TextView,就是我们看到的View
    @Override
    public View makeView() {
        TextView t = new TextView(mContext);
        t.setGravity(Gravity.CENTER);
        t.setTextSize(mHeight);
        t.setSingleLine(true);
        return t;
    }

    //定义动作,向下滚动翻页
    public void previous() {
        if (getInAnimation() != mInDown) {
            setInAnimation(mInDown);
        }
        if (getOutAnimation() != mOutDown) {
            setOutAnimation(mOutDown);
        }
    }

    //定义动作,向上滚动翻页
    public void next() {
        if (getInAnimation() != mInUp) {
            setInAnimation(mInUp);
        }
        if (getOutAnimation() != mOutUp) {
            setOutAnimation(mOutUp);
        }
    }
    /**
     *  3d动画
     *  重新定义了一个Animation,覆写了initialize和applyTransformation方法
     */

    class Rotate3dAnimation extends Animation {
        private final float mFromDegrees; //初始值
        private final float mToDegrees; //最终值
        private final boolean mTurnIn; //进
        private final boolean mTurnUp; //出
        private float mCenterX;
        private float mCenterY;
        private Camera mCamera;

        public Rotate3dAnimation(float fromDegrees, float toDegrees, boolean turnIn, boolean turnUp) {

            mFromDegrees = fromDegrees;
            mToDegrees = toDegrees;
            mTurnIn = turnIn;
            mTurnUp = turnUp;
        }
        //初始化动作
        @Override
        public void initialize(int width, int height, int parentWidth, int parentHeight) {
            super.initialize(width, height, parentWidth, parentHeight);
            mCamera = new Camera();
            mCenterY = getHeight() / 2;
            mCenterX = getWidth() / 2;
        }
        //定义动画效果
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {

            final float fromDegrees = mFromDegrees;
            //当前值 = 初始值 + (最终值 - 初始值) * interpolatedTime;
            float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);

            final float centerX = mCenterX;
            final float centerY = mCenterY;
            final Camera camera = mCamera;
            final int derection = mTurnUp ? 1 : -1;

            //通过camera进行一些矩阵操作,最后对matrix进行变化
            final Matrix matrix = t.getMatrix();

            camera.save();
            if (mTurnIn) {
                camera.translate(0.0f, derection * mCenterY * (interpolatedTime - 1.0f), 0.0f);
            } else {
                camera.translate(0.0f, derection * mCenterY * (interpolatedTime), 0.0f);
            }
            camera.rotateX(degrees);
            camera.getMatrix(matrix);
            camera.restore();

            matrix.preTranslate(-centerX, -centerY);
            matrix.postTranslate(centerX, centerY);
        }
    }
}

在activity中:

添加公告栏数据:

 // 数据
        mStringArray = new ArrayList();
        mStringArray.add("137****1111 获得一等奖");
        mStringArray.add("137****2222 获得二等奖");
        mStringArray.add("137****3333 获得三等奖");
        mStringArray.add("137****4444 获得四等奖");

通过headler发送消息开始自动翻转:

 //开始动画
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mEventHandler == null){
                    mEventHandler = new EventHandler(MainActivity.this);
                    //Value为FLAG的消息延迟0.5秒
                    mEventHandler.sendEmptyMessageDelayed(FLAG, 500);
                }

            }
        });
  public static class EventHandler extends Handler {

        private WeakReference wr;

        public EventHandler(MainActivity r) {
            wr = new WeakReference(r);
        }

        @Override
        public void handleMessage(android.os.Message msg) {
            MainActivity activity = wr.get();
            switch (msg.what) {
                case 1:
                    if (activity.mStringArray.size()!= 0){
                        //无限循环
                        int i = activity.mLoopCount % activity.mStringArray.size();
                        // 向上滚动翻页
                        activity.mAutoTextView.next();
                        //给AutoTextView 设置文字
                        activity.mAutoTextView.setText(activity.mStringArray.get(i));
                        activity.mLoopCount ++;
                        //Value为FLAG的消息延迟0.5秒
                        activity.mEventHandler.sendEmptyMessageDelayed(FLAG, 500);
                    }
                    break;
            }
        }
    }

在页面结束时一定要释放掉handler:

 //停止动画,释放handler
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mEventHandler != null){
                    //移出消息
                    mEventHandler.removeMessages(FLAG);
                    mEventHandler = null;
                }

            }
        });

xml文件:

注意  一定要在布局文件的父控件添加:

  xmlns:auto3d="http://schemas.android.com/apk/res-auto"

下面附上demo下载地址:

https://download.csdn.net/download/shanshan_1117/10315694

点击打开链接


你可能感兴趣的:(自定义view)