自定义气泡背景

来源:互联网 发布:采购数据报告体现 编辑:程序博客网 时间:2024/04/30 03:18

这个就是一个自定义View,其实自定义View也就是重写那么几个方法,onDraw(),onMeasure()。还是直接来看代码吧,注视里面都有的

public class CircleView extends View {      private int circleSum;//圆的数量      private int circleRadio;//圆的半径      private int circleColor;//圆的颜色      private int backColor;//背景颜色      private Paint backPaint;//背景画笔      private Paint circlePaint;//圆的画笔      private Circle[] circles;      private int[] direction = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};      private Random random;      private float width;      private float height;      private int[] location = new int[2];      private MyThread mMyThread;      private boolean running = true;      public CircleView(Context context) {          super(context);          backPaint = new Paint();          init();      }      public CircleView(Context context, AttributeSet attrs) {          super(context, attrs);          TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CircleView);          circleSum = ta.getInteger(R.styleable.CircleView_circleSum, 10);          circleColor = ta.getColor(R.styleable.CircleView_circleColor, Color.parseColor("#7756ffff"));          backColor = ta.getColor(R.styleable.CircleView_backColor, Color.parseColor("#21efef"));          circleRadio = ta.getInteger(R.styleable.CircleView_circleRadio, 60);          ta.recycle();          init();      }      /**      * 初始化画笔      */      private void init() {          backPaint = new Paint();          backPaint.setColor(backColor);          circlePaint = new Paint();          circlePaint.setColor(circleColor);      }      /**      * 比onDraw先执行      * <p/>      * 一个MeasureSpec封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求。      * 一个MeasureSpec由大小和模式组成      * 它有三种模式:UNSPECIFIED(未指定),父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小;      * EXACTLY(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小;      * AT_MOST(至多),子元素至多达到指定大小的值。      * <p/>      *   它常用的三个函数:      * 1.static int getMode(int measureSpec):根据提供的测量值(格式)提取模式(上述三个模式之一)      * 2.static int getSize(int measureSpec):根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小)      * 3.static int makeMeasureSpec(int size,int mode):根据提供的大小值和模式创建一个测量值(格式)      */      @Override      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {          super.onMeasure(widthMeasureSpec, heightMeasureSpec);          //获取控件宽度          width = getMeasuredWidth();          //获取控件高度          height = getMeasuredHeight();          //获取控件相对于父控件的位置坐标          this.getLocationInWindow(location);          //初始化圆          initCircle();      }      /**      * 初始化圆      */      private void initCircle() {          circles = new Circle[circleSum];          random = new Random();          for (int i = 0; i < circleSum; i++) {              int d = random.nextInt(direction.length);              int x = random.nextInt((int) width);              int y = random.nextInt((int) height);              circles[i] = new Circle(x, y, d);          }      }      @Override      protected void onDraw(Canvas canvas) {          //绘制背景          canvas.drawRect(0, 0, location[0] + width, location[1] + height, backPaint);          //遍历绘制每一个圆          for (Circle c : circles) {              canvas.drawCircle(c.getX(), c.getY(), circleRadio, circlePaint);          }          if (mMyThread == null) {              mMyThread = new MyThread();              mMyThread.start();          }      }      /**      * 不在窗口显示的时候停止线程      */      @Override      protected void onDetachedFromWindow() {          running = false;          super.onDetachedFromWindow();      }      class MyThread extends Thread {          @Override          public void run() {              while (running) {                  for (int i = 0; i < circleSum; i++) {                      Circle c = circles[i];                      changeDirection(c);                      //超出边界后重置方向                      if (c.getX() > width || c.getX() < 0 || c.getY() > height || c.getY() < 0) {                          int d;                          while (true) {                              d = random.nextInt(direction.length);                              int lastD = c.getDirection();                              if ((lastD == 0 || lastD == 4 || lastD == 6 || lastD == 8 || lastD == 10) && (d == 0 || d == 4 || d == 6 || d == 8 || d == 10)) {//上                                  continue;                              } else if ((lastD == 1 || lastD == 5 || lastD == 7 || lastD == 9) && (d == 1 || d == 5 || d == 7 || d == 9)) {//下                                  continue;                              } else if ((lastD == 2 || lastD == 4 || lastD == 5 || lastD == 8 || lastD == 9) && (d == 2 || d == 4 || d == 5 || d == 8 || d == 9)) {//左                                  continue;                              } else if ((lastD == 3 || lastD == 6 || lastD == 7 || lastD == 10) && (d == 3 || d == 6 || d == 7 || d == 10)) {//右                                  continue;                              }                              break;                          }                          circles[i].setDirection(d);                      }                  }                  try {                      Thread.sleep(30);                  } catch (InterruptedException e) {                      e.printStackTrace();                  }                  postInvalidate();              }          }          private void changeDirection(Circle c) {              float dx = 0.3f;              switch (c.getDirection()) {                  case 0://上                      c.setY(c.getY() - dx);                      break;                  case 1://下                      c.setY(c.getY() + dx);                      break;                  case 2://左                      c.setX(c.getX() - dx);                      break;                  case 3://右                      c.setX(c.getX() + dx);                      break;                  case 4://左上                      c.setX(c.getX() - dx);                      c.setY(c.getY() - dx);                      break;                  case 5://左下                      c.setX(c.getX() - dx);                      c.setY(c.getY() + dx);                      break;                  case 6://右上                      c.setX(c.getX() + dx);                      c.setY(c.getY() - dx);                      break;                  case 7://右下                      c.setX(c.getX() + dx);                      c.setY(c.getY() + dx);                      break;                  case 8://左上                      c.setX(c.getX() - dx);                      c.setY(c.getY() - dx * 2);                      break;                  case 9://左下                      c.setX(c.getX() - dx * 2);                      c.setY(c.getY() + dx);                      break;                  case 10://右上                      c.setX(c.getX() + dx);                      c.setY(c.getY() - dx * 2);                      break;              }          }      }      class Circle {          private float x;          private float y;          private int direction;          public Circle(float x, float y, int d) {              this.x = x;              this.y = y;              this.direction = d;          }          public float getX() {              return x;          }          public void setX(float x) {              this.x = x;          }          public void setY(float y) {              this.y = y;          }          public float getY() {              return y;          }          public void setDirection(int direction) {              this.direction = direction;          }          public int getDirection() {              return direction;          }      }  }  

来看看在xml文件中怎么使用

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"      android:layout_width="match_parent"      android:layout_height="match_parent">      <com.tianzhao.myapplication.CircleView          xmlns:cv="http://schemas.android.com/apk/res/com.tianzhao.myapplication"  //自己的命名空间          android:layout_width="fill_parent"          android:layout_height="200dp"          cv:circleSum="10"  //圆的数量          cv:circleColor="#7756ffff"  //圆的颜色          cv:backColor="#21efef"/> //背景颜色      <RelativeLayout          android:layout_width="fill_parent"          android:layout_height="200dp">          <ImageView              android:id="@+id/iv"              android:layout_width="80dp"              android:layout_height="80dp"              android:layout_centerInParent="true"              android:background="@drawable/user" />          <TextView              android:layout_width="wrap_content"              android:layout_height="wrap_content"              android:layout_below="@id/iv"              android:layout_centerHorizontal="true"              android:layout_marginTop="5dp"              android:text="登录"              android:textSize="20dp" />      </RelativeLayout>      <LinearLayout          android:layout_width="wrap_content"          android:layout_height="40dp"          android:layout_centerHorizontal="true"          android:layout_marginTop="230dp">          <TextView              android:layout_width="wrap_content"              android:layout_height="wrap_content"              android:gravity="center_vertical"              android:text="用户名:"              android:textSize="20dp" />          <EditText              android:layout_width="200dp"              android:layout_height="wrap_content"              android:layout_marginLeft="5dp"              android:gravity="center_vertical" />      </LinearLayout>      <LinearLayout          android:layout_width="wrap_content"          android:layout_height="40dp"          android:layout_centerHorizontal="true"          android:layout_marginTop="280dp">          <TextView              android:layout_width="wrap_content"              android:layout_height="wrap_content"              android:gravity="center_vertical"              android:text="密    码:"              android:textSize="20dp" />          <EditText              android:layout_width="200dp"              android:layout_height="wrap_content"              android:layout_marginLeft="5dp"              android:gravity="center_vertical" />      </LinearLayout>  </RelativeLayout>

这里会涉及到一个attr.xml

<?xml version="1.0" encoding="utf-8"?>  <resources>      <declare-styleable name="CircleView">          <attr name="circleSum" format="integer"></attr>          <attr name="circleColor" format="color"></attr>          <attr name="backColor" format="color"></attr>          <attr name="circleRadio" format="integer"></attr>      </declare-styleable>  </resources>  

这里写图片描述