教你如何實現(xiàn)AndroidTextView文字輪播效果

效果圖:
教你如何實現(xiàn) Android TextView 文字輪播效果

成都創(chuàng)新互聯(lián)公司專注于融安網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供融安營銷型網(wǎng)站建設(shè),融安網(wǎng)站制作、融安網(wǎng)頁設(shè)計、融安網(wǎng)站官網(wǎng)定制、小程序開發(fā)服務(wù),打造融安網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供融安網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。

實現(xiàn)思路:

1.ViewAnimator 思路

使用 ViewAnimator 自身特性,對期中的子 view 實現(xiàn)動畫切換

2.自定義 viewGroup 思路

在這個思路下,我們自定義一個容器,繼承 FrameLayout ,根據(jù)數(shù)據(jù)數(shù)量自己 new 相應(yīng)數(shù)量的 itemView 出來加入 FrameLayout ,動畫是通過對當(dāng)前 itemView 做一個出去的佛納甘話,同時對下一個 itemView 做一個進入動畫,使用 handle 實現(xiàn)延遲輪換

3.ViewFlipper 思路

ViewFlipper 思路和 ViewAnimator 一樣,不過 ViewFlipper 使用上更靈活,這里我們根據(jù)數(shù)據(jù)流量動態(tài)往 ViewFlipper 里添加 itemView

4.自定義 textView 思路

其實這個思路也好理解,我們繼承 textView ,然后在 onDraw 繪制中自己話文字,自己做動畫,動畫的思路是先把上一個文字上移到頂,然后再繪制下一個文字,從下面開始一直移動到中間

ViewAnimator 思路

ViewAnimator 是個 viewGroup ,可以實現(xiàn)動畫切換其中子 view 的效果。在 xml 布局種,我們把 ViewAnimator 當(dāng)一個容器,里面寫輪播的 view,寫多少個 view 就有多少個輪播,然后設(shè)置切換的動畫,用 handle 做定時延遲輪播,調(diào) ViewAnimator.onNext 就可以切換到下一個 view

實現(xiàn)思路:

1.先在 layout xml 中聲明布局層級結(jié)構(gòu):

 <ViewAnimator
        android:layout_width="match_parent"
        android:layout_height="200dp">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="歡迎"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="測試"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="本程序"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="!!!!!"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="hello,world"/>
    </ViewAnimator>

2.代碼種設(shè)置切換動畫

viewAnimator.setOutAnimation(this, R.anim.slide_out_up);
viewAnimator.setInAnimation(this, R.anim.slide_in_down);

3.handle 延遲循環(huán)顯示下一個

      public void showNext() {
        viewAnimator.showNext();
    }

    public void showPrevious() {
        viewAnimator.showPrevious();
    }

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (autoPlayFlag) {
                showNext();
            }
            handler.sendMessageDelayed(new Message(), TIME_INTERVAL);
        }
    };

我們在需要的位置發(fā)送 handle 事件就可以了

使用 ViewAnimator 有點和確定同樣明顯

  • 優(yōu)點:使用簡單,沒有難度
  • 缺點:xml 中固定了 view個數(shù),為了兼容不同數(shù)據(jù)量,我們需要再 ViewAnimator 基礎(chǔ)上 2 次開發(fā)

自定義 viewGroup 思路

在這個思路下,我們自定義一個容器,繼承 FrameLayout ,根據(jù)數(shù)據(jù)數(shù)量自己 new 相應(yīng)數(shù)量的 itemView 出來加入 FrameLayout ,動畫是通過對當(dāng)前 itemView 做一個出去的佛納甘話,同時對下一個 itemView 做一個進入動畫,使用 handle 實現(xiàn)延遲輪換

思路如下

1.在設(shè)置數(shù)據(jù)時添加相應(yīng)數(shù)量的 itemView 進去

    public void setNoticeList(List<String> list) {

        // 創(chuàng)建TextView
        for (int i = 0; i < list.size(); i++) {
            TextView textView = createTextView(list.get(i));
            mNoticeList.add(textView);
            addView(textView);
        }
        // 顯示第一條公告
        mCurrentNotice = 0;
        mNoticeList.get(mCurrentNotice).setVisibility(VISIBLE);
        // 啟動輪播
        start();
    }

    private TextView createTextView(String text) {
        if (mLayoutParams == null) {
            mLayoutParams = new LayoutParams(
                    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
            mLayoutParams.gravity = Gravity.CENTER_VERTICAL;
        }

        TextView textView = new TextView(getContext());
        textView.setLayoutParams(mLayoutParams);
        textView.setSingleLine();
        textView.setEllipsize(TextUtils.TruncateAt.END);
        textView.setTextColor(mTextColor);
        textView.setVisibility(GONE);
        textView.setText(text);
        // 如果有設(shè)置字體大小,如果字體大小為null。
        if (mTextSize > 0) {
            textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize);
        }
        return textView;
    }

2.在 handle 里面啟動 itemView 切換的動畫

     class NoticeRunnable implements Runnable {
        @Override
        public void run() {
            // 隱藏當(dāng)前的textView
            TextView currentView = mNoticeList.get(mCurrentNotice);
            currentView.setVisibility(GONE);
            if(mExitAnimSet != null) {
                currentView.startAnimation(mExitAnimSet);
            }
            mCurrentNotice++;
            if(mCurrentNotice >= mNoticeList.size()) {
                mCurrentNotice = 0;
            }

            // 顯示下一個TextView
            TextView nextView = mNoticeList.get(mCurrentNotice);
            nextView.setVisibility(VISIBLE);
            if(mEnterAnimSet != null) {
                nextView.startAnimation(mEnterAnimSet);
            }
            mHandler.postDelayed(this, mNoticeDuration);
        }
    }

    private void createEnterAnimation() {
        mEnterAnimSet = new AnimationSet(false);
        TranslateAnimation translateAnimation =
                new TranslateAnimation(0,0,0,0, TranslateAnimation.RELATIVE_TO_PARENT, 1f,
                        TranslateAnimation.RELATIVE_TO_SELF, 0f);
        AlphaAnimation alphaAnimation = new AlphaAnimation(0f,1f);
        mEnterAnimSet.addAnimation(translateAnimation);
        mEnterAnimSet.addAnimation(alphaAnimation);
        mEnterAnimSet.setDuration(DEFAULT_ANIMATION_DURATION);
    }

    private void createExitAnimation() {
        mExitAnimSet = new AnimationSet(false);
        TranslateAnimation translateAnimation =
                new TranslateAnimation(0,0,0,0, TranslateAnimation.RELATIVE_TO_SELF, 0f,
                        TranslateAnimation.RELATIVE_TO_PARENT, -1f);
        AlphaAnimation alphaAnimation = new AlphaAnimation(1f,0f);
        mExitAnimSet.addAnimation(translateAnimation);
        mExitAnimSet.addAnimation(alphaAnimation);
        mExitAnimSet.setDuration(DEFAULT_ANIMATION_DURATION);
    }

這樣寫最練手,但是我是不推薦這樣干的,基礎(chǔ)差一些的容易出問題,而且 google 給我們提供了一些實現(xiàn),我們何必非的自己實現(xiàn)呢,這樣寫會花點時間

ViewFlipper 思路

ViewFlipper 思路像是上面 1 和 2 的結(jié)合,ViewFlipper 對動畫的控制更優(yōu)秀一些,我們往 ViewFlipper 里面動態(tài)添加 itemView ,基本都是這個思路,區(qū)別是使用的容器不同
這里推薦一個成熟的庫:

  • TextBannerView

這個庫非常完善了,也能滿足大家的常用需求,是可以拿來直接用的,大家看圖就明白了
教你如何實現(xiàn) Android TextView 文字輪播效果

思路如下

他這里自定義了一個 ViewGroup 繼承自 RelativeLayout,在 view 初始化時添加了一個 ViewFlipper 進來,之后操作的都是這個 ViewFlipper 了

1.自定義 ViewGroup 初始化時添加了 ViewFlipper

    /**初始化控件*/
    private void init(Context context, AttributeSet attrs, int defStyleAttr) {

        mViewFlipper = new ViewFlipper(getContext());//new 一個ViewAnimator
        mViewFlipper.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        addView(mViewFlipper);
        startViewAnimator();
        //設(shè)置點擊事件
        mViewFlipper.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = mViewFlipper.getDisplayedChild();//當(dāng)前顯示的子視圖的索引位置
                if (mListener!=null){
                    mListener.onItemClick(mDatas.get(position),position);
                }
            }
        });

2.根據(jù)數(shù)據(jù)添加 itemView

      /**設(shè)置數(shù)據(jù)集合*/
    public void setDatas(List<String> datas){
        this.mDatas = datas;
        if (DisplayUtils.notEmpty(mDatas)){
            mViewFlipper.removeAllViews();
            for (int i = 0; i < mDatas.size(); i++) {
                TextView textView = new TextView(getContext());
                textView.setText(mDatas.get(i));
                //任意設(shè)置你的文字樣式,在這里
                textView.setSingleLine(isSingleLine);
                textView.setTextColor(mTextColor);
                textView.setTextSize(mTextSize);
                textView.setGravity(mGravity);

                mViewFlipper.addView(textView,i);//添加子view,并標(biāo)識子view位置
            }
        }
    }

3.添加動畫

    /**
     * 設(shè)置進入動畫和離開動畫
     *
     * @param inAnimResId  進入動畫的resID
     * @param outAnimResID 離開動畫的resID
     */
    private void setInAndOutAnimation(@AnimRes int inAnimResId, @AnimRes int outAnimResID) {
        Animation inAnim = AnimationUtils.loadAnimation(getContext(), inAnimResId);
        inAnim.setDuration(animDuration);
        mViewFlipper.setInAnimation(inAnim);

        Animation outAnim = AnimationUtils.loadAnimation(getContext(), outAnimResID);
        outAnim.setDuration(animDuration);
        mViewFlipper.setOutAnimation(outAnim);
    }

之后就是用 handle 來做延遲循環(huán),上面復(fù)制好幾遍了,這里是在不想再復(fù)制了,打個源碼很簡單,大家直接看。

吐槽下:這個庫多了一道手,多加了一個視圖層級出來,其實沒必要在頂層加一個 viewGroup 了,直接繼承 ViewFlipper 可好

自定義 textView 思路

不繼承 textView 我們直接繼承 view 都可以,只要不支持 wrap_content 就好辦。 核心就是在 onDraw 中實現(xiàn)繪制的動畫。
例子這里沒有使用 ValueAnimator 動畫,而是 1 個 px 變化就重繪一次,性能上欠考慮。

實現(xiàn)思路

1.根據(jù)文字,確定文字出屏幕的零界點

// 獲取文字矩陣的尺寸
Rect indexBound = new Rect();
mPaint.getTextBounds(text, 0, text.length(), indexBound);

// 文字居中繪制 Y 的坐標(biāo)
my = mHeight  / 2 - (bound.top + bound.bottom) / 2

// 文字移動到最頂部
mY == 0 - bound.bottom

// 文字移動到最下部
mY = mHeight  - indexBound.top;

2.在 onDraw 中實現(xiàn)繪制
         // 文字首先繪制在最底部,mY 初始時 = 0
        if (mY == 0) {
            mY = getMeasuredHeight() - indexBound.top;
        }

        // 文字移動到最頂部時,更換數(shù)據(jù),把文字移動到最底部
        if (mY == 0 - indexBound.bottom) {
            Log.i(TAG, "onDraw: " + getMeasuredHeight());
            mY = getMeasuredHeight() - indexBound.top;//返回底部
            mIndex++;//換下一組數(shù)據(jù)
        }

        // 文字移動到中間時,停止 handle 的重繪任務(wù),延遲標(biāo)準(zhǔn)時間后再開始
        if (mY == getMeasuredHeight() / 2 - (indexBound.top + indexBound.bottom) / 2) {
            isMove = false;//停止移動
            // handle 通知標(biāo)準(zhǔn)時間后開始重繪
        }

        // 處理完 Y 坐標(biāo),開始繪制文字
        canvas.drawText(font, 0, font.length(), 10, mY, mPaintFront);

        // 最后移動 1 個 px,以實現(xiàn)動畫效果
        mY -= 1

這里強調(diào)每移動 1個 px 就重繪一遍是為了確保動畫的連貫性,但是這樣系統(tǒng)也是 16 ms 才繪制一幀的,這樣高頻率的重繪并不是最優(yōu)選擇哦

分享標(biāo)題:教你如何實現(xiàn)AndroidTextView文字輪播效果
轉(zhuǎn)載來于:http://bm7419.com/article20/jcgojo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營銷、靜態(tài)網(wǎng)站、服務(wù)器托管、App設(shè)計、全網(wǎng)營銷推廣、響應(yīng)式網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作