首页 存档 技术 查看内容

干货 | Android 开发中的10个大坑和解决的小技巧!

2018-3-30 13:00 |来自: 互联网 323 0

摘要: 1、android:clipToPadding 意思是控件的绘制区域是否在padding里面。默认为true。如果你设置了此属性值为false,就能实现一个在布局上事半功陪的效果。先看一个效果图。 上图中的ListView顶部默认有一个间距,向 ...

1、android:clipToPadding


意思是控件的绘制区域是否在padding里面。默认为true。如果你设置了此属性值为false,就能实现一个在布局上事半功陪的效果。先看一个效果图。



上图中的ListView顶部默认有一个间距,向上滑动后,间距消失,如下图所示。



如果使用margin或padding,都不能实现这个效果。加一个headerView又显得大材小用,而且过于麻烦。此处的clipToPadding配合paddingTop效果就刚刚好。


同样,还有另外一个属性也很神奇:android:clipChildren,具体请参考:【Android】神奇的android:clipChildren属性(http://www.cnblogs.com/over140/p/3508335.html)


2、match_parent和wrap_content


按理说这两个属性一目了然,一个是填充布局空间适应父控件,一个是适应自身内容大小。但如果在列表如ListView中,用错了问题就大了。ListView中的getView方法需要计算列表条目,那就必然需要确定ListView的高度,onMesure才能做测量。如果指定了wrap_content,就等于告诉系统,如果我有一万个条目,你都帮我计算显示出来,然后系统按照你的要求就new了一万个对象出来。那你不悲剧了?先看一个图。



假设现在ListView有8条数据,match_parent需要new出7个对象,而wrap_content则需要8个。这里涉及到View的重用,就不多探讨了。所以这两个属性的设置将决定getView的调用次数。


由此再延伸出另外一个问题:getView被多次调用。


什么叫多次调用?比如position=0它可能调用了几次。看似很诡异吧。GridView和ListView都有可能出现,说不定这个祸首就是wrap_content。说到底是View的布局出现了问题。如果嵌套的View过于复杂,解决方案可以是通过代码测量列表所需要的高度,或者在getView中使用一个小技巧:parent.getChildCount == position


@Override

public View getView(int position, View convertView, ViewGroup parent) {

if (parent.getChildCount() == position) {

// does things here

}

return convertView;

}


3、IllegalArgumentException: pointerIndex out of range


出现这个Bug的场景还是很无语的。一开始我用ViewPager PhotoView(一个开源控件)显示图片,在多点触控放大缩小时就出现了这个问题。一开始我怀疑是PhotoView的bug,找了半天无果。要命的是不知如何try,老是crash。后来才知道是android遗留下来的bug,源码里没对pointer index做检查。改源码重新编译不太可能吧。明知有exception,又不能从根本上解决,如果不让它crash,那就只能try-catch了。解决办法是:自定义一个ViewPager并继承ViewPager。请看以下代码:


/**

* 自定义封装android.support.v4.view.ViewPager,重写onInterceptTouchEvent事件,捕获系统级别异常

*/

public class CustomViewPager extends ViewPager {

public CustomViewPager(Context context) {

this(context, null);

}

public CustomViewPager(Context context, AttributeSet attrs) {

super(context, attrs);

}

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

try {

return super.onInterceptTouchEvent(ev);

} catch (IllegalArgumentException e) {

LogUtil.e(e);

} catch (ArrayIndexOutOfBound**ception e) {

LogUtil.e(e);

}

return false;

}

}


把用到ViewPager的布局文件,替换成CustomViewPager就OK了。


4、ListView中item点击事件无响应


listView的Item点击事件突然无响应,问题一般是在listView中加入了button、checkbox等控件后出现的。这个问题是聚焦冲突造成的。在android里面,点击屏幕之后,点击事件会根据你的布局来进行分配的,当你的listView里面增加了button之后,点击事件第一优先分配给你listView里面的button。所以你的点击Item就失效了,这个时候你就要根据你的需求,是给你的item的最外层layout设置点击事件,还是给你的某个布局元素添加点击事件了。


解决办法:在ListView的根控件中设置(若根控件是LinearLayout, 则在LinearLayout中加入以下属性设置)descendantFocusability属性。


android:descendantFocusability="blocksDescendants"


官方文档也是这样说明。




5、getSupportFragmentManager()和getChildFragmentManager()


有一个需求,Fragment需要嵌套3个Fragment。基本上可以想到用ViewPager实现。开始代码是这样写的:


mViewPager.setAdapter(new CustomizeFragmentPagerAdapter(getActivity().getSupportFragmentManager(), subFragmentList));


导致的问题是嵌套的Fragment有时会莫名其妙不显示。开始根本不知道问题出现在哪,当你不知道问题的原因时,去解决这个问题显然比较麻烦。经过一次又一次的寻寻觅觅,终于在stackoverflow上看到了同样的提问。说是用getChildFragmentManager()就可以了。真是这么神奇!


mViewPager.setAdapter(new CustomizeFragmentPagerAdapter(getChildFragmentManager, subFragmentList));


让我们看一下这两个有什么区别。首先是getSupportFragmentManager(或者getFragmentManager)的说明:


声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除


路过

雷人

握手

鲜花

鸡蛋

相关分类

返回顶部