自定义控件
实现一个自定义控件
实现一个自定义控件可以通过以下步骤:
-
创建一个Java类,并继承已有的View或ViewGroup。
-
自定义视图需要覆盖一些方法,例如 onDraw()、onMeasure()和 onLayout(),以便控制视图在屏幕中所占的位置和呈现方式。
-
定义自定义属性,也就是在 attrs.xml 文件中声明 View 属性,这样在引用该自定义控件的布局文件中就可以使用你自己定义的属性。
-
在自定义控件构造方法中,加载自定义属性。可以利用 TypedArray 对象来获取自定义属性值,然后对自定义控件进行初始化。
下面是一个简单的自定义 TextView 控制示例,实现了在文本周围添加外边框线的功能:
public class LinedTextView extends AppCompatTextView {
private Paint mPaint = new Paint();
public LinedTextView(Context context) {
super(context);
init();
}
public LinedTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public LinedTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
// 设置画笔属性
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(2);
}
@Override
protected void onDraw(Canvas canvas) {
// 获取文本行数
final int lineCount = getLineCount();
// 获取每行的高度
final int lineHeight = getLineHeight();
// 获取 TextView 的宽度
final int width = getWidth();
// 获取布局参数
LayoutParams layoutParams = getLayoutParams();
// 计算文本最大宽度
int maxWidth = width - getPaddingLeft() - getPaddingRight();
// 遍历每一行文本,在文本周围绘制矩形
for (int i = 0; i < lineCount; i++) {
int lineBaseline = getLineBounds(i, null);
int lineStart = getLayout().getLineStart(i);
int lineEnd = getLayout().getLineEnd(i);
float textWidth = StaticLayout.getDesiredWidth(getText(), lineStart, lineEnd, getPaint());
if (maxWidth < textWidth) {
// 如果文本宽度超过最大宽度,则把文字折叠为多行
String text = getText().toString();
try {
int index = TextUtils.indexOf(text, ' ', lineStart + maxWidth);
if (index != -1 && index < lineEnd)
lineEnd = index;
} catch (Exception e) {
e.printStackTrace();
}
}
// 绘制背景矩形
RectF rect = new RectF(getPaddingLeft(),
lineBaseline + getPaddingTop(),
width - getPaddingRight(),
lineBaseline + lineHeight + getPaddingTop());
canvas.drawRect(rect, mPaint);
// 绘制文字
canvas.drawText(getText(), lineStart, lineEnd,
getLayout().getLineLeft(i) + getPaddingLeft(),
lineBaseline + getPaddingTop(),
getPaint());
}
}
}
通过自定义 LinedTextView 类来实现,继承自 Android 提供的 TextView 控件,并重写该控件的 onDraw() 方法,在文本周围绘制一个指定宽度和颜色的矩形。此处自定义属性就是绘制的矩形的相关属性,例如画笔颜色、画笔粗细等。
通过XML实现自定义视图,您需要完成以下步骤:
- 创建一个新的类,并在其中编写自己的自定义视图代码
public class MyCustomView extends View {
public MyCustomView(Context context) {
super(context);
// Custom code here
}
public MyCustomView(Context context, AttributeSet attrs) {
super(context, attrs);
// Custom code here
}
public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// Custom code here
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Custom drawing code here
}
}
- 在res/layout目录下创建XML文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.MyCustomView
android:id="@+id/my_custom_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:custom_attribute_name="custom_value"/>
</RelativeLayout>
-
在标签里使用您上面定义的自定义视图,在您的XML中添加您自定义视图的命名空间,如下例所示。使用
xmlns:custom
申明你自己的属性。 -
在自定义视图实现类中实现自定义属性的处理
public class MyCustomView extends View {
private String mCustomAttrVal;
public MyCustomView(Context context) {
super(context);
}
public MyCustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyle, 0);
mCustomAttrVal = a.getString(R.styleable.MyCustomView_custom_attribute_name);
a.recycle();
}
// other view methods and variables ...
}
其中的R.styleable.MyCustomView
是在不同的values/attrs.xml文件中定义的。
在这些文件中可以定义自己的属性如name、color值以及后续用于标识在代码中的一些字段等。
- 使用自定义视图add到main活动
MyCustomView myCustomView = new MyCustomView(this);
parentLayout.addView(myCustomView);
以上就是使用XML库构造自己的自定义组件元素的基本步骤。要进一步控制结构和样式,请先调查Android文档和相应的源代码以了解您能够实现多少并植入需要的操作。