自定义View和自定义属性的基本步骤:自定义View:
1.创建一个自定义View类:首先,你需要创建一个继承自View或其子类(如ImageView、Button等)的Java类。这个类将代表你的自定义View,并负责绘制和处理用户交互。
2.重写onDraw方法:在自定义View类中,你通常会重写onDraw方法来定义如何绘制你的View。在onDraw方法中,你可以使用Canvas对象进行绘制,绘制各种形状、文本、图像等。
3.处理用户交互:如果需要处理用户交互,你可以重写相应的方法,如onTouchEvent,以响应触摸事件。
项目中有遇到自定义wifi。
直接上代码
kotlin:
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.net.wifi.WifiManager
import android.util.AttributeSet
import android.view.View
import kotlin.math.min
import kotlin.math.sqrt
class WiFiStateView @JvmOverloads constructor(
context: Context?,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) :
View(context, attrs, defStyleAttr) {
private var wifi_state = 1
private var height = 0
private var width = 0
private var paint: Paint? = null
private var startAngle = 0
private var sweepAngle = 0
private var wifiHeight = 0
private var padding_bottom = 0
private var bottom_x = 0
private var bottom_y = 0
enum class Style {
RECT, ROUND
}
private var style = Style.ROUND
init {
init()
}
private fun init() {
paint = Paint(Paint.ANTI_ALIAS_FLAG)
paint!!.color = Color.BLACK
paint!!.isAntiAlias = true
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
//获取宽的测量模式
val heightSize = MeasureSpec.getSize(heightMeasureSpec) //测量值
height = resolveSize(heightSize, heightMeasureSpec)
val widthSize = MeasureSpec.getSize(widthMeasureSpec) //测量值
width = resolveSize(widthSize, widthMeasureSpec)
val calc_wifi_height = (width / (sqrt(2.0))).toInt()
wifiHeight = min(calc_wifi_height.toDouble(), height.toDouble()).toInt()
padding_bottom = (height - wifiHeight) / 2
bottom_x = width / 2
bottom_y = height - padding_bottom
setMeasuredDimension(width, height)
}
fun setWifi_state(level: Int) {
this.wifi_state = WifiManager.calculateSignalLevel(level, 5)
postInvalidate()
}
fun setStyle(style: Style) {
this.style = style
postInvalidate()
}
@SuppressLint("DrawAllocation")
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val signalRadius = wifiHeight / 4
val paint_width = signalRadius / 2
paint!!.strokeWidth = paint_width.toFloat()
if (style == Style.RECT) {
paint!!.strokeCap = Paint.Cap.BUTT
startAngle = -135
sweepAngle = 90
} else {
paint!!.strokeCap = Paint.Cap.ROUND
startAngle = -130
sweepAngle = 80
}
for (i in 1..4) {
val radius = (signalRadius * i).toFloat()
if (i <= wifi_state) {
paint!!.color = Color.parseColor("#4b4b4b")
} else {
paint!!.color = Color.parseColor("#c9c9c9")
}
var rectf: RectF
if (i == 1) {
paint!!.style = Paint.Style.FILL
if (style == Style.RECT) {
rectf = RectF(
bottom_x - radius,
bottom_y - radius,
bottom_x + radius,
bottom_y + radius
)
canvas.drawArc(
rectf, startAngle.toFloat(), sweepAngle.toFloat(), true,
paint!!
)
} else {
canvas.drawCircle(
bottom_x.toFloat(),
(bottom_y - paint_width).toFloat(),
paint_width.toFloat(),
paint!!
)
}
} else {
paint!!.style = Paint.Style.STROKE
rectf = RectF(
bottom_x - radius + paint_width / 2,
bottom_y - radius + paint_width / 2,
bottom_x + radius - paint_width / 2,
bottom_y + radius - paint_width / 2
)
canvas.drawArc(rectf, startAngle.toFloat(), sweepAngle.toFloat(), false, paint!!)
}
}
}
}
java:
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.net.wifi.WifiManager;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
public class WiFiStateView extends View {
private int wifi_state = 1;
private int height,width;
private Paint paint;
private int startAngle,sweepAngle;
private int wifiHeight = 0;
private int padding_bottom ;
private int bottom_x,bottom_y;
enum Style{
RECT,ROUND
}
private Style style = Style.ROUND;
public WiFiStateView(Context context) {
this(context,null);
}
public WiFiStateView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public WiFiStateView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//获取宽的测量模式
int heightSize = MeasureSpec.getSize(heightMeasureSpec);//测量值
height = resolveSize(heightSize, heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);//测量值
width = resolveSize(widthSize, widthMeasureSpec);
int calc_wifi_height = (int) (width / (Math.sqrt(2)));
wifiHeight = Math.min(calc_wifi_height,height);
padding_bottom = (height - wifiHeight)/2;
bottom_x = width /2;
bottom_y = height - padding_bottom;
setMeasuredDimension(width, height);
}
public void setWifi_state(int level) {
this.wifi_state = WifiManager.calculateSignalLevel(level,5);
postInvalidate();
}
public void setStyle(Style style) {
this.style = style;
postInvalidate();
}
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int signalRadius = wifiHeight / 4;
int paint_width = signalRadius/2;
paint.setStrokeWidth(paint_width);
if(style == Style.RECT){
paint.setStrokeCap(Paint.Cap.BUTT);
startAngle = -135;
sweepAngle = 90;
}else {
paint.setStrokeCap(Paint.Cap.ROUND);
startAngle = -130;
sweepAngle = 80;
}
for(int i = 1;i <= 4; i ++){
float radius = signalRadius * i;
if(i<=wifi_state){
paint.setColor(Color.parseColor("#4b4b4b"));
}else {
paint.setColor(Color.parseColor("#c9c9c9"));
}
RectF rectf;
if(i == 1){
paint.setStyle(Paint.Style.FILL);
if(style == Style.RECT){
rectf = new RectF(bottom_x - radius ,bottom_y - radius,bottom_x + radius,bottom_y + radius);
canvas.drawArc(rectf,startAngle,sweepAngle,true , paint);
}else {
canvas.drawCircle(bottom_x,bottom_y -paint_width,paint_width,paint );
}
}else {
paint.setStyle(Paint.Style.STROKE);
rectf = new RectF(bottom_x - radius + paint_width/2,bottom_y - radius + paint_width/2,bottom_x + radius - paint_width/2,bottom_y + radius - paint_width/2);
canvas.drawArc(rectf,startAngle,sweepAngle,false , paint);
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".MainActivity">
<wendu.dsbridge.DWebView
android:id="@+id/dwebview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<Button
android:layout_gravity="bottom"
android:id="@+id/btn_sendJS"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="这是原生控件,发送数据给JS"/>
<com.example.dsbridge_demo.WiFiStateView
android:layout_width="25dp"
android:layout_height="25dp"
/>
</FrameLayout>
===============
这里涉及到 Android 自定义view 自定义属性
自定义属性:
1.定义自定义属性:在res/values/attrs.xml文件中定义自定义属性。这是一个XML文件,你可以在其中指定自定义属性的名称、类型、默认值等。例如:
<resources>
<declare-styleable name="MyCustomView">
<attr name="customText" format="string" />
<attr name="customColor" format="color" />
</declare-styleable>
</resources>
2.在XML布局文件中使用自定义属性:在XML布局文件中,可以使用你定义的自定义属性来配置自定义View。例如:
<com.example.myapp.MyCustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:customText="Hello, Custom View!"
app:customColor="#FF0000" />
3.在自定义View中获取自定义属性:在自定义View类中,可以通过obtainStyledAttributes方法获取自定义属性的值,并在View的初始化中使用这些值。例如:
TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView);
String customText = attributes.getString(R.styleable.MyCustomView_customText);
int customColor = attributes.getColor(R.styleable.MyCustomView_customColor, Color.BLACK);
attributes.recycle();
// 使用获取到的属性值进行初始化
这样,你就可以通过自定义属性来配置你的自定义View,并在XML布局文件中以可视化方式使用它。这使得你的自定义View更加灵活和易于重用。
标签:自定义,--,wifi,private,paint,int,import,android From: https://blog.csdn.net/wulong756273/article/details/141037730