Android学习笔记(六) 自定义控件
自定义控件则需继承相应的控件类,控件的基类则是View,如果只是开发普通的控件,只继承View类就可以了。控件的构造函数的声明如下
View(Context context) View(Context context, AttributeSet attrs) View(Context context, AttributeSet attrs, int defStyle)
定义控件对本人来说要么是定义了控件的视图,要么是外放了控件的属性,要么是外放控件的方法。
创建属性 方式1
布局文件的内容如下
<com.example.testandroidproject.MyTestControl android:id="@+id/con1" android:layout_width="wrap_content" android:layout_height="wrap_content" Text="@string/_1234565" />
控件名要是类的全名,属性只单纯的Text则可,到类文件的构造函数里面使用
int textId = attrs.getAttributeResourceValue(null, "Text",0); mtext = context.getResources().getText(textId).toString();
则可以获取布局文件的Text的值,因为这里是从资源里面的值,所以布局文件只能填@string/的值
创建属性 方式2
在res/values的文件夹下面添加一个文件attrs.xml,内容如下
<resources > <declare-styleable name="MyTestUserControl"> <attr name="text" format="string" /> <attr name="textColor" format="color" /> </declare-styleable> </resources>
在布局文件中需要引用新的命名空间
xmlns:app=http://schemas.android.com/apk/res/com.example.testandroidproject
其实后面那段就是项目的包名
app就是新的命名空间的名称,其实android都是一个命名空间而已,那么控件属性就可以用这种形式设置
<com.example.testandroidproject.MyTestControl android:id="@+id/con1" android:layout_width="wrap_content" android:layout_height="wrap_content" app:text="@string/_1234565" app:textColor="#0000ff" />
然后在控件类的构造函数里面加入以下代码
int resourceId = 0; TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.MyTestUserControl); int N = typedArray.getIndexCount(); for (int i = 0; i < N; i++) { int attr = typedArray.getIndex(i); switch (attr) { case R.styleable.MyTestUserControl_text: mtext = typedArray.getString( R.styleable.MyTestUserControl_text); mtext=typedArray.getString(attr); break; case R.styleable.MyTestUserControl_textColor: resourceId = typedArray.getResourceId( R.styleable.MyTestUserControl_textColor, 0); mColor= resourceId > 0 ? typedArray.getResources().getColor(resourceId): typedArray.getColor(R.styleable.MyTestUserControl_textColor, Color.BLACK); break; } } typedArray.recycle();
其中第二行context.obtainStyledAttributes方法传入的第二个参数是attrs.xml对应的declare-styleable节点的name属性值。Text属性的值还是要通过资源文件中获取,所以布局文件中的属性设置不能是字面值了。
组合控件
如果定义的控件其实是组合控件来的,那么这个控件是继承一些布局的视图类
例如布局文件如下
< LinearLayout xmlns:Android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center_vertical"> <TextView android:id="@android:id/lab1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Label1" /> <EditText android:id="@android:id/txt1" android:layout_width="fill_parent" android:layout_height="wrap_content" /> < /LinearLayout>
在类的文件里面就要用这样的构造函数
public LabelText(Context context) { this(context, null); } public LabelText(Context context, AttributeSet attrs) { super(context, attrs); //在构造函数中将Xml中定义的布局解析出来。 LayoutInflater.from(context).inflate(R.layout.imagebtn_with_text, this, true); }
同时还外放了一些别的方法,整个类的定义如下了
public class LabelText extends LinearLayout { TextView label; EditText textBox; public LabelText(Context context) { this(context, null); } public LabelText(Context context, AttributeSet attrs) { super(context, attrs); //在构造函数中将Xml中定义的布局解析出来。 LayoutInflater.from(context).inflate(R.layout.imagebtn_with_text, this, true); label=(TextView)findViewById(R.id.lab1); textBox=(EditText)findViewById(R.id.txt1); } public void SetTextBoxText(String val) { textBox.setText(val); } public String GetTextBoxText() { return textBox.getText(); } public void SetLabelText(String val) { label.setText(val); } public String GetTextBoxText() { return label.getText(); } }
基类View的方法
定义控件时,可重写的基类方法,View里面提供的方法如下
- onFinishInflate() 当View中所有的子控件 均被映射成xml后触发
- onMeasure(int, int) 确定所有子元素的大小
- onLayout(boolean, int, int, int, int) 当View分配所有的子元素的大小和位置时触发
- onSizeChanged(int, int, int, int) 当view的大小发生变化时触发
- onDraw(Canvas) view渲染内容的细节
- onKeyDown(int, KeyEvent) 有按键按下后触发
- onKeyUp(int, KeyEvent) 有按键按下后弹起时触发
- onTrackballEvent(MotionEvent) 轨迹球事件
- onTouchEvent(MotionEvent) 触屏事件
- onFocusChanged(boolean, int, Rect) 当View获取 或失去焦点时触发
- onWindowFocusChanged(boolean) 当窗口包含的view获取或失去焦点时触发
- onAttachedToWindow() 当view被附着到一个窗口时触发
- onDetachedFromWindow() 当view离开附着的窗口时触发,该方法和 onAttachedToWindow() 是相反的。
- onWindowVisibilityChanged(int) 当窗口中包含的可见的view发生变化时触发
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步