自定義label組件

自定義label組件

支持邊框繪制
支持shape背景(按指定圓角裁剪,矩形,圓角矩,圓形),支持指定角圓角
支持自定義陰影(顏色,偏移,深度)
邊框顏色支持狀態選擇器

預覽

在這里插入圖片描述

核心繪制輔助類
public class LabelHelper {private final Paint paint;private Paint shadowPaint;private final float[] radiusList = new float[8];// 矩陣四角圓角 兩個一組分別為一角的x軸半徑y軸半徑  四組分別為 上左 上右  下右  下左private final Rect rect;private final Path path;private final RectF rectF;private float strokeWidth;private ColorStateList strokeColor;private boolean hasRadius;//是否有圓角private int shadowColor;//是否有陰影private float shadowRadius;private float shadowDx;private float shadowDy;private Float contentInsetLeft = null;private Float contentInsetRight = null;private int defStrokeColor;LabelHelper(View view, Context context, AttributeSet attrs) {this(view, context, attrs, Color.TRANSPARENT);}LabelHelper(View view, Context context, AttributeSet attrs, @ColorInt int defStrokeColor) {this.defStrokeColor = defStrokeColor;TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.LabelView);// 圓角float radius = array.getDimension(R.styleable.LabelView_android_radius, 0);float topLeftRadius = array.getDimension(R.styleable.LabelView_android_topLeftRadius, radius);float topRightRadius = array.getDimension(R.styleable.LabelView_android_topRightRadius, radius);float bottomLeftRadius = array.getDimension(R.styleable.LabelView_android_bottomLeftRadius, radius);float bottomRightRadius = array.getDimension(R.styleable.LabelView_android_bottomRightRadius, radius);// 陰影int shadowColor = array.getColor(R.styleable.LabelView_android_shadowColor, Color.TRANSPARENT);float shadowRadius = array.getFloat(R.styleable.LabelView_android_shadowRadius, 0.0f);float shadowDx = array.getFloat(R.styleable.LabelView_android_shadowDx, 0.0f);float shadowDy = array.getFloat(R.styleable.LabelView_android_shadowDy, 0.0f);if (array.hasValue(R.styleable.LabelView_android_contentInsetLeft)) {contentInsetLeft = array.getDimension(R.styleable.LabelView_android_contentInsetLeft, 0);}if (array.hasValue(R.styleable.LabelView_android_contentInsetRight)) {contentInsetRight = array.getDimension(R.styleable.LabelView_android_contentInsetRight, 0);}int anInt = array.getInt(R.styleable.LabelView_fillType, 1);// 邊框strokeWidth = array.getDimension(R.styleable.LabelView_borderWidth, 0);try {strokeColor = array.getColorStateList(R.styleable.LabelView_borderColor);} catch (Exception e) {e.printStackTrace();}if (strokeColor == null) {strokeColor = ColorStateList.valueOf(array.getColor(R.styleable.LabelView_borderColor, this.defStrokeColor));}view.setSelected(array.getBoolean(R.styleable.LabelView_selected, false));array.recycle();paint = new Paint();paint.setAntiAlias(true);paint.setStyle(getPaintStyle(anInt));paint.setStrokeWidth(strokeWidth);rectF = new RectF();rect = new Rect();path = new Path();setRadiusPx(view, topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius);view.setLayerType(LAYER_TYPE_HARDWARE, null);setShadow(shadowColor, shadowRadius, shadowDx, shadowDy);}// 設置陰影畫筆private void setShadow(int shadowColor, float shadowRadius, float shadowDx, float shadowDy) {if (shadowPaint == null) {shadowPaint = new Paint();shadowPaint.setAntiAlias(true);shadowPaint.setStyle(Paint.Style.FILL);}this.shadowRadius = Math.max(shadowRadius, 0);this.shadowDx = shadowDx;this.shadowDy = shadowDy;this.shadowColor = shadowColor;shadowPaint.setColor(shadowColor);shadowPaint.setShadowLayer(this.shadowRadius, this.shadowDx, this.shadowDy, shadowColor);}private Paint.Style getPaintStyle(int type) {return switch (type) {case 0 -> Paint.Style.FILL;case 2 -> Paint.Style.FILL_AND_STROKE;default -> Paint.Style.STROKE;};}void setStrokeWidth(int dp) {strokeWidth = SizeUtils.dp2px(dp);paint.setStrokeWidth(strokeWidth);}void setStrokeColor(@ColorInt int boundColor) {this.strokeColor = ColorStateList.valueOf(boundColor);}void setFillType(Paint.Style style) {paint.setStyle(style);}void setRadiusPx(View view, float topLeft, float topRight, float bottomRight, float bottomLeft) {radiusList[0] = topLeft;radiusList[1] = topLeft;radiusList[2] = topRight;radiusList[3] = topRight;radiusList[4] = bottomRight;radiusList[5] = bottomRight;radiusList[6] = bottomLeft;radiusList[7] = bottomLeft;hasRadius = topLeft > 0 || topRight > 0 || bottomRight > 0 || bottomLeft > 0;float offsetPaddingL = 0;float offsetPaddingR = 0;float offsetPaddingT = 0;float offsetPaddingB = 0;boolean autoInsetLeft = contentInsetLeft == null;boolean autoInsetRight = contentInsetRight == null;if (hasRadius) {if (autoInsetLeft) {offsetPaddingL = Math.max(topLeft, bottomLeft) / 2f;} else if (contentInsetLeft != 0) {offsetPaddingL = contentInsetLeft;}if (autoInsetRight) {offsetPaddingR = Math.max(topRight, bottomRight) / 2f;} else if (contentInsetRight != 0) {offsetPaddingR = contentInsetRight;}}if (isDrawBorder(view)) {offsetPaddingL = Math.max(offsetPaddingL, strokeWidth);offsetPaddingR = Math.max(offsetPaddingL, strokeWidth);offsetPaddingT = strokeWidth;offsetPaddingB = strokeWidth;}view.setPadding((int) Math.max(view.getPaddingLeft(), offsetPaddingL),(int) Math.max(view.getPaddingTop(), offsetPaddingT),(int) Math.max(view.getPaddingRight(), offsetPaddingR),(int) Math.max(view.getPaddingBottom(), offsetPaddingB));setStroke();view.invalidate();}private void setStroke() {if (hasRadius) {paint.setStrokeCap(Paint.Cap.ROUND);paint.setStrokeJoin(Paint.Join.ROUND);} else {paint.setStrokeCap(Paint.Cap.BUTT);paint.setStrokeJoin(Paint.Join.MITER);}}void draw(Canvas canvas, View view) {boolean drawBorder = isDrawBorder(view);boolean isDrawShadow = isDrawShadow();if (hasRadius || drawBorder || isDrawShadow) {view.getDrawingRect(rect);path.reset();rectF.set(rect);path.addRoundRect(rectF, radiusList, Path.Direction.CW);path.close();if (isDrawShadow) {// 繪制陰影canvas.drawPath(path, shadowPaint);path.reset();rectF.left += Math.max(shadowRadius - shadowDx, 0);rectF.right -= Math.max(shadowRadius + shadowDx, 0);rectF.top += Math.max(shadowRadius - shadowDy, 0);rectF.bottom -= Math.max(shadowRadius + shadowDy, 0);path.addRoundRect(rectF, radiusList, Path.Direction.CW);path.close();}if (hasRadius && !(drawBorder && paint.getStyle() != Paint.Style.STROKE)) {// 形狀裁剪canvas.clipPath(path);}}}void onDraw(Canvas canvas, View view) {if (isDrawBorder(view)) {Paint.Style style = paint.getStyle();if (style != Paint.Style.STROKE) {canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);}paint.setColor(getBoundColor(view));canvas.save();if (style != Paint.Style.FILL) {path.reset();rectF.left += (strokeWidth / 2f - 0.5f);rectF.top += (strokeWidth / 2f - 0.5f);rectF.right -= strokeWidth / 2f;rectF.bottom -= strokeWidth / 2f;path.addRoundRect(rectF, radiusList, Path.Direction.CW);path.close();}// 邊框繪制canvas.drawPath(path, paint);canvas.restore();}}Paint getPaint() {return paint;}public Rect getRect() {return rect;}public Path getPath() {return path;}public RectF getRectF() {return rectF;}public float getStrokeWidth() {return strokeWidth;}public boolean isHasRadius() {return hasRadius;}private int getBoundColor(View view) {int color = this.defStrokeColor;if (strokeColor != null) {if (strokeColor.isStateful()) {color = strokeColor.getColorForState(view.getDrawableState(), strokeColor.getDefaultColor());} else {color = strokeColor.getDefaultColor();}}return color;}private boolean isDrawBorder(View view) {return strokeWidth > 0 && getBoundColor(view) != Color.TRANSPARENT;}private boolean isDrawShadow() {return shadowPaint != null && shadowColor != Color.TRANSPARENT && shadowRadius > 0;}
}
自定義控件示例
public class LabelFrameLayout extends FrameLayout {private LabelHelper helper;public LabelFrameLayout(Context context) {this(context, null);}public LabelFrameLayout(Context context, AttributeSet attrs) {this(context, attrs, 0);}public LabelFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);setWillNotDraw(false);helper = new LabelHelper(this, context, attrs);}public void setFillType(Paint.Style style) {if (helper != null && helper.getPaint() != null) {helper.setFillType(style);invalidate();}}public void setStrokeColor(@ColorInt int boundColor) {if (helper != null) {helper.setStrokeColor(boundColor);invalidate();}}public void setStrokeColorRes(@ColorRes int colorRes) {if (helper != null) {helper.setStrokeColor(getResources().getColor(colorRes));invalidate();}}public void setStrokeWidth(int dp) {if (helper != null && helper.getPaint() != null) {helper.setStrokeWidth(dp);invalidate();}}public void setRadius(int radiusDp) {setRadiusPx(SizeUtils.dp2px(radiusDp));}public void setRadiusPx(float radius) {setRadiusPx(radius, radius, radius, radius);}public void setRadius(float topLeft, float topRight, float bottomRight, float bottomLeft) {setRadiusPx(SizeUtils.dp2px(topLeft), SizeUtils.dp2px(topRight), SizeUtils.dp2px(bottomRight), SizeUtils.dp2px(bottomLeft));}public void setRadiusPx(float topLeft, float topRight, float bottomRight, float bottomLeft) {if (helper != null) {helper.setRadiusPx(this, topLeft, topRight, bottomRight, bottomLeft);}}@Overridepublic void invalidate() {if (isLaidOut()) {super.invalidate();}}@Overridepublic void draw(Canvas canvas) {if (helper != null) {helper.draw(canvas, this);}super.draw(canvas);}@Overrideprotected void onDraw(Canvas canvas) {if (helper != null) {helper.onDraw(canvas, this);}super.onDraw(canvas);}
}
xml使用示例
<包名.LabelFrameLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="100dp"android:layout_marginBottom="10dp"android:background="@color/subColorGray"app:borderColor="@color/red"app:borderWidth="1dp"android:radius="20dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="阿迪斯發斯蒂芬" /></包名.LabelFrameLayout>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/163739.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/163739.shtml
英文地址,請注明出處:http://en.pswp.cn/news/163739.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【無標題】學習HTML

由于工作需求&#xff0c;學習了一些html的相關知識&#xff0c;最終應用到打印功能上使用。 HTML是指超文本標記語言&#xff08;HyperText Markup Language&#xff09;。它是一種用于創建和呈現互聯網上頁面的標準標記語言。HTML是Web開發的基礎&#xff0c;是構建網頁和應…

宅家追劇神器推薦,高亮輕薄投影儀極米Z7X帶你開啟追劇新體驗

周末假期怎么玩&#xff1f;相信有不少朋友已經準備好了出游計劃&#xff0c;當然也有很多小伙伴想趁周末在家追追劇、看看電影、玩玩游戲放松一下。那么&#xff0c;今天筆者就給大家帶來了一款假期娛樂神器——極米Z7X&#xff0c;無論是出游還是宅家追劇&#xff0c;極米Z7X…

深度解析 Docker Registry:構建安全高效的私有鏡像倉庫

文章目錄 什么是Docker Registry&#xff1f;Docker Hub vs. 私有RegistryDocker Hub&#xff1a;私有Registry&#xff1a; 如何構建私有Docker Registry&#xff1f;步驟一&#xff1a;安裝Docker Registry步驟二&#xff1a;配置TLS&#xff08;可選&#xff09;步驟三&…

SVD 最小二乘法解 親測ok!

線性最小二乘問題 m個方程求解n個未知數&#xff0c;有三種情況&#xff1a; mn且A為非奇異&#xff0c;則有唯一解&#xff0c;xA.inverse()*bm>n&#xff0c;約束的個數大于未知數的個數&#xff0c;稱為超定問題&#xff08;overdetermined&#xff09;m<n&#xff0…

OpenSSL SSL_read: Connection was reset, errno 10054

包含下面兩種錯誤 一、unable to access https://github.com/username/xxx.git/: OpenSSL SSL_read: Connection was reset, errno 10054二、unable to access https://github.com/username/xxx.git/: Failed to connect to github.com port 443 after 21171 ms: Timed out不同…

精通Nginx(17)-安全管控之防暴露、限制訪問、防DDos攻擊、防爬蟲、防非法引用

安全是每個系統都需要考慮的關鍵因素,Nginx在這方面提供了豐富的功能,使我們可以就實際情形做很精細調整。這些功能包括防信息暴露、客戶端訪問限制、通訊加密、防DDos攻擊、防爬蟲、防非法引用及防非法域名請求等。 目錄 防信息暴露 關閉版本號 關閉目錄列表 客戶端訪問…

18.oracle的過程和函數

oracle11g的過程和函數 一、過程&#xff08;Procedure&#xff09;1、子程序2、過程的相關語法 二、函數&#xff08;Function&#xff09;1、函數的概念2、函數的創建3、 案例 在Oracle數據庫中&#xff0c;過程和函數都是用來封裝一系列SQL語句和邏輯操作的數據庫對象&#…

ChatGPT重磅升級!集簡云支持GPT4 Turbo Vision, GPT4 Turbo, Dall.E 3,Whisper等最新模型

在11月7日凌晨&#xff0c;OpenAI全球開發者大會宣布了 GPT-4的一次大升級&#xff0c;推出了 GPT-4 Turbo號稱為迄今為止最強的大模型。 此次GPT-4的更新和升級在多個方面顯示出強大的優勢和潛力。為了讓集簡云用戶能快速體驗新模型的能力&#xff0c;我們第一時間整理了大會發…

VR直播如何打破視角壁壘,提升觀看體驗?

隨著數字技術的不斷發展&#xff0c;直播行業也發生了新的變革&#xff0c;VR直播也成為了直播行業中新的趨勢&#xff0c;那么VR直播是如何打破視角壁壘&#xff0c;提升觀看體驗的呢&#xff1f; 杭州亞運會那幾天&#xff0c;多項比賽熱火朝天&#xff0c;無論你是參賽隊伍的…

【double check 讀寫鎖】

使用double check 讀寫鎖 讀多寫少場景 記錄下 //來源 jdbc 中的查詢連接信息 //public abstract class ConnectionUrl implements DatabaseUrlContainer public static ConnectionUrl getConnectionUrlInstance(String connString, Properties info) {if (connString null…

上市公司常見的印章問題契約鎖如何幫您解決?

您知道公司印章的管理和使用是否存在問題&#xff1f;公司內部該如何通過印章問題自查&#xff0c;及時進行風險防治&#xff1f; 印章是上市公司權利的象征&#xff0c;開展“印章管理審查”確保管理和使用合規&#xff0c;也是上市公司內控和監管的一項重要內容。如果存在不合…

S71200通過PROFINET協議和島電數字控制器通訊

項目要求 西門子S71200PLC需要通過PROFINET協議和島電數字控制器&#xff08;型號&#xff1a;SRS13A&#xff09;通訊&#xff0c;讀取溫度的測量值PV和設定值SV。 項目實施 采用NET90-PN-MBT&#xff08;以下簡稱“網關”&#xff09;&#xff0c;它是一款將Modbus TCP/RT…

點擊按鈕,按鈕的文字變為倒計時,的小技巧(適用于獲取驗證碼)

看效果圖&#xff1a; 代碼 <a-buttonclick"getSms":disabled"myState.smsSendFlag"v-text"(!myState.smsSendFlag && 獲取驗證碼) || ${myState.time} s" ></a-button>data(){return {myState: {smsSendFlag: false,tim…

AI數字人的源碼獨立部署就是你創業的起點

隨著AI繪畫、chat gpt的爆火&#xff0c;AI時代開始初露矛頭的話&#xff0c;那么今年&#xff0c;或許真正是我們全面進入AI時代的元年&#xff0c;一個更新的更智能化的時代正以勢不可擋的姿態奔涌而來&#xff01; 晚一步&#xff0c;失去先機&#xff1b;晚一步&#xff0c…

Notepad-- ubuntu下載安裝

Notepad-- ubuntu下載安裝 下載 Gitee鏈接&#xff1a; https://gitee.com/cxasm/notepad– 安裝 sudo apt install *.deb運行 /opt/apps/com.hmja.notepad/files/Notepad--出錯 需要安裝qt5 sudo apt-get install qt5-default

網絡安全入門教程(非常詳細)從零基礎入門到精通

網絡安全是一個龐大而不斷發展的領域&#xff0c;它包含多個專業領域&#xff0c;如網絡防御、網絡攻擊、數據加密等。介紹網絡安全的基本概念、技術和工具&#xff0c;逐步深入&#xff0c;幫助您成為一名合格的網絡安全從業人員。 一、網絡安全基礎知識 1.計算機基礎知識 了解…

微服務簡介

1、什么是微服務 微服務&#xff08;或稱微服務架構&#xff09;是一種云原生架構方法&#xff0c;在單個應用中包含眾多松散耦合且可單獨部署的小型組件或服務。 這些服務通常擁有自己的技術棧&#xff0c;包括數據庫和數據管理模型&#xff1b;通過一個REST API、事件流和消息…

linux上的通用拍照程序

最近因為工作需要&#xff0c;在ubuntu上開發了一個拍照程序。 為了找到合適的功能研究了好幾種實現方式&#xff0c;在這里記錄一下。 目錄 太長不看版 探索過程 v4l2 QT opencv4.2 打開攝像頭 為什么不直接打開第一個視頻節點 獲取所有分辨率 切換攝像頭 太長不看…

七要素微氣象儀氣象數據監測助手

WX-WQX7 隨著科技的發展&#xff0c;氣象預測的準確性已成為人們日常生活的重要參考。而七要素微氣象儀&#xff0c;作為新型的氣象探測設備&#xff0c;以其精細化的數據測量和解析能力&#xff0c;正在改變我們的天氣預測方式。 一、產品介紹 七要素微氣象儀是一款集成了溫…