Android开发艺术探索
第三章VIew事件体系
Android中所有控件的基类是什么?
答:View,View本身就可以是单个控件也可以是多个控件组成的一组控件View位置参数的整理
--getLeft():左上角相对于父容器的横坐标
--getTop( ):左上角相对于父容器的纵坐标
--getRight( ):右下角相对于父容器的横坐标
--getBottom( ):右下角相对于父容器的纵坐标
--getX( )/getY( ):左上角相对于父容器的坐标
--getTranslationX( )/getTranslation( )T:左上角相对于父容器的偏移量
x = left +translationX (left是View的原始位置,并不会发生改变)MotionEvent的三个典型事件和事件序列和TouchSlop
VelocityTracker(速度追踪),GestureDetector(手势检测)和Scroller(弹性滑动对象)
注意点:
(1)如果只监听滑动相关的,建议自己在onTouchEvent中实现,如果要监听双击行为的话,就使用GestureDetector
(2)Scroller需要和view的conputeScroll配合使用,conputeScroll可以使view反复绘制达到弹性滑动的效果View实现滑动的方式有那些?
答:(1)通过view本身提供的scrollTo/scrollBy方法实现(mScrollX,mScrollY的值,左滑负,下滑负)
只能改变view内容的位置,不能改变view在布局中的位置
(2)通过动画给VIew施加平移效果来实现
注意点:
①View动画是对View的影响做操作,并没有真正改变view的位置参数。当一个view改变位置并保存状态后,原位置的onclick事件仍可触发
②使用属性动画可以解决上述问题,但Android3.0以下不支持属性动画。这时可以这样做兼容性适配①
--在新位置创建一个和目标Button一模一样的Button(点击事件也一样),当动画完成后,原Button设置不可见
(3)通过改变View的LayoutParams使View重新布局来实现实现弹性滑动的方法?
答:Scroller、动画和延时策略(handler+scrollTo)使用Scroller实现弹性滑动的原理
答:Scroller本身不能实现View的滑动,他需要配合View的computeScroll方法才能实现弹性滑动,他不断的让view实现重绘(invalidate方法),每次重绘距离起始时间都有一个间隔,通过这个间隔Scroller得出view的当前位置,然后调用scrollTo进行绘制
注意!:设计思路非常赞,这个过程中对View没有丝毫的引用!所以可以和多种view组合使用点击事件的传递(分发)过程?重要的三个方法,分别是做什么的?(记好伪代码,表示三方法之间的关系)
onTouch,onTouchEvent和onClick的优先级顺序?
如果view中的onTouchEvent返回flase,会发生什么?(父容器的onTouchEvent被调用。层层传递)
什么是事件序列
一个事件序列只能被一个view拦截且消耗,一旦一个元素拦截了某次事件,那么同一事件序列内的所有事件都会直接交给它处理。
某个view一旦开始处理事件,如果它不消耗ACTION_DOWN事件(onTouchEvent返回false),那么同一事件序列中的其他事件都不会再交给他处理,而是交给父元素处理
某个view开始处理事件,但只消耗了ACTION_DOWN事件,其他没有消耗,会发生什么?
view什么时候onTouchEvent返回false?(设置两个属性值为false)
viewGroup默认不拦截任何事件
view的enable属性不影响onToucheEvent的返回值
通过requestDisallowInterceptTouchEvent方法可以在子元素中干预父元素的事件分发过程,ACTION_DOWN除外。(具体实例?)
Activity对点击事件的分发过程是什么样的?
-
顶级View对点击事件的分发过程是什么样的?
ViewGroup中dispatchTouchEvent源码中,mFirstTouchTarget的作用?
ViewGroup决定拦截事件后,后续的点击事件将会默认交给他处理并且不再调用他的onInterceptTouchEvent方法
触摸时间传给子View的流程?
事件传递如何继续/终止?(看dispatchTouchEvent的返回值,true终止遍历,false继续分发)
ViewGroup遍历所有的子元素后事件都没有被合适处理的原因?①②
View处理点击事件的方法?(dispatchTouchEvent源码)
为什么onTouch(onTouchListener)的优先级高于onTouchEvent?---(方便在外界处理点击事件)
只要View的CLICKABLE和LONG_CLICKABLE有一个为true,他就会消耗这个事件,onTouchEvent返回true
ACTION_UP触发时onCLick被调用
滑动冲突的常见场景?三种,具体实例
滑动冲突的解决方法?两种,外部拦截法,内部拦截法。注意点 ---实例说明
LeetCode11,12
罗马数字和Interge类型的相互转换
罗马数字->Interge:每个罗马字母代表一个数,相加起来即可,注意最后一个数的大小问题
Interge->罗马数字:截取Interge每一位,对应到数字表中,输出字符串即可。注意str=str+value和str=value+str的区别
代码:
string intToRoman(int num)
{
map<int,int> mymap;
mymap.insert(pair<int,int>(1000,4));
mymap.insert(pair<int,int>(100,3));
mymap.insert(pair<int,int>(10,2));
mymap.insert(pair<int,int>(1,1));
string s[4][9]={{"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"},
{"X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"},
{"C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"},
{"M", "MM", "MMM"}};
string result="";
int f;
int n=1000;
while(num>0)
{
f=num/n;
num=num-f*n;
if(f>0)
{
int x=mymap[n];
result=result+s[x-1][f-1]; //这里就可以定义前后关系啊!!
}
n=n/10;
}
return result;
}
int toNumber(char ch)
{
switch(ch)
{
case 'I': return 1;
case 'V': return 5;
case 'X': return 10;
case 'L': return 50;
case 'C': return 100;
case 'D': return 500;
case 'M': return 1000;
break;
}
return 0;
}
int romanToInt(string s) {
int ret=toNumber(s[0]);
for(int i=1;i<s.size();i++)
{
if (toNumber(s[i - 1]) < toNumber(s[i])) {
ret += toNumber(s[i]) - 2 * toNumber(s[i - 1]);
} else {
ret += toNumber(s[i]);
}
}
return ret;
}
开发中的问题
- AndroidStudio中gradle2.4版本以上对内存占用有优化,不会太爆内存
- Android5.0以后,对BaiduApi等权限,如果手机中有同样权限的软件,为防止相互唤醒,会禁止安装(解决办法?)
- 项目中引入lib本地jar包报错
xxxx\java.exe finished with non-zero exit value 1
,是系统不能正确获取lib路径的问题,解决如下:
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:22.2.1'
compile files('libs/ksoap2-android-assembly-3.0.0-jar-with-dependencies.jar')
compile files('libs/fastjson-1.1.43.android.jar')
compile files('libs/analytics-5.6.1.jar')
compile files('libs/commons-codec-1.10.jar')
compile files('libs/IPJ1.jar')
compile files('libs/layoutlib.jar')
provided files(getLayoutLibPath())
}
def getLayoutLibPath()
{
def rootDir = project.rootDir
def localProperties = new File(rootDir, "local.properties")
if (localProperties.exists()) {
Properties properties = new Properties()
localProperties.withInputStream {
instr -> properties.load(instr)
}
def sdkDir = properties.getProperty('sdk.dir')
def compileSdkVersion = android.compileSdkVersion
Console.println("app compileSdkVersion : " + compileSdkVersion)
def androidJarPath = sdkDir + "/platforms/" + compileSdkVersion + "/data/layoutlib.jar"
return androidJarPath
}
return rootDir
}
每日问题:
- 客户端与服务端进行Socket连接时,如何判断客户端断开连接??
答:服务端判断输入流为NULL时 = = - 巩固回调的实现方式
- TCP套接字和UDP套接字的区别
答: