自定义View

匿名 (未验证) 提交于 2019-12-03 00:30:01

View下面有

  • ImageView
    ImageButton
    QuickContactBadge
    AppCompatImageView

  • TextView
    EditText
    Button
    RadioButton
    ToggleButton
    CheckBox
    Switch
    TextClock
    Chronometer
    RowHeaderView

  • ViewGruop
    LinearLayout
    ReativeLayout
    ViewPager
    AbsoiuteLayout
    FrameLayout
    GridLayout
  • TextureView
  • ViewStub
  • TabLtem
  • Spce

一.新建一个类继承View

package com.example.myapplication.view;  import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.os.Build; import android.support.annotation.Nullable; import android.support.annotation.RequiresApi; import android.util.AttributeSet; import android.view.View;  import com.example.myapplication.R;  /**  * Created by lyj on 2018/6/15.  */  public class MyView extends View {      public MyView(Context context) {         super(context);     }      public MyView(Context context, @Nullable AttributeSet attrs) {         super(context, attrs);     }      public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {         super(context, attrs, defStyleAttr);     }      @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)     public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {         super(context, attrs, defStyleAttr, defStyleRes);     }      @Override     protected void onDraw(Canvas canvas) {         super.onDraw(canvas); } 

二.在onDraw方法里面定义画笔,画东西

Paint paint = new Paint();

设置颜色

paint.setColor(Color.RED);

抗锯齿

paint.setAntiAlias(true);

画一个圆,把表盘背景图设置进去

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.watch);         RectF rectF = new RectF(getWidth() / 4+25, getHeight() / 2 - getWidth() / 4+25, getWidth() / 4 * 3-25, getHeight() / 2 + getHeight() / 8);         canvas.drawBitmap(bitmap, null, rectF, paint);

画时针

canvas.save();         canvas.rotate(hours * 30 + minute * 30 / 60, getWidth() / 2, getHeight() / 2);         paint.setColor(Color.BLACK);         paint.setStrokeWidth(5);         canvas.drawLine(getWidth() / 2, getHeight() / 2, getWidth() / 2, getHeight() / 2 - getHeight() / 8 + 55, paint);         canvas.restore();

画分针

canvas.save();         canvas.rotate(minute * 6, getWidth() / 2, getHeight() / 2);         paint.setColor(Color.BLACK);         paint.setStrokeWidth(3);         canvas.drawLine(getWidth() / 2, getHeight() / 2, getWidth() / 2 + 12, getHeight() / 2 - getHeight() / 8 + 40, paint);         canvas.restore();

画秒针

canvas.save();         canvas.rotate(second * 6, getWidth() / 2, getHeight() / 2);         paint.setColor(Color.BLACK);         paint.setStrokeWidth(1);         canvas.drawLine(getWidth() / 2, getHeight() / 2, getWidth() / 2 + 15, getHeight() / 2 - getHeight() / 8 + 20, paint);         canvas.restore();

画刻度

 for (int i = 0; i <= 60; i++) {             canvas.save();             canvas.rotate(6 * i, getWidth() / 2, getHeight() / 2);             paint.setStrokeWidth(2);             if (i % 5 == 0) {                 paint.setStrokeWidth(8);                 canvas.drawLine(getWidth() / 2, getHeight() / 2 - getHeight() / 8 + 20, getWidth() / 2, getHeight() / 2 - getWidth() / 4 + 35, paint);             } else {                 paint.setStrokeWidth(4);                 canvas.drawLine(getWidth() / 2, getHeight() / 2 - getHeight() / 8 + 20, getWidth() / 2, getHeight() / 2 - getWidth() / 4+40, paint);              }             canvas.restore();         }

每画完一个图形都需要canvas.save();保存一下
三.实现指针动起来
重新写一个方法

public void refresh(int h, int m, int s) {         this.hours = h;         this.minute = m;         this.second = s;         invalidate();//再次触发onDraw方法     }

这是新建的类的完整代码

package com.example.myapplication.view;  import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.os.Build; import android.support.annotation.Nullable; import android.support.annotation.RequiresApi; import android.util.AttributeSet; import android.view.View;  import com.example.myapplication.R;  /**  * Created by lyj on 2018/6/15.  */  public class MyView extends View {     private int hours = 20;     private int minute = 20;     private int second = 0;      public MyView(Context context) {         super(context);     }      public MyView(Context context, @Nullable AttributeSet attrs) {         super(context, attrs);     }      public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {         super(context, attrs, defStyleAttr);     }      @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)     public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {         super(context, attrs, defStyleAttr, defStyleRes);     }      @Override     protected void onDraw(Canvas canvas) {         super.onDraw(canvas);         Paint paint = new Paint();         //设置颜色         paint.setColor(Color.RED);         //抗锯齿         paint.setAntiAlias(true);         /*         前两个参数:圆心的位置         第三参数:半径          */         //canvas.drawCircle(getWidth()/2,getHeight()/2,getWidth()/4,paint);          Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.watch);         RectF rectF = new RectF(getWidth() / 4+25, getHeight() / 2 - getWidth() / 4+25, getWidth() / 4 * 3-25, getHeight() / 2 + getHeight() / 8);         canvas.drawBitmap(bitmap, null, rectF, paint);          //画直线(时针)         canvas.save();         canvas.rotate(hours * 30 + minute * 30 / 60, getWidth() / 2, getHeight() / 2);         paint.setColor(Color.BLACK);         paint.setStrokeWidth(5);         canvas.drawLine(getWidth() / 2, getHeight() / 2, getWidth() / 2, getHeight() / 2 - getHeight() / 8 + 55, paint);         canvas.restore();         //画直线(分针)         canvas.save();         canvas.rotate(minute * 6, getWidth() / 2, getHeight() / 2);         paint.setColor(Color.BLACK);         paint.setStrokeWidth(3);         canvas.drawLine(getWidth() / 2, getHeight() / 2, getWidth() / 2 + 12, getHeight() / 2 - getHeight() / 8 + 40, paint);         canvas.restore();          //画直线(秒针)         canvas.save();         canvas.rotate(second * 6, getWidth() / 2, getHeight() / 2);         paint.setColor(Color.BLACK);         paint.setStrokeWidth(1);         canvas.drawLine(getWidth() / 2, getHeight() / 2, getWidth() / 2 + 15, getHeight() / 2 - getHeight() / 8 + 20, paint);         canvas.restore();          for (int i = 0; i <= 60; i++) {             canvas.save();             canvas.rotate(6 * i, getWidth() / 2, getHeight() / 2);             paint.setStrokeWidth(2);             if (i % 5 == 0) {                 paint.setStrokeWidth(8);                 canvas.drawLine(getWidth() / 2, getHeight() / 2 - getHeight() / 8 + 20, getWidth() / 2, getHeight() / 2 - getWidth() / 4 + 35, paint);             } else {                 paint.setStrokeWidth(4);                 canvas.drawLine(getWidth() / 2, getHeight() / 2 - getHeight() / 8 + 20, getWidth() / 2, getHeight() / 2 - getWidth() / 4+40, paint);              }             canvas.restore();         }      }      public void refresh(int h, int m, int s) {         this.hours = h;         this.minute = m;         this.second = s;         invalidate();//再次触发onDraw方法     } } 

activity类
得到当前时间

 Calendar calendar = Calendar.getInstance();         hours = calendar.get(Calendar.HOUR_OF_DAY);         minute = calendar.get(Calendar.MINUTE);         second = calendar.get(Calendar.SECOND);

主线程不能做耗时操作,所以开启一个线程让指针动起来

new Thread(new Runnable() {             @Override             public void run() {                 while (true) {                     second++;                     if (second == 60) {                         second = 0;                         minute++;                     }                     try {                         Message message = handler.obtainMessage();                         message.what = hours;                         message.arg1 = minute;                         message.arg2 = second;                         handler.sendMessage(message);                         Thread.sleep(1000);                     } catch (InterruptedException e) {                         e.printStackTrace();                     }                 }             }         }).start();

activity类的完整代码

package com.example.myapplication.view;  import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle;  import com.example.myapplication.R;  import java.util.Calendar;  public class MyViewActivity extends AppCompatActivity {     private MyView myView;     private int hours;     private int minute;     private int second;     private Handler handler = new Handler() {         @Override         public void handleMessage(Message msg) {             super.handleMessage(msg);             myView.refresh(msg.what, msg.arg1, msg.arg2);         }     };      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_my_view);          myView = findViewById(R.id.my_view);          Calendar calendar = Calendar.getInstance();         hours = calendar.get(Calendar.HOUR_OF_DAY);         minute = calendar.get(Calendar.MINUTE);         second = calendar.get(Calendar.SECOND);          myView.refresh(hours, minute, second);          new Thread(new Runnable() {             @Override             public void run() {                 while (true) {                     second++;                     if (second == 60) {                         second = 0;                         minute++;                     }                     try {                         Message message = handler.obtainMessage();                         message.what = hours;                         message.arg1 = minute;                         message.arg2 = second;                         handler.sendMessage(message);                         Thread.sleep(1000);                     } catch (InterruptedException e) {                         e.printStackTrace();                     }                 }             }         }).start();     } } 

布局文件需要引入自己的控件

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:orientation="vertical"     tools:context="com.example.myapplication.view.MyViewActivity">     <com.example.myapplication.view.MyView         android:layout_width="match_parent"         android:layout_height="match_parent"         android:id="@+id/my_view"/> </LinearLayout> 

效果图:

新建一个类继承ImageView

package com.example.myapplication.view;          import android.annotation.SuppressLint;         import android.content.Context;         import android.graphics.Bitmap;         import android.graphics.BitmapShader;         import android.graphics.Canvas;         import android.graphics.Matrix;         import android.graphics.Paint;         import android.graphics.Shader;         import android.graphics.drawable.BitmapDrawable;         import android.graphics.drawable.Drawable;         import android.util.AttributeSet;         import android.widget.ImageView;  /**  * Created by lyj on 2018/6/15.  */  @SuppressLint("AppCompatCustomView") public class MyImageView extends ImageView{     private Paint mPaint; //画笔      private int mRadius; //圆形图片的半径      private float mScale; //图片的缩放比例     public MyImageView(Context context) {         super(context);     }      public MyImageView(Context context, AttributeSet attrs) {         super(context, attrs);     }      public MyImageView(Context context, AttributeSet attrs, int defStyleAttr) {         super(context, attrs, defStyleAttr);     }      @Override     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {         super.onMeasure(widthMeasureSpec, heightMeasureSpec);         int size = Math.min(getMeasuredWidth(), getMeasuredHeight());         mRadius = size / 2;          setMeasuredDimension(size, size);     }      @Override     protected void onDraw(Canvas canvas) {         mPaint = new Paint();         Bitmap bitmap = drawableToBitmap(getDrawable());          //初始化BitmapShader,传入bitmap对象         BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);          //计算缩放比例         mScale = (mRadius * 2.0f) / Math.min(bitmap.getHeight(), bitmap.getWidth());          Matrix matrix = new Matrix();         matrix.setScale(mScale, mScale);         bitmapShader.setLocalMatrix(matrix);           mPaint.setShader(bitmapShader);          //画圆形,指定好中心点坐标、半径、画笔         canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);     }      //写一个drawble转BitMap的方法     private Bitmap drawableToBitmap(Drawable drawable) {         if (drawable instanceof BitmapDrawable) {             BitmapDrawable bd = (BitmapDrawable) drawable;             return bd.getBitmap();         }         int w = drawable.getIntrinsicWidth();         int h = drawable.getIntrinsicHeight();         Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);         Canvas canvas = new Canvas(bitmap);         drawable.setBounds(0, 0, w, h);         drawable.draw(canvas);         return bitmap;      } } 

布局文件引入自定义图片控件:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout_height="match_parent"     tools:context="com.example.myapplication.view.MyImageActivity">     <com.example.myapplication.view.MyImageView         android:layout_width="match_parent"         android:layout_height="match_parent"         android:src="@mipmap/a"         android:id="@+id/img_myView"/>  </LinearLayout> 

效果图:

文章来源: 自定义View
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!