将一些遇到的问题整理起来,记录到这里
ListView
ListView setSelection失效
有时需要在初始状态下自动选中(点击)某一项,比如two-pane的布局,左边是一个list,右边是具体的detail。在测试时发现,使用setSelection并不能满足需求。查看该方法的文档,发现原因如下
If in touch mode, the item will not be selected but it will still be positioned appropriately.
根据android listview setselection 失效解决办法 所说的,进行测试,发现其可以选中,但不能触发onListItemClicked
方法。
最后通过调用performItemClick
方法实现list的某一项自动被点击,如果要表示选中的话,在onListItemClicked
回调里边调用setItemChecked
方法即可。
notifyDataSetChanged不刷新数据的原因
关于这个问题,有些文章已经做了解释,如
将他们总结一下,大致如下:
“总结:在这里的重点就是要注意在开始时传给ListView的list指向不能被改变,需要从始至终指向同一个内存,这样调用notifyDataSetChanged后就能够检测到list的数据变化,从而触发ListView的重新绘制了!”
这个观点有2个错误:
- 不是”数据源指向的对象不能变,必须是同一个对象”,而是Adapter中的数据源是否真正发生了变化,如果只是在Activity里更改了原始的数据源对象的指向,而没有将其重新赋值给Adapter中的数据源对象,这时notifyDataSetChanged肯定不起作用,因为Adapter中的数据(无论是否为空)并没有发生变化。
而根据上面的错误思路给出的解决办法是,将Activity里产生变化的数据源对象的值全部add到Adapter中的数据源对象中(可能还要先clear一下),不能说这种方法是错的,只是强调要明白问题产生的真正原因。 - 说得并不细致,我想他想说的应该是Adapter内部的AdapterDataSetObserver在我们调用notifyDataSetChanged后能够检测到list的数据变化。
不幸的是,真实情况是,它并不能”检测到list的数据变化”,这个Observer只是一个回调,在回调里边它会记录一些状态,最后调用requestLayout()重绘ListView。具体的执行细节,大家可以去看源代码。
WebView
网页自动缩放以适应屏幕大小
解决方法如下:
WebSettings settings = webView.getSettings();
settings.setUseWideViewPort(true);
settings.setLoadWithOverviewMode(true);
参考:Webview auto zoom IN to fit screen
延伸:上面的两个方法到底做了什么,可参考
What do setUseWideViewPort() and setLoadWithOverviewMode() precisely do?
解决网页横向滚动的问题
研究之后发现,自己一开始的想法的错误的,并不是”禁止横向滚动”,如果这样去想,会重点去看WebView的各种设置。但是真正的问题出在html上。
P.S. 网上针对设置WebView的各种解决方案我都试过,但是依然无法解决问题。
造成网页出现横向滚动条的原因是图片宽度过大,超过了屏幕宽度。
了解了这一点,解决问题就很容易了。
首先设置html的viewport的宽度为设备宽度并且禁止缩放
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
其次将所有的<img>
的宽度设置成100%,可以这样设置
<img style="max-width:100%" ...>
Web与JS交互及相关漏洞的解决
关于这一点,我在之前的文章中有专门分析,见android WebView与JS交互小结
body元素被自动加上多余的margin
最近调试时注意到本来应该在html中居中的元素,都会向右向下偏移一些,使用chrome://inspect
远程调试发现,body元素被自动加上了margin,4个方向均为8
原因是android的WebView在渲染html时,当body没有现式地指定margin时,它会自动加上margin: 8
,其实这个问题一开始就存在,但是不知google为何没有修复,可能他们认为这是一个特性而不是一个bug。
了解了问题的原因,解决自然很简单,加入以下css代码即可:
body {
margin: 0;
padding: 0;
}
参考:Remove unwanted White Space in WebView Android , Remove default margin inside WebView
禁止链接跳转到浏览器
默认情况下,WebView载入的网页如果有链接,会跳转至系统的浏览器中。如果需要继续在WebView中显示,则可以自定义WebViewClient
,如下:
webview.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// 不跳到系统浏览器,继续在当前WebView里跳转
view.loadUrl(url);
return true;
}
});
Uncaught TypeError: Cannot call method ‘getItem’ of null at XXX
当使用WebView加载某些网页时,有可能会出现这个错误:
02-07 23:23:59.230: ERROR/Web Console(3721): Uncaught TypeError: Cannot call method 'getItem' of null at http://www.google.com/:342
问题的原因在于加载的网页使用了HTML 5 Dom Storage的API - getItem方法,其中Dom Storage的接口如下:
interface Storage {
readonly attribute unsigned long length;
getter DOMString key(in unsigned long index);
getter any getItem(in DOMString key);
setter creator void setItem(in DOMString key, in any data);
deleter void removeItem(in DOMString key);
void clear();
};
解决方法很简单,只需要开启WebView的Dom Storage即可:
settings.setDomStorageEnabled(true);
WebView.loadData 乱码
有时,使用WebView.loadData时会出现乱码情况,使用网上常见的方法问题照旧
webView.loadData(htmlData, "text/html", "UTF-8");
其实仔细查看一些文档就会发现,最后一个参数encoding指的是传入的data是base64编码还是使用的URL编码,如果值不等于’base64’(包括null),WebView会按照ASCII编码来处理,所以就出现了乱码的情况。
正常情况下,浏览器是根据HTML的meta属性 - Content-Type来选择处理Web页面的编码,目前大部分网站都使用UTF-8来进行编码,如下:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
所以我们可以更改第二个参数的值来解决这个乱码问题:
webView.loadData(htmlData, "text/html; charset=UTF-8", null);
参考:
WebView causing Uncaught TypeError when loading www.google.com
浅谈 HTML5 的 DOM Storage 机制
MISC
安装失败 - INSTALL_FAILED_CONFLICTING_PROVIDER 错误
安装一个app的时候发现了这个问题,调试发现了原因及解决方案,具体详见这篇文章 惠惠购物助手android版3.8.2无法安装的原因及解决方法