自定義view:TextSwitcher使用、源碼分析(todo)

一、實現效果

就是一個列表的多條信息,上下切換展示,上下兩條挨着滑動。實現方法,考慮是 兩個TextView 使用動畫,不斷更新text內容。

二、TextSwitcher的使用

下面代碼看到,是集成自TextSwitcher的自定義view。主要:

1、 通過setFactory()設置 用於獲取 兩個切換view的view工廠,然後重寫Factory的makeView()方法 來定義TextView的樣式(setFactory內部會創建添加此textView兩次,即有了兩個TextView);

2、設置textVIew的進出的動畫。

3、設置列表數據,調用setText()來展示下一條。

/**
 * 垂直滾動的Textview 類似小喇叭通知
 */
public class AutoVerticalScrollTextView extends TextSwitcher implements ViewSwitcher.ViewFactory {

    private Context mContext;

    //mInUp,mOutUp分別構成向下翻頁的進出動畫
    private Rotate3dAnimation mInUp;
    private Rotate3dAnimation mOutUp;

    private int number = 0;

    private boolean isRunning = true;

    private NoticeHandler noticeHandler = new NoticeHandler();

    /**
     * 這個數組 用來存放你需要顯示的text
     */
    private ArrayList<String> data;
    private AutoVerticalScrollThread mAutoVerticalScrollThread;


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

    public AutoVerticalScrollTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        init();
    }

    private void init() {

        setFactory(this);

        mInUp = createInAnim(true, true);
        mOutUp = createOutAnim(false, true);

        setInAnimation(mInUp);//當View顯示時動畫資源ID
        setOutAnimation(mOutUp);//當View隱藏是動畫資源ID。
    }

    private Rotate3dAnimation createInAnim(boolean turnIn, boolean turnUp) {

        Rotate3dAnimation rotation = new Rotate3dAnimation(turnIn, turnUp);
        rotation.setDuration(1500);//執行動畫的時間
        rotation.setFillAfter(false);//是否保持動畫完畢之後的狀態
        rotation.setInterpolator(new AccelerateInterpolator());//設置加速模式

        return rotation;
    }

    private Rotate3dAnimation createOutAnim(boolean turnIn, boolean turnUp) {

        Rotate3dAnimation rotation = new Rotate3dAnimation(turnIn, turnUp);
        rotation.setDuration(1500);//執行動畫的時間
        rotation.setFillAfter(false);//是否保持動畫完畢之後的狀態
        rotation.setInterpolator(new AccelerateInterpolator());//設置加速模式

        return rotation;
    }


    /**
     * 這裏返回的TextView,就是我們看到的View,可以設置自己想要的效果
     *
     * @return
     */
    public View makeView() {

        TextView textView = new TextView(mContext);
        textView.setGravity(Gravity.LEFT);
        textView.setTextSize(11);//這是sp的單位
        textView.setGravity(Gravity.CENTER_VERTICAL);
        textView.setSingleLine(true);
        textView.setEllipsize(TextUtils.TruncateAt.MARQUEE);
        textView.setMarqueeRepeatLimit(1);
        textView.setTextColor(getResources().getColor(R.color.colorPrimary));//TODO
        textView.setBackgroundResource(R.drawable.text_switch_bg);

        Drawable leftDrawable = AppCompatResources.getDrawable(mContext, R.mipmap.icon_item_detail_back);
        int w = leftDrawable.getIntrinsicWidth();
        int h = leftDrawable.getIntrinsicHeight();
        leftDrawable.setBounds(0, 0, w, h);
        textView.setCompoundDrawables(leftDrawable, null, null, null);
        textView.setCompoundDrawablePadding(10);
        textView.setPadding(10,10,10,10);
        return textView;

    }

    /**
     * 定義動作,向上滾動翻頁
     */
    private void showAnimation() {
        //顯示動畫
        if (getInAnimation() != mInUp) {
            setInAnimation(mInUp);
        }
        //隱藏動畫
        if (getOutAnimation() != mOutUp) {
            setOutAnimation(mOutUp);
        }
    }

    /**
     * 傳入 要展示的 內容
     * @param data
     */
    public void setData(ArrayList<String> data) {
        this.data = data;
    }

    /**
     * 開始滾動
     */
    public void start() {
        if (mAutoVerticalScrollThread == null) {
            mAutoVerticalScrollThread = new AutoVerticalScrollThread();
        }

        isRunning = true;
        number = 0;
        if (!mAutoVerticalScrollThread.isAlive()) {
            mAutoVerticalScrollThread.start();
        }
    }

    class AutoVerticalScrollThread extends Thread {
        @Override
        public void run() {
            while (isRunning) {
                noticeHandler.sendEmptyMessage(199);
                SystemClock.sleep(4000); // TODO 這個播放間隔時間 可以作成 自定義屬性,在xml中設置
//                    noticeHandler.sendEmptyMessage(200);
//                    SystemClock.sleep(2500);
            }
        }
    }

    /**
     * 停止滾動
     */
    public void stop() {
//        getNextView().setFocusable(false);
//        getNextView().setFocusableInTouchMode(false);

        isRunning = false;

        noticeHandler.removeMessages(199);

        if (mAutoVerticalScrollThread.isAlive()) {
            mAutoVerticalScrollThread.stop();
        }
    }

    private class NoticeHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 199) {
                setText(data.get(number % data.size()));
                showAnimation();
                number++;
//
//                getCurrentView().setFocusable(false);
//                getCurrentView().setFocusableInTouchMode(false);
            }
            else if (msg.what == 200) {
                //開始 跑馬燈效果
//                getCurrentView().setFocusable(true);
//                getCurrentView().setFocusableInTouchMode(true);
            }

        }
    }

    class Rotate3dAnimation extends Animation {
        private float mCenterX;
        private float mCenterY;
        private final boolean mTurnIn;
        private final boolean mTurnUp;
        private Camera mCamera;

        public Rotate3dAnimation(boolean turnIn, boolean turnUp) {
            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();
            mCenterX = getWidth();
        }

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {

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

            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.getMatrix(matrix);
            camera.restore();

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

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章