Android群英传-自定义View、控件
来源:互联网 发布:程序员直播赚钱 编辑:程序博客网 时间:2024/05/17 04:07
注意点
- 绘制View的显示内容,需要重写
onDraw()
方法 - 该View若要使用
wrap_content
属性,必须重写onMeasure()
方法 - 通过自定义
attrs
属性,还可以设置新的属性配置值
View中重要的回调方法
- ++onFinishInflate()++: 从XML加载组件后回调
- ++onSizeChanged()++:组件大小改变时
- onMeasure():进行测量
- onLayout(): 确定显示的位置
- onTouchEvent(): 监听触摸事件时回调
自定义控件三大方法
一、现有控件进行扩展
比如扩展TextView
思路如下:
@Override protected void onDraw(Canvas canvas) { //回调父类方法前,实现自己的逻辑,对TextView来说在“绘制文本”内容之前 super.onDraw(canvas); //回调父类方法后,实现自己的逻辑,对TextView来说在“绘制文本”内容之后 }
1.利用画笔绘制矩形框
public class MyTextView extends TextView { public MyTextView(Context context) { super(context); } public MyTextView(Context context,AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { //回调父类方法前,实现自己的逻辑,对TextView来说在“绘制文本”内容之前 Paint mPaint1 = new Paint(); mPaint1.setColor(ContextCompat.getColor(getContext(), R.color.colorAccent)); mPaint1.setStyle(Paint.Style.FILL); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint1); canvas.save(); //绘制文字前平移10像素(px) canvas.translate(10, 0); super.onDraw(canvas); canvas.restore(); }}
2.LinearGradient Shader
和Matrix
实现动态的文字闪动效果
需要onDraw()
和onSizeChanged()
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if(mMatrix != null){ mTranslate += mViewWidth/5; if(mTranslate > 2*mViewWidth){ mTranslate = -mViewWidth; } mMatrix.setTranslate(mTranslate, 0); mLinearGradient.setLocalMatrix(mMatrix); postInvalidateDelayed(100); } }@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if(mViewWidth == 0){ mViewWidth = getMeasuredWidth(); if(mViewWidth > 0){ mPaint = getPaint(); mLinearGradient = new LinearGradient( 0, 0, mViewWidth, 0, new int[]{ Color.BLUE, 0xffffffff, Color.BLUE}, null, Shader.TileMode.CLAMP); mPaint.setShader(mLinearGradient); mMatrix = new Matrix(); } } }
二、复合控件
简单的组合控件:
链接:http://blog.csdn.net/yelangjueqi/article/details/8879340
1.定义属性
为一个View提供自定义的属性,只需要在res
的values
目录下创建一个attrs.xml
的属性定义文件,代码参考下面:
使用UI模板需要引用第三方控件的名字空间
* 下列引用android的系统属性
xmlns:android="http://schemas.android.com/apk/res/android"
- 第三方的控件都使用如下代码来引用名字空间
xmlns:app="http://schemas.android.com/apk/res-auto"
android studio需要使用xmlns:app
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="TopBar"> <attr name="Title" format="string"/> <attr name="TitleTextSize" format="dimension"/> <attr name="TitleTextColor" format="color"/> <attr name="RightText" format="string"/> <attr name="RightTextSize" format="dimension"/> <attr name="RightTextColor" format="color"/> <attr name="LeftImageSize" format="integer"/> </declare-styleable></resources>
2.自定义控件类
package com.example.lenovo.qqdemos.CustomView;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Color;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.View;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;import com.example.lenovo.qqdemos.R;/** * Created by feather on 2016/8/19. */public class TopBar extends LinearLayout{ private ImageView mHeadImage; private TextView mTitleText; private TextView mRightText; //标题 String mTitle; int mTitleTextColor; float mTitleTextSize; //左侧头像 float mHeadImageSize; //右侧文本 String mRightTextStr; int mRightTextColor; float mRightTextSize; //接口 topbarClickListener mListener; public TopBar(Context context, AttributeSet attrs) { super(context, attrs); //注意参数: root=this, 及 attachToRo LayoutInflater.from(context).inflate(R.layout.feather_topbar, this, true); mHeadImage = (ImageView) findViewById(R.id.topbar_head_image); mTitleText = (TextView) findViewById(R.id.topbar_title); mRightText = (TextView) findViewById(R.id.topbar_right_text); //将在 atts.xml中定义的 declare-styleable的所有属性的值存储到 TypedArray中 TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TopBar); /*----------------------------------------------------------- * 标题-根据属性初始化 * ----------------------------------------------------------*/ String mTitle = typedArray.getString(R.styleable.TopBar_Title); int mTitleTextColor = typedArray.getColor(R.styleable.TopBar_TitleTextColor, Color.WHITE); float mTitleTextSize = typedArray.getDimension(R.styleable.TopBar_TitleTextSize, 20); if(mTitle != null) mTitleText.setText(mTitle); mTitleText.setTextColor(mTitleTextColor); mTitleText.setTextSize(mTitleTextSize); /*----------------------------------------------------------- * 左侧头像-根据属性初始化 * ----------------------------------------------------------*/ int mHeadImageSize = typedArray.getInt(R.styleable.TopBar_LeftImageSize, 20); mHeadImage.setMaxWidth(mHeadImageSize); mHeadImage.setMaxHeight(mHeadImageSize); //监听器 mHeadImage.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mListener.leftImageClick(); } }); /*----------------------------------------------------------- * 右侧文本-根据属性初始化 * ----------------------------------------------------------*/ String mRightTextStr = typedArray.getString(R.styleable.TopBar_RightText); int mRightTextColor = typedArray.getColor(R.styleable.TopBar_RightTextColor, Color.WHITE); float mRightTextSize = typedArray.getDimension(R.styleable.TopBar_RightTextSize, 20); if(mRightTextStr != null) mRightText.setText(mRightTextStr); mRightText.setTextColor(mRightTextColor); mRightText.setTextSize(mRightTextSize); //监听器 mRightText.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mListener.rightTextClick(); } }); } public interface topbarClickListener{ void leftImageClick(); void rightTextClick(); }}
1.其中使用属性的办法
//将在 atts.xml中定义的 declare-styleable的所有属性的值存储到 TypedArray中 TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TopBar); /*----------------------------------------------------------- * 根据属性初始化 * ----------------------------------------------------------*/ String mTitle = typedArray.getString(R.styleable.TopBar_Title); int mTitleTextColor = typedArray.getColor(R.styleable.TopBar_TitleTextColor, Color.WHITE); float mTitleTextSize = typedArray.getDimension(R.styleable.TopBar_TitleTextSize, 20); int mHeadImageSize = typedArray.getInt(R.styleable.TopBar_LeftImageSize, 20); String mRightTextStr = typedArray.getString(R.styleable.TopBar_RightText); int mRightTextColor = typedArray.getColor(R.styleable.TopBar_RightTextColor, Color.WHITE); float mRightTextSize = typedArray.getDimension(R.styleable.TopBar_RightTextSize, 20); //避免重新创建时的错误 typedArray.recycle();
2.该控件的布局
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorBlue" android:orientation="vertical" > <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#00000000"> <com.pkmmte.view.CircularImageView android:id="@+id/topbar_head_image" android:layout_width="40dp" android:layout_height="40dp" android:src="@drawable/default_user_head" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:visibility="invisible" > </com.pkmmte.view.CircularImageView> <TextView android:id="@+id/topbar_title" android:layout_width="wrap_content" android:layout_height="match_parent" android:text="标题" android:textSize="20dp" android:gravity="center" android:textColor="@color/white" android:layout_centerInParent="true" android:visibility="invisible"/> <TextView android:id="@+id/topbar_right_text" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_centerInParent="true" android:text="编辑" android:textSize="20dp" android:layout_alignParentRight="true" android:layout_marginRight="4dp" android:textColor="@color/white" android:gravity="center" android:visibility="invisible"/> </RelativeLayout></LinearLayout>
3.使用该控件
- 可以通过
xmlns:app="http://schemas.android.com/apk/res-auto"
使用自定义属性,如下面app:Title
部分
<com.example.lenovo.qqdemos.CustomView.TopBar xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/chat_menu_topbar" android:layout_width="match_parent" android:layout_height="55dp" app:Title="hello"> </com.example.lenovo.qqdemos.CustomView.TopBar>
错误提示
1.android.view.InflateException: Binary XML file line #9: Error inflating class com.feather.past.MyTextView
2.java.lang.NoSuchMethodException: [class android.content.Context, interface android.util.AttributeSet]
1.报错原因:
在自定义view时,没有重写含有(Context context,AttributeSet attrs)的构造器
解决办法:
重新对于构造器,例如:
public ControlKeyboardLinearLayout(Context context,AttributeSet attrs){ super(context, attrs); }
2.报错原因:
自定义view为内部类时,没有将内部类设置为static,例如:
public class a{ public class b extents TextVIew{ ... }}
解决办法:
为内部类加上static关键字,例如:
public class a{ public static class b extents TextVIew{ ... }}
0 0
- Android群英传-自定义View、控件
- 自定义View (Android群英传)
- 《Android 群英传》读书笔记:自定义 View 之创建复合控件
- 自定义View(一)(Android群英传)
- 自定义view android群英传笔记
- 自定义View(二)(Android群英传)
- 自定义View(三)(Android群英传)
- Android群英传读书笔记---自定义控件(-)
- Android群英传--自定义View详解(一)
- Android群英传读书笔记第三章(Android控件架构与自定义View)
- android群英传之自定义View--对现有控件进行扩展(1)
- android群英传笔记--第三章--自定义控件三简单形状View
- 《Android 群英传》读书笔记:自定义 View 之对现有控件进行拓展
- Android群英传之Android控件架构与自定义控件
- 3.Android群英传读书笔记-控件架构与自定义控件
- Android群英传 第三章-控件架构与自定义控件
- Android群英传学习——控件架构与自定义控件
- Android群英传——第三章自定义View
- 采用shc工具加密Shell脚本
- DG备库delay设置备库延时apply archivelog 但不延时传送归archivelog
- 小白程序北漂一周年
- 生成mif文件
- 前端自动化工具Grunt的使用
- Android群英传-自定义View、控件
- Data truncation: Incorrect datetime value: '' for column 'create_date' at row 1
- Oracle视图(View)创建使用
- 周记2016.7
- 如何构建你自己的 Git 服务器
- Xcode 如何使用旧版本SDK以保证程序兼容性
- tjut 3065
- Pycharm 使用大全
- “好打”的美团真能玩,在上海不遵守商务楼规定还聚众滋事