『Android基礎入門』自定義view控制元件畫一個五彩斑斕的黑圈圈
theme: fancy highlight: androidstudio
我正在參與掘金創作者訓練營第5期,點選瞭解活動詳情
👨🎓作者簡介:一位喜歡寫作,計科專業大二菜鳥
🏡個人主頁:starry陸離
🕒首發日期:2022年8月3日星期三
🌌上期文章:『Android基礎入門』dataBinding的簡單使用
📚訂閱專欄:『Android基礎入門』
如果文章有幫到你的話記得點贊👍+收藏💗支援一下哦
『Android基礎入門』自定義view控制元件畫一個五彩斑斕的黑圈圈
1.前言
今天我們來實現一個好玩的小功能,自定義一個view控制元件在隨機位置畫一個隨機顏色的圓圈,並實現點選事件監聽移除與清空功能
首先來康康效果吧
2.xml佈局設計
首先我們建立一個空專案,簡單的來實現這個xml檔案佈局
佈局主要分為兩個部分,上大半部分是我們用來畫圖的view佈局,我們的圖案最終會渲染到這個部分。
下半部分是一個巢狀的約束佈局,佈局中放置三個button,分別來實現在view佈局中新增一個圓,移除一個圓以及清空所有的圓
activity_main.xml原始碼
```xml
4.自定義view畫布
我們需要自定義一個畫布類
用自定義的CircleView繼承View父類替換View控制元件
View類中有onDraw()
方法,我們通過重寫此方式實現在view佈局上作畫
有了畫布自然要有畫布,建立一支紅色的畫筆,呼叫畫圓的方法drawCircle()
java
//有了畫布canvas,我們還需要一支畫筆
Paint paint=new Paint();
paint.setColor(Color.RED);
java
public class CircleView extends View {
public CircleView(Context context) {
super(context);
}
public CircleView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
//設定畫布的背景色為黑色
this.setBackgroundColor(Color.BLACK);
//有了畫布canvas,我們還需要一支畫筆
Paint paint=new Paint();
paint.setColor(Color.RED);
//用畫筆paint畫一個圓心座標為(400,500)的半徑為100的圓
canvas.drawCircle(400,500,100,paint);
}
}
為什麼執行載入,畫布上就出現了一個紅色的圓呢?因為在載入CircleView的時候會自動執行onDraw()
方法且預設只執行一次;
為了不讓一執行就出現圓,而是通過我們的點選事件出現圓,我們定義一個布林值變數,在MainActivity中通過按鈕的點選事件新增圓
5.實現畫多個圓
畫多個圓就需要將圓儲存在一個列表List或者是陣列中,然後再到onDraw()
方法中依次渲染這些圓到view佈局上
除此之外,我們生成的圓物件的顏色和位置應該是隨機的,而且圓的位置不應該超出畫布的範圍
因此我們建立多個類,分別來實現這些功能
5.1圓物件
java
static class Circle{
float x,y;
final float RADIUS=120;
final int color;
public Circle(float x, float y,int color) {
this.x = x;
this.y = y;
this.color=color;
}
}
5.2隨機顏色
Color.argb(200,r,g,b)
是返回是一個代表顏色的整數值,argb()
裡的四個引數就是a(透明度),r,g,b(紅,綠,藍三原色)的值
java
public static int getRandomColor(){
Random random=new Random();
int r=random.nextInt(256);
int g=random.nextInt(256);
int b=random.nextInt(256);
return Color.argb(200,r,g,b);
}
5.3隨機位置新增一個圓
java
/*
* 新增一個圓
* */
public void addCircle(){
//在view的寬高範圍內,隨機生成一個座標
float x=(float) (Math.random()*viewWidth);
float y=(float) (Math.random()*viewHeight);
//約束條件,不讓圓超出畫布範圍
//寬度約束
if(x<120f){
x=120f;
}else if(x>viewWidth-120f){
x=viewWidth-120f;
}
//高度約束
if(y<120f){
y=120f;
}else if(y>viewHeight-120f){
y=viewHeight-120f;
}
//將圓新增到列表中
CircleView.Circle circle=new CircleView.Circle(x,y,CircleView.getRandomColor());
CircleView.circleList.add(circle);
}
5.4移除與清空
java
public void removeCircle(){
if(!circleList.isEmpty()){
circleList.remove(circleList.size()-1);
}
}
public void clearCircle(){
circleList.clear();
}
5.5在Activity中監聽點選事件
注意最後一行程式碼:在子執行緒中重新執行一次 circleView.postInvalidate();
因為我們之前說過自定義的的CircleView類中的onDraw()
方法在載入這個控制元件時只會執行一次,而我們每一次點選都要重寫渲染view,所以需要在每一次使用者點選操作後在子執行緒中重新渲染view控制元件,這樣才能讓使用者看到實時的效果
java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private CircleView circleView;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.addBtn).setOnClickListener(this);
findViewById(R.id.moveBtn).setOnClickListener(this);
findViewById(R.id.clearBtn).setOnClickListener(this);
circleView=findViewById(R.id.view);
}
@Override
public void onClick(View view) {
if(view.getId()==R.id.addBtn){
Toast.makeText(MainActivity.this,"add",Toast.LENGTH_SHORT).show();
circleView.addCircle();
}else if(view.getId()==R.id.clearBtn){
Toast.makeText(MainActivity.this,"clear",Toast.LENGTH_SHORT).show();
circleView.clearCircle();
}else if(view.getId()==R.id.moveBtn){
Toast.makeText(MainActivity.this,"Move",Toast.LENGTH_SHORT).show();
circleView.removeCircle();
}
//在子執行緒中重新執行一次
circleView.postInvalidate();
}
}
6.效果展示
7.完整程式碼
7.1MainActivity
java
package com.hnucm.ad0301;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private CircleView circleView;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.addBtn).setOnClickListener(this);
findViewById(R.id.moveBtn).setOnClickListener(this);
findViewById(R.id.clearBtn).setOnClickListener(this);
circleView=findViewById(R.id.view);
}
@Override
public void onClick(View view) {
if(view.getId()==R.id.addBtn){
Toast.makeText(MainActivity.this,"add",Toast.LENGTH_SHORT).show();
circleView.addCircle();
}else if(view.getId()==R.id.clearBtn){
Toast.makeText(MainActivity.this,"clear",Toast.LENGTH_SHORT).show();
circleView.clearCircle();
}else if(view.getId()==R.id.moveBtn){
Toast.makeText(MainActivity.this,"Move",Toast.LENGTH_SHORT).show();
circleView.removeCircle();
}
//在子執行緒中重新執行一次
circleView.postInvalidate();
}
}
7.2CircleView
java
package com.hnucm.ad0301;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class CircleView extends View {
public static List<Circle>circleList=new ArrayList<>();
public float viewWidth;
public float viewHeight;
public CircleView(Context context) {
super(context);
}
public CircleView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
//獲取畫布的寬高
viewWidth=canvas.getWidth();
viewHeight=canvas.getHeight();
//設定畫布的背景色為黑色
this.setBackgroundColor(Color.BLACK);
//有了畫布canvas,我們還需要一支畫筆
Paint paint=new Paint();
//遍歷列表畫圓
for(int i=0;i<circleList.size();++i){
Circle circle=circleList.get(i);
paint.setColor(circle.color);
canvas.drawCircle(circle.x,circle.y,circle.RADIUS,paint);
}
}
/*
* 新增一個圓
* */
public void addCircle(){
//在view的寬高範圍內,隨機生成一個座標
float x=(float) (Math.random()*viewWidth);
float y=(float) (Math.random()*viewHeight);
//約束條件,不讓圓超出畫布範圍
//寬度約束
if(x<120f){
x=120f;
}else if(x>viewWidth-120f){
x=viewWidth-120f;
}
//高度約束
if(y<120f){
y=120f;
}else if(y>viewHeight-120f){
y=viewHeight-120f;
}
//將圓新增到列表中
CircleView.Circle circle=new CircleView.Circle(x,y,CircleView.getRandomColor());
CircleView.circleList.add(circle);
}
public void removeCircle(){
if(!circleList.isEmpty()){
circleList.remove(circleList.size()-1);
}
}
public void clearCircle(){
circleList.clear();
}
static class Circle{
float x,y;
final float RADIUS=120;
final int color;
public Circle(float x, float y,int color) {
this.x = x;
this.y = y;
this.color=color;
}
}
public static int getRandomColor(){
Random random=new Random();
int r=random.nextInt(256);
int g=random.nextInt(256);
int b=random.nextInt(256);
return Color.argb(200,r,g,b);
}
}
7.3activity_main.xml
```xml