android 頁面加載效果(Dialog類型效果)

這個屬於頁面打開時的延遲加載效果,總的來說比較好用,網絡太卡的時候也不至於沒辦法進行操作,當然也存在沒有加載完成而產生的誤操作可能性,具體還是要看項目的需要。

公共類:

public class CustomProgressDialog extends Dialog {
    private Context context = null;
    private static CustomProgressDialog customProgressDialog = null;

    public CustomProgressDialog(Context context){
        super(context);
        this.context = context;
    }

    public CustomProgressDialog(Context context, int theme) {
        super(context, theme);
    }

    public static CustomProgressDialog createDialog(Context context){
        customProgressDialog = new CustomProgressDialog(context, R.style.CustomProgressDialog);
        customProgressDialog.setContentView(R.layout.customprogressdialog);
        customProgressDialog.getWindow().getAttributes().gravity = Gravity.CENTER;

        return customProgressDialog;
    }

    public void onWindowFocusChanged(boolean hasFocus){

        if (customProgressDialog == null){
            return;
        }

//        ImageView imageView = (ImageView) customProgressDialog.findViewById(R.id.loadingImageView);
//        AnimationDrawable animationDrawable = (AnimationDrawable) imageView.getBackground();
//        animationDrawable.start();
    }

    /**
     *
     * [Summary]
     *       setTitile 標題
     * @param strTitle
     * @return
     *
     */
    public CustomProgressDialog setTitile(String strTitle){
        return customProgressDialog;
    }

    /**
     *
     * [Summary]
     *       setMessage 提示內容
     * @param strMessage
     * @return
     *
     */
    public CustomProgressDialog setMessage(String strMessage){
        TextView tvMsg = (TextView)customProgressDialog.findViewById(R.id.id_tv_loadingmsg);

        if (tvMsg != null){
            tvMsg.setText(strMessage);
        }

        return customProgressDialog;
    }
}

佈局文件xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">
    <com.meikuang.landongjiguang.renyuandingwei.PublicClass.WindowsLoad
        android:id="@+id/windows_load"
        android:layout_width="80dp"
        android:layout_height="80dp" />
    <ImageView
        android:id="@+id/loadingImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"/>
    <TextView
        android:id="@+id/id_tv_loadingmsg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:textSize="20sp"/>
</LinearLayout>

加載動畫文件:

public class WindowsLoad extends View {
    private float pi = (float) Math.PI;
    private String TAG = "WindowsLoad";
    private Paint paint;
    private int R;
    private float circleR;
    private ValueAnimator circleAnimator1;
    private ValueAnimator circleAnimator2;
    private ValueAnimator circleAnimator3;
    private boolean init = true;
    float x1, x2, x3, y1, y2, y3;

    public WindowsLoad(Context context, AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.parseColor("#ffffff"));
        R = 10;
    }


    float[] circleCentre;
    float[] start1;
    float[] start2;
    float[] start3;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //初始化
        if (init) {
            circleCentre = new float[]{getWidth() / 2, getHeight() / 2};
            start1 = new float[]{getWidth() / 2, R};
            start2 = onCiecleCoordinate(-0.5f, start1, circleCentre);
            start3 = onCiecleCoordinate(-0.5f, start2, circleCentre);
            init = false;
            loading();
        }
//        canvas.drawCircle(start1[0], start1[1], R, paint);
//        Log.d(TAG, "onDraw() returned: "+ start1[0]+"   "+start1[1] +"   "+ start2[0]+"   "+start2[1]);

        //第一個點初始位置
        if (!circleAnimator1.isRunning()) {
            canvas.drawCircle(start1[0], start1[1], R, paint);
        }
        //第二個點初始位置
        if (!circleAnimator2.isRunning()) {
            canvas.drawCircle(start2[0], start2[1], R, paint);
        }
        //第三個點初始位置
        if (!circleAnimator3.isRunning()) {
            canvas.drawCircle(start3[0], start3[1], R, paint);
        }

        if (circleAnimator1.isRunning()) {
            x1 = (float) (circleCentre[0] + circleR * Math.cos((float) circleAnimator1.getAnimatedValue()));
            y1 = (float) (circleCentre[1] + circleR * Math.sin((float) circleAnimator1.getAnimatedValue()));
            canvas.drawCircle(x1, y1, R, paint);
        }
        if (circleAnimator2.isRunning()) {
            x2 = (float) (circleCentre[0] + circleR * Math.cos((float) circleAnimator2.getAnimatedValue()));
            y2 = (float) (circleCentre[1] + circleR * Math.sin((float) circleAnimator2.getAnimatedValue()));
            canvas.drawCircle(x2, y2, R, paint);
        }
        if (circleAnimator3.isRunning()) {
            x3 = (float) (circleCentre[0] + circleR * Math.cos((float) circleAnimator3.getAnimatedValue()));
            y3 = (float) (circleCentre[1] + circleR * Math.sin((float) circleAnimator3.getAnimatedValue()));
            canvas.drawCircle(x3, y3, R, paint);
        }
        if (circleAnimator1.isRunning() || circleAnimator2.isRunning() || circleAnimator3.isRunning()) {
            invalidate();
        }
    }


    private void loading() {
        circleAnimator1 = getCircleData(start1, circleCentre, 0);
        circleAnimator1.start();
        circleAnimator2 = getCircleData(start2, circleCentre, 300);
        circleAnimator2.start();
        circleAnimator3 = getCircleData(start3, circleCentre, 600);
        circleAnimator3.start();
        postDelayed(new Runnable() {
            @Override
            public void run() {
                loading();
                invalidate();
            }
        }, circleAnimator3.getDuration() + 600);
    }

    private SlowToQuick slowToQuick = new SlowToQuick();

    private ValueAnimator getCircleData(float[] startCoordinate, float[] RCoordinate, int delay) {
        float x1 = startCoordinate[0];
        float y1 = startCoordinate[1];
        float x0 = RCoordinate[0];
        float y0 = RCoordinate[1];
//        Log.i(TAG, "getCircleData x y: " + x1+"  ,"+y1+"  x0  "+x0+ " y0  "+y0);
        circleR = (float) Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
        float param = (float) (Math.abs(y1 - y0) / circleR);
        if (param < -1.0) {
            param = -1.0f;
        } else if (param > 1.0) {
            param = 1.0f;
        }
        float a = (float) Math.asin(param);
        if (x1 >= x0 && y1 >= y0) {
            a = a;
        } else if (x1 < x0 && y1 >= y0) {
            a = pi - a;
        } else if (x1 < x0 && y1 < y0) {
            a = a + pi;
        } else {
            a = 2 * pi - a;
        }
        ValueAnimator circleAnimator = ValueAnimator.ofFloat(a, a + 2 * pi);
        circleAnimator.setDuration(1500);
        circleAnimator.setInterpolator(slowToQuick);
        circleAnimator.setStartDelay(delay);
        return circleAnimator;
    }

    //獲取同一個圓上,間隔固定角度的點座標
    private float[] onCiecleCoordinate(float angle, float[] start, float[] center) {
        float x1 = start[0];
        float y1 = start[1];
        float x0 = center[0];
        float y0 = center[1];
        float R = (float) Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
        float param = (float) (Math.abs(y1 - y0) / R);
        if (param < -1.0) {
            param = -1.0f;
        } else if (param > 1.0) {
            param = 1.0f;
        }
        float a = (float) Math.asin(param);
        if (x1 >= x0 && y1 >= y0) {
            a = a;
        } else if (x1 < x0 && y1 >= y0) {
            a = pi - a;
        } else if (x1 < x0 && y1 < y0) {
            a = a + pi;
        } else {
            a = 2 * pi - a;
        }
        float x = (float) (center[0] + R * Math.cos(a + angle));
        float y = (float) (center[1] + R * Math.sin(a + angle));
        return new float[]{x, y};
    }

    class SlowToQuick implements Interpolator {
        @Override
        public float getInterpolation(float input) {
            return input * input;
        }
    }
}

然後再在styles.xml文件中添加以下代碼:

<style name="CustomDialog" parent="@android:style/Theme.Dialog">
        <item name="android:windowFrame">@null</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
        <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
    </style>

    <style name="CustomProgressDialog" parent="@style/CustomDialog">
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowNoTitle">true</item>
    </style>

作爲對Dialog的配置。

用法:

首先定義:

private CustomProgressDialog progressDialog = null;//加載頁

然後在開始加載頁面的地方寫入代碼:

//加載頁添加
        if (progressDialog == null){
            progressDialog = CustomProgressDialog.createDialog(getActivity());
        }
        progressDialog.show();
最後在結束加載地方寫入代碼:

//關閉加載頁
        if (progressDialog != null){
            progressDialog.dismiss();
            progressDialog = null;
        }
這樣就可以實現加載頁面效果。



P.S:動畫可以進行各種替換,但是如果對加載頁面沒有特別的特殊要求最好儘量使用代碼生成的動畫,不要使用圖片幀動畫式,一來手機可能會卡頓(畢竟在加載狀態下,原本各個進程就被佔用了),二來不容易適配(畢竟手機的分辨率不一樣,就不再需要美工挨個畫)。

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