Android UI设计系列之自定义TextView属性实现带下划线的文本框(4)
作者:llew2011 发布时间:2022-08-11 11:03:29
在Android开发过程中,如果Android系统自带的属性不能满足我们日常开发的需求,那么就需要我们给系统控件添加额外的属性了。假如有个需求是实现带下划线的文本显示(下划线),如果不使用自定义属性的话实现起来也不太难(起码我认为的实现方式是有许多种的),今天就讲解一下如何使用自定义属性来实现上述带下划线的文本框吧。还好Android中自定义属性不是很复杂,也可以归纳为三步走吧。
老规矩,还是先贴出工程目录吧:
一、添加属性文件
在values文件夹中新建attrs.xml文件,在文件中新建属性文件,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 自定义属性开始 -->
<declare-styleable name="BorderTextView">
<attr name="layout_borders" format="boolean"></attr>
<attr name="layout_borderLeft" format="boolean"></attr>
<attr name="layout_borderTop" format="boolean"></attr>
<attr name="layout_borderRight" format="boolean"></attr>
<attr name="layout_borderBottom" format="boolean"></attr>
</declare-styleable>
<!-- 自定义属性结束 -->
</resources>
其中需要说明的是,自定义属性文件的根节点页是<resources>,在根节点内创建你所需要的属性值,自定义属性的节点是以<declare-styleable>开始的,它表示的是个属性集可以包含众多属性,其中name="BorderTextView"是属性集名。接着在<declare-styleable>中定义我们需要的以<attr>为节点的属性,attr表示属性的意思name表示当前属性的名称,format表示的是属性值的类型,例如我们当前定义的属性类型为boolean类型,也就是说当前定义的属性取值只能为boolean类型的,format可以表示的的类型有好多种,最常见的如:string,boolean,integer,dimension,reference等这,里就不再详细讲解了,如果谁有疑问,可以自己动手问问度娘,她知道的比我多,呵呵
二、使用自定义属性
在attrs.xml文件中定义好了属性,就可以在布局文件中使用了,接下来看看在布局文件中如何使用自定义属 * ,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:greendroid="http://schemas.android.com/apk/res/com.llew.e"
android:orientation="vertical"
android:layout_width="fill_parent"
android:background="#ffffff"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dip"
android:text="@string/hello"
android:textColor="#000000" />
<com.llew.e.view.wedgit.BorderTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="左侧带有边框"
android:layout_margin="10dip"
greendroid:layout_borderLeft="true"
android:textSize="20sp"
android:textColor="#aabbcc">
</com.llew.e.view.wedgit.BorderTextView>
<com.llew.e.view.wedgit.BorderTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="顶部带有边框"
android:layout_margin="10dip"
greendroid:layout_borderTop="true"
android:textSize="20sp"
android:textColor="#bbccaa">
</com.llew.e.view.wedgit.BorderTextView>
<com.llew.e.view.wedgit.BorderTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="右侧带有边框"
android:layout_margin="10dip"
greendroid:layout_borderRight="true"
android:textSize="20sp"
android:textColor="#ccaabb">
</com.llew.e.view.wedgit.BorderTextView>
<com.llew.e.view.wedgit.BorderTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="底部带有边框"
android:layout_margin="10dip"
greendroid:layout_borderBottom="true"
android:textSize="20sp"
android:textColor="#abcabc">
</com.llew.e.view.wedgit.BorderTextView>
<com.llew.e.view.wedgit.BorderTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="四周带有边框"
android:layout_margin="10dip"
greendroid:layout_borders="true"
android:textSize="20sp"
android:textColor="#cbacba">
</com.llew.e.view.wedgit.BorderTextView>
</LinearLayout>
使用自定义控件也很简单就是包名+自定义控件名,为了使用我们自定义的属性,必须在布局文件的根节点中加上xmlns:greendroid="http://schemas.android.com/apk/res/com.llew.e"这句话,其中xmlns:greendroid表示的是命名空间名称,greendroid只是个名字是我们使用自定义属性的前缀,可以随便取值(只要不是android就行了),com.llew.e是在manifest中的package的对应值,使用自定义属性就想代码中的那样:greendroid:layout_borderLeft="true",(*^__^*) 嘻嘻……,是不是可简单?
三、根据自定义属性值做相应操作
完成自定义属性文件之后,我们就来为控件添加自定义的属性了,自定义控件我认为最简单的实现就是使用继承,在继承的基础上进行扩充来实现我们所要的功能,所以为了实现带边框的文本组件,我就直接继承了TextView组件,在它的基础上进行扩充了,代码如下:
public class BorderTextView extends TextView {
/**
* 四周是否带有边框【true:四周带有边框】【false:四周不带边框】
*/
boolean borders = false;
/**
* 左边是否带有边框【true:左侧带有边框】【false:左侧不带边框】
*/
boolean borderLeft = false;
/**
* 顶部是否带有边框【true:顶部带有边框】【false:底部不带边框】
*/
boolean borderTop = false;
/**
* 右侧是否带有边框【true:右侧带有边框】【false:右侧不带边框】
*/
boolean borderRight = false;
/**
* 底部是否带有边框【true:底部带有边框】【false:底部不带边框】
*/
boolean borderBottom = false;
/**
* 边框颜色
*/
String textColor = "#ff000000";
public BorderTextView(Context context) {
this(context, null);
}
public BorderTextView(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.textViewStyle);
}
public BorderTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// 获取自定义属性集
TypedArray typedArray = context.obtainStyledAttributes(attrs,
R.styleable.BorderTextView);
// 是否设置全部边框,默认为false
borders = typedArray.getBoolean(
R.styleable.BorderTextView_layout_borders, false);
// 是否设置左侧边框,默认为false
borderLeft = typedArray.getBoolean(
R.styleable.BorderTextView_layout_borderLeft, false);
// 是否设置顶部边框,默认为false
borderTop = typedArray.getBoolean(
R.styleable.BorderTextView_layout_borderTop, false);
// 是否设置右侧边框,默认为false
borderRight = typedArray.getBoolean(
R.styleable.BorderTextView_layout_borderRight, false);
// 是否设置底部边框,默认为false
borderBottom = typedArray.getBoolean(
R.styleable.BorderTextView_layout_borderBottom, false);
// 获取文本颜色值,用来画边框的,便于和文本颜色匹配
textColor = attrs.getAttributeValue(
"http://schemas.android.com/apk/res/android", "textColor");
typedArray.recycle();
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
// 创建画笔
Paint paint = new Paint();
// 获取该画笔颜色
int color = paint.getColor();
// 设置画笔颜色
paint.setColor(Color.parseColor(textColor));
// 如果borders为true,表示左上右下都有边框
if (borders) {
canvas.drawLine(0, 0, 0, this.getHeight() - 1, paint);
canvas.drawLine(0, 0, this.getWidth() - 1, 0, paint);
canvas.drawLine(this.getWidth() - 1, 0, this.getWidth() - 1,
this.getHeight() - 1, paint);
canvas.drawLine(0, this.getHeight() - 1, this.getWidth() - 1,
this.getHeight() - 1, paint);
} else {
if (borderLeft) {
// 画左边框线
canvas.drawLine(0, 0, 0, this.getHeight() - 1, paint);
}
if (borderTop) {
// 画顶部边框线
canvas.drawLine(0, 0, this.getWidth() - 1, 0, paint);
}
if (borderRight) {
// 画右侧边框线
canvas.drawLine(this.getWidth() - 1, 0, this.getWidth() - 1,
this.getHeight() - 1, paint);
}
if (borderBottom) {
// 画底部边框线
canvas.drawLine(0, this.getHeight() - 1, this.getWidth() - 1,
this.getHeight() - 1, paint);
}
}
// 设置画笔颜色归位
paint.setColor(color);
}
}
其实给BorderTextView添加边框也是很简单,原理就是其draw方法中绘画出边框罢,我们都知道每一个View控件在屏幕上显示出来大致可以归纳为三大步骤,首先调用View控件的onMesure方法,其次调用View控件的onLayout方法,再次调用View控件的onDraw方法,所以我们只需要在draw方法中绘制出边框就行了,绘制边框的步骤很简单,代码注释也很详细,就不再详细讲解了
最后运行一下程序来看一下效果图吧,呵呵


猜你喜欢
- 1. 简介直到4g时代,流量依然是宝贵的东西。而移动网络传输中,最占流量的一种载体:图片,成为了我们移动开发者不得不关注的一个问题。我们关注
- 23种设计模式第十二篇:java模版方法模式定义:定义一个操作中算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重定义
- 在上一章中,有个问题可能大家都没有注意,Acitivity 在使用startActivityForResult后,可以给另一个的Acitiv
- 第一步:在d盘新建android文件夹,在此文件夹中再建三个子文件夹,Android Studio 、 Android_SDK、Androi
- 安卓使用SmsManager实现发送短信,供大家参考,具体内容如下关键代码实现package com.example.sms; import
- 本文研究的主要是Java中后台线程的相关问题,具体介绍如下。以前从来没有听说过,java中有后台线程这种东西。一般来说,JVM(JAVA虚拟
- 在Android中要让一个程序的界面始终保持一个方向,不随手机方向转动而变化的办法: 只要在AndroidManifest.xml里面配置一
- 首先在枚举类中 定义state 和定义的抽象方法。public enum JavaPlatformState { // 定义st
- JTable的排序是一个让人头疼的问题,Sun没有为排序这个最常用的功能提供类。但是近日翻看Sun官方java的tutorial,却发现其在
- 起因unity程序build到pc上,拿到其他人的机器上结果有些功能不正常,看log里面大概是Fallback handler could
- 1.@GrpcServise的作用和优势在没有使用@GrpcServise注解编写服务端时,我们通常需要自定义Server以及端口,包括st
- 1.由json字符串转换成Map对象如json字符串:{"contend":[{"bid":&quo
- mongodb的数据插入速度是其一个亮点,同样的10000条数据,插入的速度要比Mysql和sqlserver都要快,当然这也是要看使用者怎
- 本文不再对值类型进行讨论,主要讨论一下引用类型。如要看内存值类型的朋友可以看一下前一篇C#之CLR内存原理初探。C#引用类型具体分析如下:先
- 1) async / await使用 async / await 模式,可以在执行代码块操作的时候不会阻塞 UI 或者当前的线程。即使该操作
- 概述线上项目发布一般有以下几种方案:机发布蓝绿部署滚动部署灰度发布停机发布 这种发布一般在夜里或者进行大版本升级的时候发布,因为需要停机,所
- 一、什么是 LRU 算法就是一种缓存淘汰策略。计算机的缓存容量有限,如果缓存满了就要删除一些内容,给新内容腾位置。但问题是,删除哪些内容呢?
- 一、DataTable转XML#region DataTableToXml /// &
- Canvas,在英语中,这个单词的意思是帆布。在Android中,则把Canvas当做画布,只要我们借助设置好的画笔(Paint类)就可以在
- MVP(Model-View-Presenter) 是总所周知MVC模式的一个演变,他们的主要目的都是划分模块职责,降低模块耦合,易测试,提