Android 提供了一个复杂且强大的组件化模型,可帮助您根据基本布局类 View 和 ViewGroup 构建界面。首先,该平台包含各种预构建的 View 和 ViewGroup 子类,分别称为微件和布局,可供用来构建界面。
- 可用的部分微件: Button、TextView、EditText、ListView、CheckBox、RadioButton、Gallery、Spinner,以及具有特殊用途的 AutoCompleteTextView、ImageSwitcher 和 TextSwitcher。
- 可用布局: LinearLayout、FrameLayout、RelativeLayout 等
而自定义视图组件又分为:
完全自定义的组件可用于创建外观完全如您所需的图形组件。要创建完全自定义的组件,请执行以下操作:
public class CustomView extends View
<declare-styleable name="CustomViewStyle">
<attr name="inner_color" format="color" />
<attr name="inner_background" format="reference" />
</declare-styleable>
// 在代码中调用:
init(){
val a = context.obtainStyledAttributes(attrs, R.styleable.CustomViewStyle, 0, 0)
val innerColor = a.getColor(R.styleable.CustomViewStyle_inner_color, 0)
val layoutBackground = a.getResourceId(R.styleable.CustomViewStyle_inner_background, R.color.transparent)
a.recycle()
}
// View 布局
onMeasure(int, int) 调用以确定此视图及其所有子级的大小要求。
onLayout(boolean, int, int, int, int) 在此视图应为其所有子级分配大小和位置时调用。
onSizeChanged(int, int, int, int) 在此视图的大小发生变化时调用。
// View 绘制
onDraw(Canvas) 在视图应渲染其内容时调用。
// View 事件处理
onKeyDown(int, KeyEvent) 在发生新的按键事件时调用。
onKeyUp(int, KeyEvent) 在发生 key up 事件时调用。
onTrackballEvent(MotionEvent) 在发生轨迹球动作事件时调用。
onTouchEvent(MotionEvent) 在发生触屏动作事件时调用。
// 焦点
onFocusChanged(boolean, int, Rect) 在视图获得或失去焦点时调用。
onWindowFocusChanged(boolean) 在包含视图的窗口获得或失去焦点时调用。
// 附加
onAttachedToWindow() 在视图附加到窗口时调用。
onDetachedFromWindow() 在视图与其窗口分离时调用。
onWindowVisibilityChanged(int) 在包含视图的窗口的可见性发生变化时调用。
示例:【CustomView】扫码中的扫描框(ViewfinderView)-简单实现
整合包含一组现有控件的可再用组件,属于复合组件(或复合控件)。简而言之,这会将许多更原子的控件(或视图)整合到可被视为一件事的项的逻辑分组中。
如要创建复合组件,请执行以下操作:
public class CustomLayoutView extends FrameLayout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:id="@+id/progress_bar_container"
android:clickable="false"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:id="@+id/submission_delay_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/BodyRegBlack"
android:visibility="gone"
android:layout_marginBottom="@dimen/dp_80"
tools:text="Please wait while we submit your inventory count"
/>
<ImageView
android:id="@+id/progress_image"
android:layout_width="@dimen/dp_125"
android:layout_height="@dimen/dp_125"
android:src="@drawable/gif_load_progress"
android:visibility="visible" />
</LinearLayout>
<declare-styleable name="CustomLayoutView">
<attr name="layout_show" format="boolean" />
<attr name="layout_clickable" format="boolean" />
<attr name="layout_background" format="reference" />
</declare-styleable>
// 在代码中调用:
init(){
val a = context.obtainStyledAttributes(attrs, R.styleable.CustomLayoutView, 0, 0)
val layoutClickable = a.getBoolean(R.styleable.CustomLayoutView_layout_clickable, false)
val layoutShow = a.getBoolean(R.styleable.CustomLayoutView_layout_show, false)
val layoutBackground = a.getResourceId(R.styleable.CustomLayoutView_layout_background, R.color.transparent)
a.recycle()
}
onDraw()
和 onMeasure()
方法,因为布局的默认行为会正常发挥作用。不过,您仍然可以根据需要替换这些方法。on...
方法(如 onKeyDown()
),以在按下某个键时从组合框的弹出式列表中选择特定的默认值。对于它,我们可以非常快速地构建任意复杂化的复合视图,并像使用单个组件一样重复使用它们。
示例:【CustomView】Android SlidingTabLayout 按钮之间切换指示器滑动-简单实现
通过一个更简单的选项来创建自定义 View,这在某些情况下非常实用。如果已经有一个组件非常契合您的需要,则只需扩展该组件并只替换您希望更改的行为即可。您可以使用完全自定义的组件来完成所有操作,但是通过从视图层次结构中更专用的类着手,您还可以免费获得很多可能完全符合您需求的行为。
如要创建扩展现有View,请执行以下操作:
public static class LinedEditText extends EditText
1.LinedEditText
定义为 NoteEditor
Activity 中的内部类,但它是公开类,因此可以作为 NoteEditor.LinedEditText
从 NoteEditor
类的外部访问(如果需要)。 2.它是 static
,这意味着它不会生成允许其从父类访问数据的所谓“合成方法”,而这反过来意味着它的行为方式其实就像单独的类(而不是与 NoteEditor
密切相关的类)。如果内部类不需要从外部类访问状态,那么这是创建内部类的更简洁的方法,可以使生成的类一直比较小,并允许其他类轻松使用。 3.它扩展了 EditText
,即我们在这种情况下选择自定义的 View。之后,新类将能够取代普通的 EditText
视图。
// 替换方法,即在原有的on..方法中添加额外的处理
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
if (changed) {
paint.shader = LinearGradient(0F, 0F, width.toFloat() / 2, height.toFloat(), ContextCompat.getColor(context, R.color.colorMainGradient), ContextCompat.getColor(context, R.color.colorMain), Shader.TileMode.CLAMP)
}
}
对于此示例,通过替换 onLayout()
方法,再原View的paint上添加渐变色绘制,是文本以渐变色显示出来。
示例:【CustomView】渐变色文本(GradientTextView)- 简单实现