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

licqi 8年前
   <p>老规矩,先来看看类似过年放的鞭炮的效果图:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/cc69adbc38e524c8efeb36cc5c4901d5.png"></p>    <p style="text-align: center;">block</p>    <p>学习博客也是学习一种变通的思想,能够举一反三,才能掌握真正的精髓。</p>    <p>这里留下一个小小的挑战:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/9507b725df21922555398771998c5330.png"></p>    <p style="text-align: center;">block</p>    <p>怎么获取菱形区域的点击事件?欢迎留言,欢迎讨论,谢谢。</p>    <p>我临时的处理方法是以菱形的内切圆来处理点击事情的。</p>    <h3>鞭炮布局(BlockFrameLayout)</h3>    <p>分析效果图,可以看出魔方布局是由一块块小的菱形按照某种规律组合而成的,我们这里以繁化简,先来看看一块小的菱形:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/162526dc18159088d85a7ab00ace83b2.png"></p>    <p style="text-align: center;">block</p>    <p>接着看看三块菱形组成的图案:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/772f0440516000ad3488c573afaceed9.png"></p>    <p style="text-align: center;">block</p>    <p>看看最后的效果图:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/54f1e0899b453f8cf1b4dad53b49d41d.png"></p>    <p style="text-align: center;">block</p>    <p>是不是已经发现规律了啊?对的,以三块菱形为一组,从上往下就组成了最终的图案。</p>    <p>核心思想:分析前三块菱形和后三块菱形的坐标变化。</p>    <p>相信你已经找到了:</p>    <pre>  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++;      }</pre>    <p>那么 onLayout 方法:</p>    <pre>  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);     }</pre>    <p>如果对于自定义 ViewGroup 流程有什么疑问的童鞋,请查看我自定义系类前面的几篇博客。</p>    <h3>菱形(BlockView )</h3>    <p>BlockView 类比较简单,我这里就直接贴出代码,有什么疑问的请留言,会第一时间给你回复。</p>    <pre>  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;      }  }</pre>    <p> </p>    <p> </p>    <p> </p>