当前位置: 首页 > news >正文

自定义View-- wifi强度

自定义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.sqrtclass WiFiStateView @JvmOverloads constructor(context: Context?,attrs: AttributeSet? = null,defStyleAttr: Int = 0
) :View(context, attrs, defStyleAttr) {private var wifi_state = 1private var height = 0private var width = 0private var paint: Paint? = nullprivate var startAngle = 0private var sweepAngle = 0private var wifiHeight = 0private var padding_bottom = 0private var bottom_x = 0private var bottom_y = 0enum class Style {RECT, ROUND}private var style = Style.ROUNDinit {init()}private fun init() {paint = Paint(Paint.ANTI_ALIAS_FLAG)paint!!.color = Color.BLACKpaint!!.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) / 2bottom_x = width / 2bottom_y = height - padding_bottomsetMeasuredDimension(width, height)}fun setWifi_state(level: Int) {this.wifi_state = WifiManager.calculateSignalLevel(level, 5)postInvalidate()}fun setStyle(style: Style) {this.style = stylepostInvalidate()}@SuppressLint("DrawAllocation")override fun onDraw(canvas: Canvas) {super.onDraw(canvas)val signalRadius = wifiHeight / 4val paint_width = signalRadius / 2paint!!.strokeWidth = paint_width.toFloat()if (style == Style.RECT) {paint!!.strokeCap = Paint.Cap.BUTTstartAngle = -135sweepAngle = 90} else {paint!!.strokeCap = Paint.Cap.ROUNDstartAngle = -130sweepAngle = 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: RectFif (i == 1) {paint!!.style = Paint.Style.FILLif (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.STROKErectf = 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);}@Overrideprotected 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")@Overrideprotected 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.DWebViewandroid:id="@+id/dwebview"android:layout_width="match_parent"android:layout_height="match_parent"/><Buttonandroid: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.WiFiStateViewandroid: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.MyCustomViewandroid: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更加灵活和易于重用。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 从0开始搭建vue + flask 旅游景点数据分析系统( 六):搭建后端flask框架
  • Win32注册表操作
  • Rust 所有权
  • 大数据-Big Data(一):概述与基础
  • Tracecat:开源 SOAR
  • Transformer 模型中的 QKV 机制是如何运作的
  • 区块链平台的图灵完备性
  • 探秘C# LINQ元素运算:原理阐释与实践指南
  • day 22线程间通信
  • Java参数传递
  • 深度学习-----------数值稳定性
  • docker部署jenkins和jenkins的基本使用
  • 【SpringCloud】SpringCloudNetflix笔记
  • 重塑购车体验,实时云渲染赋能东风日产探路云看车新体验
  • Date类型的字段序列化成JSON字符串
  • 【JavaScript】通过闭包创建具有私有属性的实例对象
  • Android框架之Volley
  • Consul Config 使用Git做版本控制的实现
  • es6要点
  • HTTP中GET与POST的区别 99%的错误认识
  • Java到底能干嘛?
  • Java方法详解
  • Js基础——数据类型之Null和Undefined
  • Js基础知识(一) - 变量
  • Just for fun——迅速写完快速排序
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • php ci框架整合银盛支付
  • Zsh 开发指南(第十四篇 文件读写)
  • 关于for循环的简单归纳
  • 免费小说阅读小程序
  • 前端_面试
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • -- 数据结构 顺序表 --Java
  • 微服务入门【系列视频课程】
  • 微信小程序:实现悬浮返回和分享按钮
  • 温故知新之javascript面向对象
  • 详解NodeJs流之一
  • 运行时添加log4j2的appender
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • 1.Ext JS 建立web开发工程
  • #{} 和 ${}区别
  • #QT(QCharts绘制曲线)
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (13)Hive调优——动态分区导致的小文件问题
  • (2)从源码角度聊聊Jetpack Navigator的工作流程
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (七)Appdesigner-初步入门及常用组件的使用方法说明
  • (转)Oracle存储过程编写经验和优化措施
  • *算法训练(leetcode)第三十九天 | 115. 不同的子序列、583. 两个字符串的删除操作、72. 编辑距离
  • .Net core 6.0 升8.0
  • .net反编译工具
  • .NET周刊【7月第4期 2024-07-28】