自定義view————廣告彈窗

madreain發表於2017-08-10

今天給大家帶來自定義view————廣告彈窗,效果圖中的照片文字都是隨便找的,實際專案中根據UI的設計稍微修改修改基本上就能達到預想的效果了(注:女神劉亦菲的圖是好好找的!!!)

效果圖
效果圖

效果圖看完了,接下來分析一下實現過程,首先整體是繼承Dialog去實現的,組合自定義view達到預想效果,倒數計時是一個畫圈圈的過程,接下來詳細講解吧

畫給倒數計時的圈圈

一個背景色的底盤drawCircle(),一個畫圈圈drawArc(),一個文字的顯示,今天這裡的文字顯示採取了一個新的實現方式StaticLayout(android中處理文字換行的一個工具類)

//畫底盤
        canvas.drawCircle(width / 2, height / 2, min / 2, circlePaint);
        //畫邊框
        RectF rectF;
        if (width > height) {
            rectF = new RectF(width / 2 - min / 2 + borderWidth / 2, 0 + borderWidth / 2, width / 2 + min / 2 - borderWidth / 2, height - borderWidth / 2);
        } else {
            rectF = new RectF(borderWidth / 2, height / 2 - min / 2 + borderWidth / 2, width - borderWidth / 2, height / 2 - borderWidth / 2 + min / 2);
        }
        canvas.drawArc(rectF, -90, progress, false, borderPaint);
        //畫居中的文字
        canvas.translate(width / 2, height / 2 - staticLayout.getHeight() / 2);
        staticLayout.draw(canvas);複製程式碼

看到這裡staticLayout是那裡來的呀,看下面就知道了

    int textWidth = (int) textPaint.measureText(text.substring(0, text.length()));
        staticLayout = new StaticLayout(text, textPaint, textWidth, Layout.Alignment.ALIGN_NORMAL, 1F, 0, false);複製程式碼

靜態的圈圈背景都已經就位,現在開始執行倒數計時動畫,這裡寫的是5s

是時候讓圈圈動起來了

這裡採用倒數計時器來倒數計時然後通知重新整理動畫


   //倒數計時
     public void start() {
         if (listener != null) {
             listener.onStartCount();
         }
         //倒數計時器     第一個參數列示總時間,第二個參數列示間隔時間
         new CountDownTimer((long) lastTime, 30) {
             @Override
             public void onTick(long millisUntilFinished) {
                 progress = 360 - ((lastTime - millisUntilFinished) / lastTime) * 360;
                 invalidate();
             }

             @Override
             public void onFinish() {
                 progress = 0;
                 invalidate();
                 if (listener != null) {
                     listener.onFinishCount();
                 }
             }
         }.start();
     }複製程式碼

倒數計時的準備工作做好了,將倒數計時的完整程式碼奉上

/**
 * Created by Administrator on 2017/8/10.
 * 廣告倒數計時
 *
 * @auther madreain
 */

public class CountDownView extends View {

    private static final int BACKGROUND_COLOR = 0x50555555;
    private static final float BORDER_WIDTH = 15f;
    private static final int BORDER_COLOR = 0xFF6ADBFE;
    private static final String TEXT = "跳過";
    private static final float TEXT_SIZE = 50f;
    private static final int TEXT_COLOR = 0xFFFFFFFF;

    int width;
    int height;
    int min;

    private int backgroundColor;
    private float borderWidth;
    private int borderColor;
    private String text;
    private int textColor;
    private float textSize;

    private Paint circlePaint;
    private TextPaint textPaint;
    private Paint borderPaint;

    private float progress = 360;
    private StaticLayout staticLayout;

    private CountDownTimerListener listener;

    //倒數計時 顯示5秒什麼的
    float lastTime = 5000;

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

    public CountDownView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CountDownView);
        backgroundColor = ta.getColor(R.styleable.CountDownView_background_color, BACKGROUND_COLOR);
        borderWidth = ta.getDimension(R.styleable.CountDownView_borders_width, BORDER_WIDTH);
        borderColor = ta.getColor(R.styleable.CountDownView_borders_color, BORDER_COLOR);
        text = ta.getString(R.styleable.CountDownView_text);
        if (text == null) {
            text = TEXT;
        }
        textSize = ta.getDimension(R.styleable.CountDownView_text_size, TEXT_SIZE);
        textColor = ta.getColor(R.styleable.CountDownView_text_color, TEXT_COLOR);
        ta.recycle();
        init();
    }

    private void init() {
        circlePaint = new Paint();
        circlePaint.setAntiAlias(true);
        circlePaint.setDither(true);
        circlePaint.setColor(backgroundColor);
        circlePaint.setStyle(Paint.Style.FILL);

        textPaint = new TextPaint();
        textPaint.setAntiAlias(true);
        textPaint.setDither(true);
        textPaint.setColor(textColor);
        textPaint.setTextSize(textSize);
        textPaint.setTextAlign(Paint.Align.CENTER);

        borderPaint = new Paint();
        borderPaint.setAntiAlias(true);
        borderPaint.setDither(true);
        borderPaint.setColor(borderColor);
        borderPaint.setStrokeWidth(borderWidth);
        borderPaint.setStyle(Paint.Style.STROKE);

        int textWidth = (int) textPaint.measureText(text.substring(0, text.length()));
        staticLayout = new StaticLayout(text, textPaint, textWidth, Layout.Alignment.ALIGN_NORMAL, 1F, 0, false);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        if (widthMode != MeasureSpec.EXACTLY) {
            width = staticLayout.getWidth();
        }
        if (heightMode != MeasureSpec.EXACTLY) {
            height = staticLayout.getHeight();
        }
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width=w;
        height=h;
        min = Math.min(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //畫底盤
        canvas.drawCircle(width / 2, height / 2, min / 2, circlePaint);
        //畫邊框
        RectF rectF;
        if (width > height) {
            rectF = new RectF(width / 2 - min / 2 + borderWidth / 2, 0 + borderWidth / 2, width / 2 + min / 2 - borderWidth / 2, height - borderWidth / 2);
        } else {
            rectF = new RectF(borderWidth / 2, height / 2 - min / 2 + borderWidth / 2, width - borderWidth / 2, height / 2 - borderWidth / 2 + min / 2);
        }
        canvas.drawArc(rectF, -90, progress, false, borderPaint);
        //畫居中的文字
        canvas.translate(width / 2, height / 2 - staticLayout.getHeight() / 2);
        staticLayout.draw(canvas);
    }


    //倒數計時
    public void start() {
        if (listener != null) {
            listener.onStartCount();
        }
        //倒數計時器     第一個參數列示總時間,第二個參數列示間隔時間
        new CountDownTimer((long) lastTime, 30) {
            @Override
            public void onTick(long millisUntilFinished) {
                progress = 360 - ((lastTime - millisUntilFinished) / lastTime) * 360;
                invalidate();
            }

            @Override
            public void onFinish() {
                progress = 0;
                invalidate();
                if (listener != null) {
                    listener.onFinishCount();
                }
            }
        }.start();
    }

    public void setCountDownTimerListener(CountDownTimerListener listener) {
        this.listener = listener;
    }

    public interface CountDownTimerListener {
        void onStartCount();

        void onChangeCount(int second);

        void onFinishCount();
    }
}複製程式碼

廣告彈窗

廣告彈窗上的倒數計時已經準備好了,開始組合自定義view的撰寫了,後期實際專案開發中,這一塊可以根據實際情況修改組合的view佈局

/**
 * Created by Administrator on 2017/8/10.
 * 閃屏廣告
 *
 * @auther madreain
 */

public class SplashDialog extends Dialog {

    private Context mContext;
    //展示的
    AdvertisingImgModel advertisingImgModel;

    //背景照片
    private ImageView img_background;
    //倒數計時
    private CountDownView count_down_view;

    private OnSplashDetailClickListener onSplashDetailClickListener;

    public SplashDialog(Context context, AdvertisingImgModel advertisingImgModel) {
        super(context, R.style.ADDialog);
        mContext = context;
        this.advertisingImgModel = advertisingImgModel;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splash_dialog);
        full(true);
        initView();
    }

    /**
     * @param enable false 顯示,true 隱藏
     */
    private void full(boolean enable) {
        WindowManager.LayoutParams p = this.getWindow().getAttributes();
        if (enable) {

            p.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;//|=:或等於,取其一

        } else {
            p.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN);//&=:與等於,取其二同時滿足,     ~ : 取反

        }
        getWindow().setAttributes(p);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
    }

    private void initView() {

        img_background = (ImageView) findViewById(R.id.img_background);
        Glide.with(mContext).load(advertisingImgModel.getImgurl()).into(img_background);
        //廣告倒數計時
        count_down_view = (CountDownView) findViewById(R.id.count_down_view);
        count_down_view.setCountDownTimerListener(new CountDownView.CountDownTimerListener() {
            @Override
            public void onStartCount() {

            }

            @Override
            public void onChangeCount(int second) {

            }

            @Override
            public void onFinishCount() {
                dismiss();
            }
        });
        //啟動倒數計時
        count_down_view.start();
        //點選跳過按鈕
        count_down_view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
            }
        });
        //點選事件
        img_background.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (onSplashDetailClickListener != null) {
                    onSplashDetailClickListener.onSplashDetailClick(advertisingImgModel);
                }
                dismiss();
            }
        });

    }


    public void setOnSplashDetailClickListener(OnSplashDetailClickListener onSplashDetailClickListener) {
        this.onSplashDetailClickListener = onSplashDetailClickListener;
    }

    public interface OnSplashDetailClickListener {
        void onSplashDetailClick(AdvertisingImgModel advertisingImgModel);
    }

}複製程式碼

程式碼中使用

  txt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AdvertisingImgModel advertisingImgModel = new AdvertisingImgModel(1, "http://bmob-cdn-10899.b0.upaiyun.com/2017/05/09/34b6d85c406894f3803d949a78c4546e.jpg");
                splashDialog = new SplashDialog(MainActivity.this, advertisingImgModel);
                splashDialog.setOnSplashDetailClickListener(new SplashDialog.OnSplashDetailClickListener() {
                    @Override
                    public void onSplashDetailClick(AdvertisingImgModel advertisingImgModel) {
                        Toast.makeText(MainActivity.this, "跳轉到廣告的詳情頁", Toast.LENGTH_SHORT).show();
                    }
                });
                splashDialog.show();
            }
        });複製程式碼

大家如果有什麼好的自定義view推薦練手的,歡迎留言

SplashView github demo

相關文章