自定义View(及多点触控)及View的生命周期

> 监听手指上下左右滑动

在Android应用中,经常需要手势滑动操作,比如上下滑动,或左右方向滑动,处理手势滑动通常有两种方法:一种是单独实现setOnTouchListener监听器来,另一种是构建手势探测器。
第一种方法,就是在要实现滑动的View中,实现OnTouchListener监听事件,然后判断KeyDonw和KeyUp 直接的位置距离来判断滑动方向。第二种方法:就是构建手势探测器,如GestureDetector mygesture = new GestureDetector(this);,然后在onFling方法中根据MotionEvent的两个参数的 按下和滑动以及放开的位置和距离来判断滑动方向以及滑动速度等的。要构建GestureDetector,必须要和OnTouchListener一起使用,因为必须设置Touch监听。
Android开发之手势滑动(滑动手势监听)详解- http://www.cnblogs.com/JczmDeveloper/p/3772967.html
用Activity的onTouchEvent方法实现监听手指上下左右滑动- http://blog.csdn.net/qiantujava/article/details/9903891

-------------------------------

移动开发之手势与双指缩放-http://geek.csdn.net/news/detail/193169
  iOS的Safari浏览器是第一个支持多点触摸的浏览器,并提供触摸API供开发者使用,到后来Android 3也开始支持多点触摸,各大浏览器也借鉴Safari提出了触摸API,除了个别硬件支持属性外,大致相同,这是值得庆幸的。
  IE10支持多点触摸,但是其多点触摸与iOS和Android不同,iOS和Android浏览器为多点触摸提供一个包含touches数组的事件,包含所有多点触摸对象,而IE10为多点触摸的每一个触摸点创建一个单独的触摸事件。

> 自定义圆形进度条

Android高手进阶之自定义View,自定义属性(带进度的圆形进度条)- http://download.csdn.net/detail/xiaanming/6008579
三种方式实现自定义圆形页面加载中效果的进度条 - https://yq.aliyun.com/articles/4346
android利用shap画小圆圈(空心圆、实心圆)- http://blog.csdn.net/l506945024/article/details/52587112
自定义View(自定义圆形效果)- http://www.jianshu.com/p/f54a928878ca


Android自定义控件- http://blog.csdn.net/q4878802/article/category/5664655

各种Android自定义控件、Widget、Material Design- http://www.ctolib.com/topics-113378.html
自定义控件其实很简单- http://blog.csdn.net/aigestudio?viewmode=contents

自定义控件三部曲之绘图- http://blog.csdn.net/harvic880925/article/category/1707319/1
自定义view- http://blog.csdn.net/wingichoy/article/category/6032967

安卓自定义View进阶-多点触控详解- http://www.gcssloop.com/customview/multi-touch

【Android】View绘制过程分析之measure-- http://blog.csdn.net/rongxinhua/article/details/19649015

【Android】View绘制过程分析之layout-- http://blog.csdn.net/rongxinhua/article/details/19650373
【Android】View绘制过程分析之draw-- http://blog.csdn.net/rongxinhua/article/details/19676689

让你的app提升一个档次-Android酷炫自定义控件-- http://www.jianshu.com/p/356619fe64d5#

》Android 如何保存与恢复自定义View的状态?- http://blog.csdn.net/a553181867/article/details/54633151

自定义控件分为自定义组合组件和自定义View。

自定义View的实现方式大概可以分为三种,自绘控件、组合控件、以及继承控件。

深入理解android view 生命周期 -http://blog.csdn.net/sun_star1chen/article/details/44626433

     自定义View时我们不可避免的要和View生命周期相关函数打交道,可能需要重新其中的某个或某几个来满足定制的需求,因此了解View的生命周期是Android程序猿进阶的必经之路。

android 自定义控件/view有以下14个周期:

  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离开附着的窗口时触发,Android123提示该方法和  onAttachedToWindow() 是相反的。  
  onWindowVisibilityChanged( int ) 当窗口中包含的可见的view发生变化时触发 

> View.requestLayout(),请求重新布局,重新调用onMeasure(),onLayout(),onDraw()

View.invalidate(),刷新视图,相当于调用onDraw()

> postInvalidate()和invalidate()的区别
  都用于刷新界面;postInvalidate()用在子线程invalidate()用在主线程

> notifyDataSetChanged和notifyDataSetInvalidated的区别
  notifyDataSetInvalidated(),会重绘整个控件(还原到初始状态)
  notifyDataSetChanged(),重绘当前可见区域

> View本身的大小,由onMeasure()决定;View在ViewGroup中的位置,由onLayout()决定;绘制View,onDraw定义了如何绘制这个View。

postInvalidate() 可在线程中更新UI;  invalidate()在主线程中更新UI。

> 自定义View的三个主要方法

1、自定义View的属性
2、在View的构造方法中获得我们自定义的属性

一、onMeasure()方法
onMeasure(int widthMeasureSpec,int heightMeasureSpec)
1、调用时间:当控件的父元素放置该控件时,用于告诉父元素该控件需要的大小。
2、传入参数:widthMeasureSpec,heightMeasureSpec。这两个传入参数由高32位和低16位组成,高32位保存的值叫specMode,可以通过MeasureSpec.getMode()获取;低16位为specSize可以由MeasureSpec.getSize()获取。这两个值是由ViewGroup中的layout_width,layout_height和padding以及View自身的layout_margin共同决定。权值weight也是尤其需要考虑的因素,有它的存在情况可能会稍微复杂点。

二、onLayout()方法
onLayout(boolean changed, int left, int top,int right,int bottom);
父容器的onLayout()调用子类的onLayout()来确定子view在viewGroup中的位置,如:onLayout(10,10,100,100)表示子容器在父容器中(10,10)位置显示,长、宽都是90。结合onMeasure()方法使用可以确定子view的布局。

三、onDraw()方法
onDraw(Canvas canvas)
自定义view的关键方法,用于绘制界面,可以重写此方法以绘制自定义View。


import java.util.HashSet;
import java.util.Random;
import java.util.Set;


import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;


import com.example.customview01.R;


public class CustomTitleView extends View
{
/**
* 文本
*/
private String mTitleText;
/**
* 文本的颜色
*/
private int mTitleTextColor;
/**
* 文本的大小
*/
private int mTitleTextSize;

/**
* 绘制时控制文本绘制的范围
*/
private Rect mBound;
private Paint mPaint;
public CustomTitleView(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public CustomTitleView(Context context)
{
this(context, null);
}
/**
* 获得我自定义的样式属性,构造方法

* @param context
* @param attrs
* @param defStyle
*/
public CustomTitleView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
/**
* 获得我们所定义的自定义样式属性
*/
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomTitleView, defStyle, 0);
int n = a.getIndexCount();
for (int i = 0; i < n; i++)
{
int attr = a.getIndex(i);
switch (attr)
{
case R.styleable.CustomTitleView_titleText:
mTitleText = a.getString(attr);
break;
case R.styleable.CustomTitleView_titleTextColor:
// 默认颜色设置为黑色
mTitleTextColor = a.getColor(attr, Color.BLACK);
break;
case R.styleable.CustomTitleView_titleTextSize:
// 默认设置为16sp,TypeValue也可以把sp转化为px
mTitleTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
break;

}

}
a.recycle();
/**
* 获得绘制文本的宽和高
*/
mPaint = new Paint();
mPaint.setTextSize(mTitleTextSize);
// mPaint.setColor(mTitleTextColor);
mBound = new Rect();
mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);

this.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
mTitleText = randomText();
postInvalidate();
}
});
}
private String randomText()
{
Random random = new Random();
Set<Integer> set = new HashSet<Integer>();
while (set.size() < 4)
{
int randomInt = random.nextInt(10);
set.add(randomInt);
}
StringBuffer sb = new StringBuffer();
for (Integer i : set)
{
sb.append("" + i);
}
return sb.toString();
}


//设置控件的高度和宽度
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = 0;
int height = 0;
/**
* 设置宽度
*/
int specMode = MeasureSpec.getMode(widthMeasureSpec);
int specSize = MeasureSpec.getSize(widthMeasureSpec);
switch (specMode)
{
case MeasureSpec.EXACTLY:// 明确指定了
width = getPaddingLeft() + getPaddingRight() + specSize;
break;
case MeasureSpec.AT_MOST:// 一般为WARP_CONTENT
width = getPaddingLeft() + getPaddingRight() + mBound.width();
break;
}
/**
* 设置高度
*/
specMode = MeasureSpec.getMode(heightMeasureSpec);
specSize = MeasureSpec.getSize(heightMeasureSpec);
switch (specMode)
{
case MeasureSpec.EXACTLY:// 明确指定了
height = getPaddingTop() + getPaddingBottom() + specSize;
break;
case MeasureSpec.AT_MOST:// 一般为WARP_CONTENT
height = getPaddingTop() + getPaddingBottom() + mBound.height();
break;
}
setMeasuredDimension(width, height);


}
//
@Override
protected void onDraw(Canvas canvas)
{
mPaint.setColor(Color.YELLOW);
canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);


mPaint.setColor(mTitleTextColor);
canvas.drawText(mTitleText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
}
}

转载地址:http://blog.csdn.net/lmj623565791/article/details/24252901

你可能感兴趣的:(自定义View(及多点触控)及View的生命周期)