Android自定义View入门级
来源:互联网 发布:淘宝药店 提交需求 编辑:程序博客网 时间:2024/05/18 03:08
Android入门级的自定义View,比较基础,例子也都是找的大神的博客看看敲敲的。直接上代码,代码中有详细注释。
一、Android自定义View
总结来说,自定义控件的实现有三种方式,分别是:自绘控件、组合控件和继承控件。
三个比较重要的方法:onMeasure(),onLayout(),onDraw()
二、自定义View自绘控件
(继承View的点击获取随机数显示)
博客:http://blog.csdn.net/lmj623565791/article/details/24252901/
1、在res/values/目录下新建一个attrs.xml,在里面声明属性和样式
<resources> //自定义属性 <declare-styleable name="custom_view"> <attr name="text_color" format="color" /> <attr name="text_text" format="string" /> <attr name="text_size" format="dimension" /> </declare-styleable></resources>
2、继承View类,在构造方法中,获取我们的样式
public class MyCustomView extends View { private String mTextString; private int mTextColor; private float mTextSize; //图形和画笔 private Rect mRect; private Paint mPaint; public MyCustomView(Context context) { this(context, null); } public MyCustomView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyCustomView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //和XML中的属性建立连接 TypedArray _typeArray = context.obtainStyledAttributes(attrs, R.styleable.custom_view, defStyleAttr, 0); mTextString = _typeArray.getString(R.styleable.custom_view_text_text); mTextColor = _typeArray.getColor(R.styleable.custom_view_text_color, 0); mTextSize = _typeArray.getDimension(R.styleable.custom_view_text_size, (float) 15); //使用recycle()方法,使得可以实时获取属性值 _typeArray.recycle(); //画一个矩形 mPaint = new Paint(); mPaint.setTextSize(mTextSize); mRect = new Rect(); mPaint.getTextBounds(mTextString, 0, mTextString.length(), mRect); //当前View的点击事件,显示变化的数字 this.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mTextString = getRandomText(); //在子线程中刷新view postInvalidate(); } }); } /** * 测量自定义view,一般在view中都是这种固定的模式 * * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //将测量结束的尺寸传给setMeasuredDimension方法 setMeasuredDimension(getWidthDimension(widthMeasureSpec), getHeightDimension(heightMeasureSpec)); } /** * 一般在自定义view中(继承View类),不需要重新布局 * * @param changed * @param left * @param top * @param right * @param bottom */ @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); } /** * 重写onDraw,重新绘制 * * @param canvas */ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint.setColor(Color.YELLOW); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint); mPaint.setColor(mTextColor); canvas.drawText(mTextString, getWidth() / 2 - mRect.width() / 2, getHeight() / 2 + mRect.height() / 2, mPaint); } /** * 获取宽的测量尺寸 * * @param _widthMeasureSpec * @return */ public int getWidthDimension(int _widthMeasureSpec) { int _resultWidthDimension = 200; int _widthMode = MeasureSpec.getMode(_widthMeasureSpec); int _widthSize = MeasureSpec.getSize(_widthMeasureSpec); if (MeasureSpec.EXACTLY == _widthMode) { _resultWidthDimension = _widthSize; } else { _resultWidthDimension = Math.min(_widthSize, _resultWidthDimension); } return _resultWidthDimension; } /** * 获取高的测量尺寸 * * @param _heightMeasureSpec * @return */ public int getHeightDimension(int _heightMeasureSpec) { int _resultHeightDimension = 200; int _heightMode = MeasureSpec.getMode(_heightMeasureSpec); int _heightSize = MeasureSpec.getSize(_heightMeasureSpec); if (MeasureSpec.EXACTLY == _heightMode) { _resultHeightDimension = _heightSize; } else { _resultHeightDimension = Math.min(_heightSize, _resultHeightDimension); } return _resultHeightDimension; } /** * 获取一个变化的四位数 * * @return */ public String getRandomText() { StringBuilder _stringBuilder = new StringBuilder(); Random _random = new Random(); Set<Integer> _set = new HashSet<>(); while (_set.size() < 4) { int _randomInt = _random.nextInt(10); _set.add(_randomInt); } for (Integer j : _set) { _stringBuilder.append(j); } return _stringBuilder.toString(); }}
3、在布局中使用
重要:xmlns:mycustomview=”http://schemas.android.com/apk/res-auto”使用自定义命名空间
<com.millet.millet.CustomView.MyCustomView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" mycustomview:text_color="@color/colorPrimary" mycustomview:text_size="20dp" mycustomview:text_text="你好" />
4、效果
三、自定义View组合控件
(标题栏的组合)
参照Android群英传一书
1、在attrs.xml中声明属性和样式
<resources> //自定义组合控件 <declare-styleable name="custom_view_mix"> <attr name="left_text" format="string" /> <attr name="left_text_size" format="dimension" /> <attr name="middle_text" format="string" /> <attr name="middle_text_size" format="dimension" /> <attr name="right_text" format="string" /> <attr name="right_text_size" format="dimension" /> <attr name="bg" format="color" /> </declare-styleable></resources>
2、继承ViewGroup,在构造方法中获取属性
public class MyCustomViewMix extends LinearLayout { private String _leftString, _middleString, _rightString; private float _leftSize, _middleSize, _rightSize; private int _colorBg; private TextView _leftText, _middleText, _rightText; private LinearLayout _linear; public MyCustomViewMix(Context context) { this(context, null); } public MyCustomViewMix(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyCustomViewMix(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //和XML中的属性建立连接 TypedArray _typeArray = context.obtainStyledAttributes(attrs, R.styleable.custom_view_mix, defStyleAttr, 0); _leftString = _typeArray.getString(R.styleable.custom_view_mix_left_text); _middleString = _typeArray.getString(R.styleable.custom_view_mix_middle_text); _rightString = _typeArray.getString(R.styleable.custom_view_mix_right_text); _leftSize = _typeArray.getDimension(R.styleable.custom_view_mix_left_text_size, (float) 15); _middleSize = _typeArray.getDimension(R.styleable.custom_view_mix_middle_text_size, (float) 15); _rightSize = _typeArray.getDimension(R.styleable.custom_view_mix_right_text_size, (float) 15); _colorBg = _typeArray.getColor(R.styleable.custom_view_mix_bg, getResources().getColor(R.color.colorPrimaryDark)); //使用recycle()方法,使得可以实时获取属性值 _typeArray.recycle(); initView(context); } public void initView(Context _context) { LayoutInflater.from(_context).inflate(R.layout.my_custom_view_mix, this, true); _leftText = (TextView) findViewById(R.id.my_custom_view_mix_left); _middleText = (TextView) findViewById(R.id.my_custom_view_mix_middle); _rightText = (TextView) findViewById(R.id.my_custom_view_mix_right); _linear = (LinearLayout) findViewById(R.id.my_custom_view_mix_bg); _linear.setBackgroundColor(_colorBg); _leftText.setText(_leftString); _middleText.setText(_middleString); _rightText.setText(_rightString); _leftText.setTextSize(_leftSize); _middleText.setTextSize(_middleSize); _rightText.setTextSize(_rightSize); }
3、在布局中使用
重要:xmlns:apps=”http://schemas.android.com/apk/res-auto”使用自定义命名空间
<com.millet.millet.CustomView.MyCustomViewMix android:layout_width="match_parent" android:layout_height="wrap_content" apps:bg="@android:color/holo_green_dark" apps:left_text="left" apps:left_text_size="8dp" apps:middle_text="middle" apps:middle_text_size="8dp" apps:right_text="right" apps:right_text_size="8dp" />
4、图片效果
四、自定义View继承控件
(ListView的滑动删除)
博客:http://blog.csdn.net/guolin_blog/article/details/17357967
1、先准备一个删除的布局样式delete_button.xml
<?xml version="1.0" encoding="utf-8"?><Button xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/delete_button" android:layout_width="match_parent" android:layout_height="60dp" android:background="@color/colorPrimaryDark" android:text="删除" />
2、继承ListView类,进行添加滑动删除的功能
public class MyCustomViewExtends extends ListView implements GestureDetector.OnGestureListener, View.OnTouchListener { //手势 private GestureDetector mGestureDetector; private onDeleteListener mOnDeleteListener; //当前选择的第几个 private int mSelectedItem; //是否显示了删除按钮 private boolean mIsDeleteShown; //ListView的Item private ViewGroup mItemLayout; //删除布局 private View mDeleteButton; public MyCustomViewExtends(Context context) { this(context, null); } public MyCustomViewExtends(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyCustomViewExtends(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //初始化手势以及注册手势事件 mGestureDetector = new GestureDetector(context, this); //注册touch事件 setOnTouchListener(this); } //对外留一个注册删除回调接口 public void setOndeleteListener(onDeleteListener _l) { mOnDeleteListener = _l; } /*以下属于Touch事件的回调方法*/ @Override public boolean onTouch(View v, MotionEvent event) { //判断删除按钮是否可见,如果可见,则从ListView的Item中移除删除按钮 if (mIsDeleteShown) { mItemLayout.removeView(mDeleteButton); mDeleteButton = null; mIsDeleteShown = false; return false; } else { //调用手势的点击事件 return mGestureDetector.onTouchEvent(event); } } /*以下属于手势的回调方法*/ @Override public boolean onDown(MotionEvent e) { //假如没有显示删除的布局,我们根据点击事件来计算当前点击的布局Item if (!mIsDeleteShown) { mSelectedItem = pointToPosition((int) e.getX(), (int) e.getY()); } return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { //根据是否显示和在横向滑动的情况下处理 if (!mIsDeleteShown && Math.abs(velocityX) > Math.abs(velocityY)) { //初始化删除按钮布局 mDeleteButton = LayoutInflater.from(getContext()).inflate(R.layout.delete_button, null); //初始化ListView的Item mItemLayout = (ViewGroup) getChildAt(mSelectedItem - getFirstVisiblePosition()); //在ListView的Item中放置删除按钮 RelativeLayout.LayoutParams _param = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT); _param.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); _param.addRule(RelativeLayout.CENTER_VERTICAL); mItemLayout.addView(mDeleteButton, _param); //设置删除按钮为可见状态 mIsDeleteShown = true; //点击删除按钮事件 mDeleteButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //点击删除按钮,在ListView中移除删除按钮 mItemLayout.removeView(mDeleteButton); mDeleteButton = null; //设置删除按钮为不可见 mIsDeleteShown = false; //使用回调对外传出对第几个Item进行了删除 mOnDeleteListener.onDelete(mSelectedItem); } }); } return false; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; } @Override public void onLongPress(MotionEvent e) { } //删除监听接口 public interface onDeleteListener { void onDelete(int _index); }}
3、在布局中使用
<com.millet.millet.CustomView.MyCustomViewExtends android:id="@+id/activity_my_custom_list_view" android:layout_width="match_parent" android:layout_height="match_parent" android:dividerHeight="2dp" />
4、在Activity中使用
public class MyCustomListView extends BaseActivity { private MyCustomViewExtends mMyCustomViewExtends; private MyCustomListViewAdapter mMyCustomListViewAdapter; private List<String> mList = new ArrayList<>(); @Override public void initData(Bundle savedInstanceState) { for (int i = 0; i < 20; i++) { mList.add("Millet" + i); } } @Override public void initView(Bundle savedInstanceState) { setContentView(R.layout.activity_my_custom_list_view); mMyCustomViewExtends = (MyCustomViewExtends) findViewById(R.id.activity_my_custom_list_view); mMyCustomListViewAdapter = new MyCustomListViewAdapter(this, 0, mList); mMyCustomViewExtends.setAdapter(mMyCustomListViewAdapter); mMyCustomViewExtends.setOndeleteListener(new MyCustomViewExtends.onDeleteListener() { @Override public void onDelete(int _index) { mList.remove(_index); mMyCustomListViewAdapter.notifyDataSetChanged(); } }); } @Override public void loadData(Bundle savedInstanceState) { } public class MyCustomListViewAdapter extends ArrayAdapter { public MyCustomListViewAdapter(Context context, int resource, List<String> objects) { super(context, resource, objects); } @NonNull @Override public View getView(int position, View convertView, ViewGroup parent) { View _view; if (null == convertView) { _view = getLayoutInflater().inflate(R.layout.my_list_view_item, null); } else { _view = convertView; } TextView _textView = (TextView) _view.findViewById(R.id.my_list_view_item_text); _textView.setText((String) getItem(position)); return _view; } }}
5、图片效果
0 0
- Android自定义View入门级
- Android自定义View入门
- Android自定义View入门
- Android 自定义View入门
- Android自定义View入门
- Android自定义View入门
- Android--自定义View入门
- Android开发-自定义view-入门级自定义view全注解
- Android入门级自定义View-拼图游戏
- Android自定义View的入门
- Android自定义View入门---自定义一个TextView
- android自定义控件(二) 入门,继承View
- android自定义控件(二) 入门,继承View
- android自定义控件(二) 入门,继承View
- android自定义控件(二) 入门,继承View
- Android开发,自定义View(一)-----入门
- Android View---自定义View
- Android View---自定义View
- JAVA设计模式之适配器模式
- 【JZOJ 4910】子串
- 深度探索C语言函数可变长参数
- mysql多源复制
- IoC容器笔记2
- Android自定义View入门级
- docker相关技术
- Prime Ring Problem
- python学习_基础(一)
- 闪屏
- MySQL存储过程学习
- 系统tcp 连接状态统计
- POJ 3050 Hopscotch 笔记
- hive udf