Android自定義View實現(xiàn)仿美團底部導航動畫

目錄

效果展示

實現(xiàn)原理

這個效果主要是運用了貝塞爾曲線、自定義ViewGroup以及動畫的知識。
1.貝塞爾曲線(用于實現(xiàn)順暢的圓?。?/strong>
一個自定義的ViewGroup中總共使用了三段貝塞爾曲線:


而要做到三段貝塞爾曲線完美對接,則需要使第一段貝塞爾曲線的控制點與第二段貝塞爾曲線的起始點和控制點,三點在一條直線上,因此B點需要隨著C點的升高。(如下圖所示)

2.自定義ViewGroup
這里為了簡單我是直接繼承LinearLayout通過重寫onMeasure方法來實現(xiàn)的,主要是對控件 的高度做了調(diào)整,代碼如下:

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if(imgChild == null){
            //獲取ImageView 和ImageView 的寬度
            for(int i = 0 ; i < getChildCount() ; i++){
                View child = getChildAt(i);
                if(child instanceof ImageView){
                    imgChild = (ImageView) child;
                    imgChildWidth = imgChild.getMeasuredWidth();
                    LinearLayout.LayoutParams layoutParams = (LayoutParams) imgChild.getLayoutParams();
                    layoutParams.topMargin += (imgChildWidth / 2 + offsetFloatHeight);//整體的高度等于自適應高度加浮動的高度加偏移的高度
                    imgChild.setLayoutParams(layoutParams);
                    Log.e("寬度",imgChildWidth+"");
                    break;
                }
            }
        }
    }

3.動畫
這里我總共定義了兩個動畫,一個用來浮起一個用來縮回,其中浮起的動畫加了個頂部回彈的效果,代碼如下:

 /**
     * 加載縮回的動畫
     */
    private void initRestractAnim() {
        if(animatorRestract == null){
            animatorRestract = ValueAnimator.ofFloat(imgChildWidth / 2f, 0);
            animatorRestract.setDuration(500);
            animatorRestract.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float animatedValue = (float) animation.getAnimatedValue();
                    if(imgChild != null){
                        imgChild.setTranslationY(-animatedValue/3);
                    }
                    setFloatHeight(animatedValue);
                }
            });
        }
    }

    /**
     * 加載浮起的動畫
     */
    private void initFloatAnim() {
        if(animatorFloat == null){
            animatorFloat = ValueAnimator.ofFloat(0, imgChildWidth / 2f + offsetFloatHeight,imgChildWidth / 2f);
            animatorFloat.setDuration(500);
            animatorFloat.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float animatedValue = (float) animation.getAnimatedValue();
                    if(imgChild != null){
                        imgChild.setTranslationY(-animatedValue/3);
                    }
                    setFloatHeight(animatedValue);
                }
            });
        }
    }

案例源碼

想要詳細了解的同學可以在這下載源碼:https://gitee.com/itfitness/FitnessLib

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容