自定義View之案列篇(一):鞭炮

licqi 8年前發布 | 5K 次閱讀 安卓開發 Android開發 移動開發

老規矩,先來看看類似過年放的鞭炮的效果圖:

block

學習博客也是學習一種變通的思想,能夠舉一反三,才能掌握真正的精髓。

這里留下一個小小的挑戰:

block

怎么獲取菱形區域的點擊事件?歡迎留言,歡迎討論,謝謝。

我臨時的處理方法是以菱形的內切圓來處理點擊事情的。

鞭炮布局(BlockFrameLayout)

分析效果圖,可以看出魔方布局是由一塊塊小的菱形按照某種規律組合而成的,我們這里以繁化簡,先來看看一塊小的菱形:

block

接著看看三塊菱形組成的圖案:

block

看看最后的效果圖:

block

是不是已經發現規律了啊?對的,以三塊菱形為一組,從上往下就組成了最終的圖案。

核心思想:分析前三塊菱形和后三塊菱形的坐標變化。

相信你已經找到了:

if ((i + 1) % 3 == 1) { //第一塊
        startX = getWidth() / 2 - mChildSize / 2;
        startY = mChildSize * bulge;
    } else if ((i + 1) % 3 == 2) { //第二塊
        startX = getWidth() / 2 - mChildSize;
        startY = mChildSize * bulge + mChildSize / 2;
    } else if ((i + 1) % 3 == 0) { //第三塊
        startX = getWidth() / 2;
        startY = mChildSize * bulge + mChildSize / 2;
        bulge++;
    }

那么 onLayout 方法:

final int childCount = getChildCount();
   int startX = 0;
   int startY = 0;
   int bulge = 0;
   for (int i = 0; i < childCount; i++) {
       View childView = getChildAt(i);
       if (childView.getVisibility() == GONE) {
           continue;
       }
       if ((i + 1) % 3 == 1) {
           startX = getWidth() / 2 - mChildSize / 2;
           startY = mChildSize * bulge;
       } else if ((i + 1) % 3 == 2) {
           startX = getWidth() / 2 - mChildSize;
           startY = mChildSize * bulge + mChildSize / 2;
       } else if ((i + 1) % 3 == 0) {
           startX = getWidth() / 2;
           startY = mChildSize * bulge + mChildSize / 2;
           bulge++;
       }
       childView.layout(startX, startY, startX + mChildSize, startY + mChildSize);
   }

如果對于自定義 ViewGroup 流程有什么疑問的童鞋,請查看我自定義系類前面的幾篇博客。

菱形(BlockView )

BlockView 類比較簡單,我這里就直接貼出代碼,有什么疑問的請留言,會第一時間給你回復。

package com.github.blockdemo.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
 * Created by Administrator on 10/17 0017.
 */
public class BlockView extends View {

    private Context mContext;

    private Paint mPaint;

    private Paint mTextPaint;

    private Path mPath;

    private String mText;

    private Paint.FontMetrics mMetrics;

    private OnClickListener mOnClickListener;

    private boolean mClickEnable = true;

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

    public BlockView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BlockView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(Color.parseColor("#3F51B5"));

        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setStyle(Paint.Style.FILL);
        mTextPaint.setColor(Color.parseColor("#FFFFFF"));

        mPath = new Path();

        mText = "8";
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPath.reset();

        mPath.moveTo(getWidth() / 2, 0);
        mPath.lineTo(0, getHeight() / 2);
        mPath.lineTo(getWidth() / 2, getHeight());
        mPath.lineTo(getWidth(), getHeight() / 2);

        mPath.close();
        canvas.drawPath(mPath, mPaint);

        mTextPaint.setTextSize(getWidth() / 4);
        mMetrics = mTextPaint.getFontMetrics();
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        canvas.drawText(mText, getWidth() / 2, getHeight() / 2 +
                (mMetrics.bottom - mMetrics.top) / 2 - mMetrics.bottom, mTextPaint);

    }

    public void setPaintColor(int... colors) {
        if (colors != null)
            mPaint.setColor(colors[0]);
    }

    public void setText(String text) {
        mText = text;
    }

    public int dip2px(float dpValue) {
        final float scale = mContext.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                float x = event.getX();
                float y = event.getY();
                int centerX = getWidth() / 2;
                int centerY = getHeight() / 2;
                   //注意下這里以菱形的內切圓來處理點擊事件,如果你有什么好的方案請留言
                if ((centerX - x) * (centerX - x) + (centerY - y) * (centerY - y) <= getWidth() * getWidth() / 8) {
                    if (mOnClickListener != null && mClickEnable) {
                        mOnClickListener.BlockOnClickListener(mText);
                        mClickEnable = false;
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                mClickEnable = true;
                break;
            default:
                break;
        }
        return true;
    }

    public interface OnClickListener {
        void BlockOnClickListener(String text);
    }

    public void setBlockOnClickListener(OnClickListener onClickListener) {
        this.mOnClickListener = onClickListener;
    }
}

 

 

 

 本文由用戶 licqi 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!