上一篇博客传送门:Android常见问题总结(七)
Android全屏方式对比
博主目前发现两种在Android中实现全屏的方案,分别是:
- 通过 View#setSystemUiVisibility 方法,使用 View#SYSTEM_UI_FLAG_FULLSCREEN
- 通过 Window#addFlags 方法,使用 WindowManager.LayoutParams#FLAG_FULLSCREEN
两者在视觉效果上并没有什么不同,其中,View#SYSTEM_UI_FLAG_FULLSCREEN 说明如下:
1 | /** |
主要需要注意的细节有这种方式实现的全屏效果是短暂的(transient),会因为用户的某些操作(如:跳转到其他应用,下拉状态栏等)退出全屏模式
而 WindowManager.LayoutParams#FLAG_FULLSCREEN 说明如下:
1 | /** |
主要需要注意的是跟软键盘弹出的一些交互问题
ListView的Header与Footer设置Visibility为Gone不起作用
常用的ViewGroup,例如LinearLayout,在onMeasure方法内对每个child view执行measure前,会判断child view的visibility是否为gone。如果是gone,则不对这个child view执行measure操作,即这个child view的高度不被计算在linearLayout的高度里面。LinearLayout的measureVertical代码片段
1 | void measureVertical(int widthMeasureSpec, int heightMeasureSpec) { |
view在measure自己时,并不会去判断自己的Visibility是GONE。这个逻辑操作如上述代码所示,是在parent view里面做的。所以当对LinearLayout里面的一个childView设置Visiblility为gone时,这个view不会被measure,最终也不会被显示出来。
在使用ListView时,经常会添加一些headerView、footerView。但是当设置headerView、footerView的visibility为gone时,却发现headerView、footerView虽然没有显示出来,但垂直方向其所占的位置还是被显示出来了,从而出现了空白区域。网上查到的解决办法是:不能直接设置headerView、footerView的Visibility为gone。而是要在HeaderView、FooterView外面包一层parent view(FrameLayout RelativeLayout 都可以),并设置layout_height=“wrap_content”。然后对里面的childView设置visibility为GONE、VISIBLE都会生效。查看源码,情况确实如此。
ListView的onMeasure里面,如果ListView的widthMode、heightMode有一个是unspecified时(应该对应于在XML中没有对listView设置layout_width、layout_height),会调用方法measureScrapChild。如果没有unspecified的情况,则会调用measureHeightOfChildren方法,而此方法内部也会调用measureScrapChild方法。查看measureScrapChild方法:
1 | private void measureScrapChild(View child, int position, int widthMeasureSpec, int heightHint) { |
可以看出,listview在对child view执行measure前,没有判断visibility为gone的情况。
再看看里面的详细逻辑:
- lpHeight>0时,说明在xml或者程序里面设置了一个确定的尺寸,这里没有问题
- else里面,设置mode为UNSPECIFIED,就是让child view自己去决定大小,child view在measure自己时,不会考虑VISIBILITY属性
如果外面包一层parent view(例如LinearLayout),并设置layout_height为wrap_content(按上面的分析,设置match_parent也是可以的),listView会调用调用额外的这个parent view的measure方法。而LinearLayout在measure时,会判断child view的visibility,如果为gone,则会返回0。最终这个额外的parent view返回给list view的尺寸就是0,从而解决了空白区域的问题
ViewGroup没有调用onDraw方法
结论:经测试得知,在没有background背景的情况下,ViewGroup并不会执行onDraw绘制
View#draw相关代码:
1 |
|
可以看到想要执行onDraw,我们都需要变量dirtyOpaque为false(这个变量的具体逻辑没有追踪,大意应该是需要有内容进行绘制吧,所以我们需要添加一个背景)
又或者我们可以重写方法dispatchDraw,这个是一定会执行的
ViewPager获取当前显示的Fragment
最近博主使用到了ViewPager与Fragment这一经典的组合,在此记录一下如何在ViewPager中获取当前显示的Fragment
FragmentManager#findFragmentByTag
当我们使用Viewpager + FragmentPagerAdapter的组合时,加载过的Fragment都会被保留,因此我们可以通过 FragmentManager#findFragmentByTag 来获取相应的 Fragment
根据网上相关的资料以及翻看源码,我们可以使用 FragmentPagerAdapter#makeFragmentName 来获取相应的 tag (该方法是private的,我们可以拷贝出来使用)
具体的源码如下所示:
1 | /** |
PS:FragmentPagerAdapter#makeFragmentName 这个方法是 private 的,直接调用或者copy并不是非常保险,比较好的做法是把整个FragmentPagerAdapter都拷贝出去
重写FragmentPagerAdapter#setPrimaryItem
这个方法在每次viewpager滑动后都会被调用,而object参数就是显示的Fragment
我们可以通过重写该方法,把object存到我们的成员变量中随时读取
不过这种方式有一个缺陷,FragmentPagerAdapter#setPrimaryItem是在 viewpager的滑动监听执行完后才会调用的,因此我们在滑动监听中读取的当前Fragment是不正确的
Android 7.0 https 抓包问题
当我们使用Fiddler或者Charles等工具,想要在Android手机上抓包https请求时,我们需要把他们的证书安装到手机上,让手机能与抓包工具正确建立https连接
然而这个方式在Android 7.0 以上的版本却失效了,博主亲测像往常安装证书之后还是不能抓包https请求
具体的原因可以参考官方的文档:
https://developer.android.com/training/articles/security-config.html
简单来说,就是因为官方的检验机制变得更加严格了,虽然我们安装了相应的用户证书,但应用仍然是不信任我们的证书的
要解决这个问题,根据官方文档:
- 我们需要把我们的证书放置/res/raw目录下
- 我们需要在/res/xml新建一个network_security_config.xml,来配置证书
- 在AndroidManifest.xml上应用此配置
network_security_config.xml:
1 | <?xml version="1.0" encoding="utf-8"?> |
AndroidManifest.xml:
1 | <application |