android 小知识点
小知识点总结
1.
android中MotionEvent.ACTION_CANCEL事件如何被触发?
对于这个问题,android文档的说明很简短,想看明白很难。国外一网页说的还比较详细,写在这里分享给大家:
原文是这样的:
You receive this when a parent takes possession of the motion, for example when the user has dragged enough across a list view or scroll view that it will start scrolling instead of letting you press the buttons inside of it.
意思是这样的:
当你的手指(或者其它)移动屏幕的时候会触发这个事件,比如当你的手指在屏幕上拖动一个listView或者一个ScrollView而不是去按上面的按钮时会触发这个事件。
2.
computeScroll:主要功能是计算拖动的位移量、更新背景、设置要显示的屏幕
(setCurrentScreen(mCurrentScreen);)。
重写computeScroll()的原因
调用startScroll()是不会有滚动效果的,只有在computeScroll()获取滚动情况,做出滚动的响应
computeScroll在父控件执行drawChild时,会调用这个方法
Scroller并不是View,它不负责任何显示工作,只是计算滚动过程。http://i.cnblogs.com/EditPosts.aspx?postid=3816292
你在使用的时候可以用startScroll(int startX, int startY, int dx, int dy)指定起始位置和x/y轴位移
然后调用computeScrollOffset()计算当前位置,返回"true"代表滚动中,返回"false"代表滚动结束
最后调用getCurrX()/getCurrY()获得当前坐标,然后根据这个坐标绘制你的View
3.一些获取坐标的方法:http://i.cnblogs.com/EditPosts.aspx?postid=3816292
getScrollx()是滑过的距离 getCurrX()是当前的坐标。
getX()表示的是widge自身左上角的坐标,
getRawX()表示的是相对于屏幕左上角的的X坐标(注意:这个屏幕左上角是手机手机屏幕左上角,不管activity是否有titleBar或是否全屏幕),getY(),getRawY()一样的道理
视图左侧位置 view.getLeft()
2、视图右侧位置 view.getRight()
3、视图顶部位置 view.getTop();
4、视图底部位置 view.getBottom();
5、 视图宽度 view.getWidth();
6、视图高度 view.getHeight()
MotionEvent类中 getRowX()和 getX()
1、event.getRowX():触摸点相对于屏幕原点的x坐标
2、event.getX(): 触摸点相对于其所在组件原点的x坐标
4.adapter中控制adapter中的数据(当点击listview中的一个button 后修改了adapter的数据,在自己定adapter的参数中在传递修改后adapter,在list.setadapter就可以动态实现点击listView中的button对listView 进行更改)
5.ListView中的点击执行点击(如有两个position位置不同的按钮播放声音,有时候点击一个按钮,两个都播放,这时候可以将播放信息封装到一个自定义控件当中,自定义一个事件监听,且是单例模式就可以解除问题了)
6.继承百度的broadcast 然后动态注册后
(动态注册的broadcast先于静态注册的运行)
然后再动态中的修改 MainAvtivity的红圈圈,
再在静态broadcast中判断文章ID 是否存在,
存在就不保存了,不存在就证明不是在MainActivity界面当中,就直接保存了
7.在ListView自定义控件当中可以根据点击的位置的(getx(),gety())来判断点击的哪一个ListView的litem
1 @Override 2 public boolean onTouchEvent(MotionEvent ev) { 3 4 switch (ev.getAction()) { 5 case MotionEvent.ACTION_DOWN: 6 7 pointToPosition = pointToPosition((int) ev.getX(), (int) ev.getY()); 8 9 } 10 return super.onTouchEvent(ev); 11 } 12 13 }
8.回调接口的一个用法:
例如:在一个自定义控件Button中定义一个回调接口,并包含实现这个接口的方法。在Activity中利用这个接口,实例化该接口。可以对这个Activity中的一些参数进行控制。例子:
这个自定义Button,中有个IAction 的内部接口,并有实现该接口的方法setAction123
1 public class MyButton extends Button { 2 3 IAction iAction; 4 5 public MyButton(Context context) { 6 super(context); 7 } 8 9 public MyButton(Context context, AttributeSet attrs) { 10 super(context, attrs); 11 } 12 13 public MyButton(Context context, AttributeSet attrs, int defStyle) { 14 super(context, attrs, defStyle); 15 } 16 17 public void setAction123(IAction iAction) { 18 this.iAction = iAction; 19 20 } 21 22 @Override 23 public boolean onTouchEvent(MotionEvent event) { 24 switch (event.getAction()) { 25 case MotionEvent.ACTION_DOWN: 26 27 iAction.motion(); 28 break; 29 30 case MotionEvent.ACTION_MOVE: 31 break; 32 33 case MotionEvent.ACTION_UP: 34 break; 35 default: 36 break; 37 38 } 39 40 return super.onTouchEvent(event); 41 } 42 43 interface IAction { 44 45 public void motion(); 46 47 } 48 49 }
在应用了MyButton的Activity中实例进行节后回调:
1 public class EightActivity extends Activity { 2 3 private MyButton btn; 4 private TextView textView; 5 private int i = 0; 6 7 @Override 8 protected void onCreate(Bundle savedInstanceState) { 9 super.onCreate(savedInstanceState); 10 setContentView(R.layout.activity_eight); 11 btn = (MyButton) findViewById(R.id.btn_submit); 12 textView = (TextView) findViewById(R.id.tv_show); 13 btn.setAction123(new MyButton.IAction() { 14 15 @Override 16 public void motion() { 17 i++; 18 } 19 }); 20 21 textView.setOnClickListener(new TextView.OnClickListener() { 22 23 @Override 24 public void onClick(View v) { 25 textView.setText("点击buttoni的值是否改变了--->>" + i); 26 } 27 }); 28 } 29 30 }
上面进行接口的实例化后,当Mybutton触发了Action_Down事件后,会调用IAction接口中的motion方法,然后就会调用在Activity中接口实例化类,就执行了i++,这就用Button中的方法,来设置了Activity中的参数
9.Handler的定义:
Handler的定义:
主要接受子线程发送的数据, 并用此数据配合主线程更新UI.
解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,
进行事件分发, 比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。
如果此时需要一个耗时的操作,例如: 联网读取数据,
或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,,如果你放在主线程中的话,界面会出现假死现象,
如果5秒钟还没有完成的话,,会收到Android系统的一个错误提示 "强制关闭".
这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,,Android主线程是线程不安全的,
也就是说,更新UI只能在主线程中更新,子线程中操作是危险的. 这个时候,Handler就出现了.,来解决这个复杂的问题 ,
由于Handler运行在主线程中(UI线程中), 它与子线程可以通过Message对象来传递数据,
这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据)
, 把这些消息放入主线程队列中,配合主线程进行更新UI。
10.ScrollView 设置滚动条的位置
ScrollView 的滚动条默认置顶,若想设置它的位置,可以使用
mScrollView.smoothScrollTo(x,y)方法,可达到效果。
使用mScrollView.scrollTo(x,y)方法,首次初始化时无效果,
改用 mScrollView.smoothScrollTo(x,y)则成功了!
注意:mScrollView.scrollTo(x,y) 方法不太好用的原因是:据资料说ScrollTo方法设置滚动的位置,将会调用 onScrollChanged(int,int ,int,int)方法,视图被视为无效。
11.事件分发的小点:
当TouchEvent发生时,首先Activity将TouchEvent传递给最顶层的View, TouchEvent最先到达最顶层 view 的 dispatchTouchEvent 。然后由 dispatchTouchEvent 方法进行分发,如果dispatchTouchEvent返回true ,则交给这个view的onTouchEvent处理,如果dispatchTouchEvent返回 false ,则交给这个 view 的 onInterceptTouchEvent方法来决定是否要拦截这个事件,
如果onInterceptTouchEvent返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理,如果onInterceptTouchEvent返回 false ,那么就传递给子 view,由子 view 的 dispatchTouchEvent 再来开始这个事件的分发
12.在用ListView的时候,想获取在当前屏幕中ListView显示内容的firstItem和lastItem的位置,来获取当前屏幕显示的item条数的视乎,要调用
ListView的getLastVisiblePosition()和getFirstVisiblePosition()方法,但是在调用后返回的最后一个位置是-1,第一个位置始终是0。
解决办法是:
1 actualListView.post(new Runnable() { 2 3 @Override 4 public void run() { 5 int visibleCountMums = testListView.getLastVisiblePosition() 6 - testListView.getFirstVisiblePosition(); 7 8 } 9 });
获取的时候加入到消息队列当中去,和HackThirteen 在onCreate()方法中获取View的宽度和高度是想通的。
13.三种更新view的方法:
至此,从《自定义控件其实很简单》系列开始我们已经学会三种对View进行刷新的方式:第一种是在刚开始讲《自定义控件其实很简单1/12》让View作 为Runnable的实现类,在run方法中更新,另一种是我们后来用的比较多的直接在onDraw方法中invalidate(),最后一种呢则是上面 我们讲的Handler来处理绘制逻辑,这三种方法虽说本质一样但是实现方式各不相同且应用场景也不尽相同~第一种更倾向于多种状态进行同时重绘,第二种 局限性很大虽说常见但能实现的功能很弱,第三种可以应用到绝大多数的重绘情景且不受不同状态的影响自由度更大
14.Thread和Runnable的一些区别
- Runnable方式可以避免Thread方式由于java单集成特性带来的缺陷
- Runnable的代码可以被多个线程(Thread实例)共享,适合于多个线程处理同一资源的情况
15.微信扫描二维码下载APK
将APK的下载地址生成二维码,在UC二维码扫描和其他二维码扫描的时候基本上都可以下载APK,但是在微信中去扫描可能就下载不了,有如下几个原因和解决办法:
- 目前的APP基本都支持二维码扫描,发现二维码用微信扫描后打不开,无法跳转,经折腾发现是微信的一种安全机制,需要在下载地址后面加上#mp.weixin.qq.com,就可以跳转到浏览器下载页面。
这个方法只适用于微信5.0之前的,5.0之后的这个方法就失效了。
-
1,首先你在QQ开放平台http://open.qq.com注册,创建你的应用,
2,在你的应用中就可以找到 微下载的url,有pc端的,和手机端的,
3,把pc端的url地址用浏览器打开,然后可以看到立即下载按钮,
4,通过查看源代码,把这个按钮的下载地址找到,
5,把这个下载地址生成二维码,用微信扫一 扫就可以直接通过浏览器下载了。这个方法个人不喜欢,需要上传到腾讯的应用宝平台,审核就要好几天,后期管理起来的话也比较麻烦,不过这个方法肯定是可以的,毕竟微信和腾讯是一家人。
-
综上的一些方法,始终是有些欠妥的。
16.在写自定义HorizontalScrollView的时候,想要动态获取XML文件中子View的,获取的方法在onMeasure()中去获取,
如下代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class MyHorizontalScrollView extends HorizontalScrollView { 2 3 private LinearLayout li; 4 private ViewGroup mMenu; 5 private ViewGroup mContent; 6 private int screenWidth, screenHeight; 7 // menu距离右边的距离 8 private int rightPadding = 100; 9 private boolean once; 10 11 public MyHorizontalScrollView(Context context, AttributeSet attrs, 12 int defStyle) { 13 super(context, attrs, defStyle); 14 } 15 16 public MyHorizontalScrollView(Context context, AttributeSet attrs) { 17 super(context, attrs); 18 init(context); 19 20 } 21 22 public MyHorizontalScrollView(Context context) { 23 super(context); 24 } 25 26 private void init(Context context) { 27 28 System.out.println("init"); 29 // 设置大小 30 screenWidth = new MeasureScreen().getWindowWidth(context); 31 screenHeight = new MeasureScreen().getWindowHeigh(context); 32 // 将dp转换成 px 33 TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, 34 getResources().getDisplayMetrics()); 35 36 } 37 38 @Override 39 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 40 super.onSizeChanged(w, h, oldw, oldh); 41 li = (LinearLayout) getChildAt(0); 42 mMenu = (ViewGroup) li.getChildAt(0); 43 mContent = (ViewGroup) li.getChildAt(1); 44 } 45 46 @Override 47 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 48 System.out.println("onMeasure"); 49 if (!once) { 50 51 // 给menu和content设置宽度 52 mMenu.getLayoutParams().width = screenWidth - rightPadding; 53 mContent.getLayoutParams().width = screenWidth; 54 once = true; 55 } 56 57 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 58 } 59 60 }
17想要实现拖动效果的方法:
- (方法一)像上下拉刷新一样,对HeadView的Padding的距离进行动态设置就了,但不能设置margin, 所以其实是HeadView里面内容在变化,外面还是在原来地方的(对本身有滑动效果的控件警惕一点,)
看原来控件width,height属性是否是wrapcontent,或者使用了0dp + weight,因为这些是按比例来的,所以padding改变内容布局排版可能也会改变的
- (方法二)想要移动View,可以利用Scroller来进行移动
- (方法三)在v4包里多了一个新的类,ViewDragHelper来进行View的拖拽效果