自定義View合輯(5)-仿QQ郵箱下拉重新整理

leavesC發表於2019-05-07

為了加強對自定義 View 的認知以及開發能力,我計劃這段時間陸續來完成幾個難度從易到難的自定義 View,並簡單的寫幾篇部落格來進行介紹,所有的程式碼也都會開源,也希望讀者能給個 star 哈 GitHub 地址:github.com/leavesC/Cus… 也可以下載 Apk 來體驗下:www.pgyer.com/CustomView

先看下效果圖:

自定義View合輯(5)-仿QQ郵箱下拉重新整理

和 QQ郵箱 官方的還是有點差別的,沒完成仿造成功,不過大概思路明白了就可以的了~

以左邊的小圓作為例子,其變化規律是這樣的

  • 小圓半徑從 0 逐漸增大到 minRadius ,此過程只是半徑增大,其座標點不變,依然處於最左邊
  • 小圓從左邊逐漸位移到中間位置,此過程半徑逐漸從 minRadius 增大到 maxRadius,X 座標逐漸增大,Y 座標不變
  • 小圓從中間逐漸位移到最右邊,此過程半徑從 maxRadius 逐漸減小到 minRadius,X 座標逐漸增大,Y 座標不變
  • 小圓處於最右邊保持座標點不變,半徑逐漸從 minRadius 減小到 0

三個小圓的變化規律都是如上所述,只是起始狀態有所差別而已,可以規定各個狀態佔總的動畫時間的四分之一,因此 CircleRefreshView 的重點就在於根據動畫值的變化來計算三個小圓的座標系以及半徑大小

    private void updateCircle(int index, float fraction) {
        //             x              x               x
        // ------------||-------------||--------------||------------
        //            1/4            2/4             3/4
        //      1/4            2/4            3/4            4/4

        //   左邊-綠色
        // 半徑從0到min  半徑從min到max    半徑從max到min   半徑從min到0

        //   中間-橙色
        //                                半徑從max到min   半徑從min到0
        //半徑從0到min   半徑從min到max

        //   右邊-紅色
        //                                                 半徑從min到0
        //半徑從0到min  半徑從min到max     半徑從max到min

        float radius = 0;
        float x = 0;
        switch (index) {
            case LEFT: {
                if (fraction <= 1f / 4f) {
                    radius = minRadius * (4f * fraction);
                    x = minRadius;
                } else if (fraction <= 0.5f) {
                    float percent = (fraction - 1f / 4f) * 4f;
                    radius = minRadius + percent * (maxRadius - minRadius);
                    x = minRadius + percent * (contentWidth / 2f - minRadius);
                } else if (fraction <= 3f / 4f) {
                    float percent = (fraction - 0.5f) * 4f;
                    radius = maxRadius - percent * (maxRadius - minRadius);
                    x = contentWidth / 2f + percent * (contentWidth / 2f - minRadius);
                } else {
                    radius = minRadius - (fraction - 3f / 4f) * 4f * minRadius;
                    x = contentWidth - minRadius;
                }
                break;
            }
            case CENTER: {
                if (fraction <= 1f / 4f) {
                    float percent = fraction * 4f;
                    radius = maxRadius - (maxRadius - minRadius) * percent;
                    x = contentWidth / 2f + (contentWidth / 2f - minRadius) * percent;
                } else if (fraction <= 0.5f) {
                    radius = minRadius - (fraction - 1f / 4f) * 4f * minRadius;
                    x = contentWidth - minRadius;
                } else if (fraction <= 3f / 4f) {
                    radius = minRadius * (4f * (fraction - 0.5f));
                    x = minRadius;
                } else {
                    float percent = (fraction - 3f / 4f) * 4f;
                    radius = minRadius + (maxRadius - minRadius) * percent;
                    x = minRadius + (contentWidth / 2f - minRadius) * percent;
                }
                break;
            }
            case RIGHT: {
                if (fraction <= 1f / 4f) {
                    radius = minRadius - 4f * fraction * minRadius;
                    x = contentWidth - minRadius;
                } else if (fraction <= 0.5f) {
                    radius = minRadius * (4f * (fraction - 1f / 4f));
                    x = minRadius;
                } else if (fraction <= 3f / 4f) {
                    float percent = (fraction - 0.5f) * 4f;
                    radius = minRadius + (maxRadius - minRadius) * percent;
                    x = minRadius + (contentWidth / 2f - minRadius) * percent;
                } else {
                    float percent = (fraction - 3f / 4f) * 4f;
                    radius = maxRadius - (maxRadius - minRadius) * percent;
                    x = contentWidth / 2f + (contentWidth / 2f - minRadius) * percent;
                }
                break;
            }
        }
        Circle circle = circleList.get(index);
        circle.radius = radius;
        circle.x = x;
    }
複製程式碼

然後在 onDraw 方法裡直接繪製三個小圓點即可

    @Override
    protected void onDraw(Canvas canvas) {
        for (Circle circle : circleList) {
            paint.setColor(circle.color);
            canvas.drawCircle(circle.x + getPaddingLeft(), circle.y + getPaddingTop(), circle.radius, paint);
        }
    }
複製程式碼

相關文章