安卓的画布如何实现安卓开发 自动更新新

【总结】移动应用界面设计的尺寸设置及规范 - 推酷
【总结】移动应用界面设计的尺寸设置及规范
刚接触移动应用的界面设计,最先跳入脑海的疑问是:画布尺寸设计多大(特别是Android)、图标和字体大小怎么定、需要设计多套设计稿么、如何切图以配合开发的实现?
本篇将结合iOS和android官方的设计规范、搜集的资料以及工作中的摸索,来分享移动应用界面设计中的尺寸规范等问题,希望能给移动端的新手设计师些许指引。若有不当之处,欢迎斧正。
一、android篇
1、android分辨率
Android的多分辨率,一向是设计师和开发者非常头疼的事儿。尽管如此,对于多分辨造成的复杂问题,也是大家要优先解决的。Android支持多种不同的dpi模式:ldpi 、mdpi 、hdpi 、xhdpi 、xxhdpi 、xxxhdpi
注意,ppi、dpi 是密度单位,不是度量单位 :
* ppi (pixels per inch):图像分辨率 (在图像中,每英寸所包含的像素数目)
* dpi (dots per inch): 打印分辨率 (每英寸所能打印的点数,即打印精度)
dpi主要应用于输出,重点是打印设备上;ppi对于设计师应该比较熟悉,photoshop画布的分辨率常设置为72像素/英寸,这个单位其实就是ppi 。尽管概念不同,但是对于移动设备的显示屏,可以看作ppi=dpi 。
ppi的运算方式是:PPI = √(长度像素数² + 宽度像素数²) / 屏幕对角线英寸数。即:长、宽各自平方之和的开方,再除以屏幕对角线的英寸数。
以iphone5为例,其ppi=√(1136px² + 640px²)/4 in=326ppi(视网膜Retina屏)
对于android手机,一个不确切的分法是,720 x 1280 的手机很可能接近 320 dpi (xhdpi模式),480 x 800 的手机很可能接近 240 dpi (hdpi模式),而320 x 480 的手机则很接近 160 dpi(mdpi模式)。
来自友盟指数2014年3月份的数据(
480 x 800的手机占比最高为31.9%,720 x 1280的手机占比为16.5%位居第二,而240 x 320的手机占比最少为1.0% 。xxdhpi模式的高分辨率1080 x 1920手机占比也越来越高,目前为6.1% 。
2、单位换算方法
android开发中,文字大小的单位是sp,非文字的尺寸单位用dp,但是我们在设计稿用的单位是px。这些单位如何换算,是设计师、开发者需要了解的关键。
* dp:Density-independent pixels,以160PPI屏幕为标准,则1dp=1px。dp和px的换算公式 :dp*ppi/160 = px。对于320ppi的屏幕,1dp x 320ppi/160 = 2px。
* sp:Scale-independent pixels,它是安卓的字体单位,以160PPI屏幕为标准,当字体大小为 100%时, 1sp=1px。sp 与 px 的换算公式:sp*ppi/160 = px。对于320ppi的屏幕,1sp x 320ppi/160 = 2px。
简单理解的话,px(像素)是我们UI设计师在PS里使用的,同时也是手机屏幕上所显示的,dp是开发写layout的时候使用的尺寸单位。
为什么要把sp和dp代替px?
原因是他们不会因为ppi的变化而变化,在相同物理尺寸和不同ppi下,他们呈现的高度大小是相同。也就是说更接近物理呈现,而px则不行。
根据单位换算方法,可总结出:
当运行在mdpi下时,1dp=1px :也就是说设计师在PS里定义一个item高48px,开发就会定义该item高48dp ;
当运行在hdpi模式下时,1dp=1.5px :也就是说设计师在PS里定义一个item高72px,开发就会定义该item高48dp ;
当运行在xhdpi模式下时,1dp=2px :也就是说设计师在PS里定义一个item高96px,开发就会定义该item高48dp ;
当你的app需要适配多个dpi模式的时候,请参考图1的比例进行换算 。
3、设计稿基本元素的尺寸设置
为了适应多分辨率的手机,理想的方式是为每种分辨率做一套设计稿,包括所用到的icon、设计稿标注等。但在实际开发中,这种方法耗时耗力。所以通常会选择折中的方法。
在标准基础上(比如xhdpi)开始,然后放大或缩小,以适应到其他尺寸。不足之处是,对于更高分辨率的手机,图标被放大后会导致质量不高。
以最高分辨率为基准设计,然后缩小适应到所需的小分辨率上。缺点是,图标等若都最大尺寸,加载时速度慢且耗费流量较多,对于小分辨率的用户也不够好。
结合友盟的分辨率占比数据、也为了方便换算到android开发中的尺寸单位,
推荐设计稿的画布尺寸选用 720X1280 ,分辨率仍旧为72ppi(像素/英寸)
在android规范中对于导航栏、工具栏等的尺寸没有明确的规定。但根据48dp原则,以及一些主流的android应用的截图分析,总结一下尺寸要求:
状态栏高度:
导航栏、操作栏高度:
96 px=48dp x 2
主菜单栏高度:
内容区域高度:
1038 px (-96=1038)
Android最近出的手机都几乎去掉了实体键,把功能键移到了屏幕中,高度也和菜单栏一样为:96 px
4、图标和字体大小(来自官方规范文档)
a、启动图标(home页或app列表页)
整体大小为48 x 48 dp
b、操作栏图标,代表用户在app中可以使用到的最重要的图标
整体大小为32 x 32 dp ,图形实际区域为 24 x 24 dp
c、小图标/场景图标,提供操作或特定项目的状态。
比如gmail app的星型标记、一些内容展开收起用到的向下向上的图标等。整体大小为16 x 16 dp ,图形实际区域为 12 x 12 dp 。
d、通知图标
如果app有通知,要提供一个有新通知时显示在状态栏的通知图标。整体大小为24 x 24 dp ,图形实际区域为 22 x 22 dp 。
注:android规范提供的尺寸单位是dp,若设计稿尺寸设为720 x 1280 ,图标大小需在规范要求的尺寸数字上乘以2。比如操作栏图标32 x 32 dp ,则设计稿上应该是64 x 64 px 。
e、字体大小
Android规范中的要求如下:
前面提到Android开发中的字号单位是sp,而换算关系是 sp*ppi/160 = px 。所以720 x 1280尺寸的设计稿上,字体大小可选择为 24px 、28px 、32px 、36px ,主要根据文字的重要程度来选择,特殊情况下也可能选择更大或更小的字体。
f、其他尺寸要求
通常把48dp作为可触摸的UI元件的标准。
为什么要用48dp呢?一般来说,48dp转化为一个物理尺寸约9毫米。通常建议目标大小为7-10毫米,以方便用户手指能准确并且舒适触摸目标区域。
如果你设计的元素高和宽至少48dp,你就可以保证:
(1)触摸目标绝不会比建议的最低目标(7mm)小,无论在什么屏幕上显示。
(2)在整体信息密度和触摸目标大小之间取得了一个很好的平衡。
另外,每个UI元素之间的空白通常是8dp 。
5、一点疑问供探讨
在720 x 1280 px 的设计稿上,有两个按钮(比如登录、注册)并排一行放置,尺寸均为320 x 80 px ,换算为android开发单位就是 160 x 40 dp 。
根据前面的计算方式,如果显示在 480 x 800的手机上,反过来换算为px尺寸就是 240 x 60 px ,此时两个按钮排放在一行,刚好是480px=屏幕横向尺寸,铺满了整行,显然显示效果并不合适。
如果遇到这种情况,如何做呢?咨询android开发工程师,得到的答案是可能需要做自适应处理,不过目前他们都是写固定的dp值。所以我想设计师是否也需要考虑——在基准分辨率下设置的尺寸换算在其他分辨率下,是否也能优雅显示?
iPhone 界面尺寸:320&480、640&960、640&1136
iPad 界面尺寸:48&1536
(以上单位都是像素,至于分辨率一般网页UI和移动UI基本上都只要 72 ppi)
2、单位换算px、pt
这里需要先区分pt、px,pt(磅值)是物理长度单位,指的是72分之一英寸。手机上看来同一大小的字磅值是一样的,但是换算成不同分辨率手机的字号px值不一样。(
px=pt*ppi/72
iPhone在出retina屏(也就是4S)之前的屏幕像素是320x480px,屏幕密度是163ppi,4S的屏幕像素是640x960px,屏幕密度是326ppi,翻了一倍。iPhone5的ppi没有变化,兼容性方面要增加类似首屏画面等程序上的判断。
在iPhone界面上元素的定位、尺寸是通过一个单位point,而非px,屏幕上固定有320x480pt,retina屏两倍的分辨率改变的只是pt和px之间的比例而已,这样就能实现不改变程序,只上传两套图片就兼容两个分辨率。
在设计的时候并不是每个尺寸都要做一套,尺寸按自己的手机尺寸来设计,比较方便预览效果,一般用 640&960 或者 640&1136 的尺寸设计。其中设计稿的画布分辨率设为默认的72ppi(此时1px=1pt ),所以设计师可以统一采用px为单位。
开发拿到设计稿时,将上面标注的以px为单位的字号大小、图像尺寸除以2,就是非retina屏上的pt值,这样在retina屏上也可以根据此pt值换算对应的px大小,以确保不同的分辨率下有合适的效果。
3、基本元素的尺寸设置
iPhone的APP界面一般由四个元素组成,分别是:状态栏、导航栏、主菜单栏以及中间的内容区域。
这里取用 640&960 的尺寸设计,那我们就说说在这个尺寸下这些元素的尺寸:
就是我们经常说的信号、运营商、电量等显示手机状态的区域,其高度为:40 px
显示当前界面的名称,包含相应的功能或者页面间跳转的按钮,其高度为:88 px
主菜单栏:
类似于页面的主菜单,提供整个应用的分类内容的快速跳转,其高度为:98 px
内容区域:
展示应用提供的相应内容,整个应用中布局变更最为频繁的,其高度为:734 px=960-40-88-98
以上尺寸适用于 iPhone 4、4S,iPhone5/5s 的 640&11136 的尺寸,其实就是中间的内容区域高度增加到:910 px,其他尺寸也同上。
4、常用图像、图标大小(来自官方规范文档)
单位:像素
5、字体大小
iOS交互设计规范文档上,对字体大小没有做严格的数值规定,只提供了一些指导原则:
单位:点pt
- 即便用户选择了最小文字大小,文字也不应小于 22 点。作为对照,正文样式在大字号下使用 34 点字体大小作为默认文字大小设置。
- 通常来说,每一档文字大小设置的字体大小和行间距的差异是 2 点。例外情况是两个标题样式,在最小、小和中等设置时都使用相同字体大小、行间距和字间距。
- 在最小的三种文字大小中,字间距相对宽阔;在最大的三种文字大小中,字间距相对紧密。
- 标题和正文样式使用一样的字体大小。为了将其和正文样式区分,标题样式使用加粗效果。
- 导航控制器中的文字使用和大号的正文样式文字大小(明确来说,是 34 点)。
- 文本通常使用常规体和中等大小,而不是用细体和粗体。
百度用户体验做过的一个小调查:
单位:像素px
还有个方法就是找你觉得好的APP应用,手机截图后放进PS自己对比调节字体大小。
三、如果android、iOS同时开发,设计稿尺寸设置多大呢?
可采用iPhone的尺寸 640 x 960 px设计,用于Android开发时,将其分辨率看作320ppi(xhdpi模式),再采用上文的方法进行换算、设置尺寸。
【附】参考资料
已发表评论数()
&&登&&&陆&&
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见该栏目下:
android canvas 画布
来源:网络整理 | 编辑:年轻网
android canvas 画布,有需要的朋友可以参考下。
画布对于游戏界面的绘制以及自定义界面有着非常大的作用,可以实现书写文字,添加图片等操作,首先在xml布局文件中书写一个布局文件然后引入该view布局然后在view类中进行绘制即可。
1.书写xml文件
&com.example.study2d.GameView
android:layout_width=&200dp&
android:layout_height=&200dp&/&
2。定义视图类
public class GameView extends View {
private P//声明一个画笔,通过该画笔实现文字,矢量图的绘制等
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint(Paint.ANTI_ALIAS_FLAG); //对画笔进行初始设置
// TODO Auto-generated constructor stub
protected void onDraw(Canvas canvas) {
paint.setColor(Color.YELLOW); //设置画笔颜色
canvas.drawRect(0, 0, getWidth(), getHeight(), paint); //用上述声明的画笔进行绘制矩形
paint.setColor(Color.BLUE);
paint.setTextSize(20);
String text = &Hello View&;
canvas.drawText(text, 0, getHeight() / 2, paint);//通过上面的画笔来进写字
3.位图的绘制
首先我们需要先获取位图资源
bitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.icon0)).getBitmap()通过该函数我们可以获得位图资源,对于位图资源的加载,加载图片一般要放在程序的最开始,以此来防止这种加载迟缓导致程序启动慢的问题。
获得图片之后我们就可以开始对其进行绘制了
canvas.drawBitmap(bitmap, 100, 100,null);,第一个参数是我们所获得的图片的名字,然后是图片的位置坐标,最后一个参数是画笔的名字,对于画笔来说,我们在绘制位图的时候一般是不需要画笔来进行绘制的。
canvas.scale(0.5f,0.5f,bitmap1.getWidth()/2,bitmap1.getHeight()/2);通过该函数我们可以实现对于获得的位图的大小的绘制,后两个参数就是获得位图的大小的绘制。
对于视图,我们可以通过方法invalidate来实现,通过在画布中设置上一下参数来实现根据相应的要求实现实时的更新。
更多关于“”的文章
[转]让你的Android开发Eclipse环( 01:01)
有需求,就总有人去填补,这个世( 01:00)
年轻网资讯
简介:年轻,80后,90后,年轻人的地盘!年轻网,让您更健康、更美丽!
android canvas 画布
[转]让你的Android开发Ecl
有需求,就总有人去填补,
  设置两个按钮事件:/**写入偏好设置**/publ...
【】&android canvas 画布
本周精彩图文Android开发笔记 - 技术在于积累 - ITeye技术网站
1:Android Permission denied(不允许连接Socket) 错误
原因是: 需要访问到网络,所以,在AndroidManifest.xml中,需要进行如下配置: &uses-permission android:name="android.permission.INTERNET" /&
2:ListView滚动变黑解决方法
ListView增加一个属性android:cacheColorHint="#"
3:Item用自己的背景盖住了Selector光标
ListView增加一个属性:android:drawSelectorOnTop="true"这样光标就会跑到Item上面的图层
4:在利用Tab标签(自定义按钮)实现不同Activity切换,不同Activity均已经设置了模式为singleTask或singleInstance时,但是每次点击Tab标签中的特定Activity时,每次都还是会执行onCreate方法,原因如下:1:管理Tab标签(实现Activity切换的Tab标签)的容器(Activity)必须继承ActivityGroup
2:Activity设置的启动模式必须为singleTask或singleInstance3:LocalActivityManager中的startActivity方法对于的Activity对应的ID,必须为需要跳转过去的Activity名称,否则失效。
4:存放tab标签(自定义按钮)对应的layout中必须有一个FrameLayout放置子activity。
5:模拟器提示访问网络出现如下异常:
java.net.UnknownHostException: Host is unresolved
原因是模拟器没有开通代理访问网络。
6:开发过程中,当listview控件中有button、checkbox等控件时,可能是由于这些子控件中获取到了focus事件,导致listview中onItemClick事件失效,只需要按如下方式处理即可:
1)每一个控件重新设置focusable属性
2)Item Layout的根控件设置其android:descendantFocusability=”blocksDescendant”即可
7:开发自定义控件步骤
1)创建res/values/***.xml资源文件(里面的内容节点declare-styleable,子节点中的内容为该自定义控件的属性字段)
2)创建res/layout/***.xml布局文件(对应主的布局中定义声明自定义控件xmlns:custom ="")
custom可以随意编写;com.test.jzh则需要依据自定义控件所在package路径而定,一定为该工程的包名。
3)编写自定义控件的实体操作类,完成控件所展示的界面、功能操作等。
开发自定义控件需要注意的事情:
1:自定义控件需要重写android系统控件的如下构造函数
View(Context context)
View(Context context, AttributeSet attrs)
同时构造函数也可以做些其他的事情
2:自定义控件也可以在初始化的时候构造从Layout布局中完成初始化动作
3:自定义空时如果需要实现控件布局飞翻转、移动位置(非正常的控件)需求时,可以借助于重写控件的onDraw方法,让Canvas画布做相应的处理,如:
Canvas.rotate(-90);---旋转
Canvas.translate(-getHeight(),0);---移动
1:运行时 在logcat中看到虚拟机找不到CustomeView这个类。最后发现是要在xml中加上整个package name(如红色所示)(xmlns:app="/apk/res/com.custome"),因为自定义的派生类不再java虚拟机的classpath中
2:在setContentView中inflate xml时,没有把id值传给CustomeView的实例,最后发现很多在xml中的属性都会通过View的构造函数 View(Context context, AttributeSet attr)中的第二个参数传递进来的,而我的派生类只提供了 CustomeView(Context context)的够咱函数,导致id值无法传入
8:Listview中性能优化方案(需要加载图片)
1)将图片以文件(文件名称编号唯一)的形式缓存到手机中、后面每次列表加载时先判断文件是否存在,存在则直接读取出来显示;否则直接网络请求,再写入缓存中。
2)Adapte设置getview可以用---convertView = LayoutInflater.from(context).inflate(R.layout.main, null, false);也可以用自定义了继承自LinearLayout的MBlogListItemView,如:
public class TestItemLayout extends LinearLayout {
public TextView text1;
public ImageView icon1;
public TextView text2;
public ImageView icon2;
public TestItemLayout(Context context) {
super(context);
((LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
R.layout.list_item_icon_text, this);
icon1 = (ImageView) findViewById(R.id.icon1);
text1 = (TextView) findViewById(R.id.text1);
icon2 = (ImageView) findViewById(R.id.icon2);
text2 = (TextView) findViewById(R.id.text2);
10:输入框中如何出现下一页。
在edittext控件中增加android:singleLine="true"即可。
11:将listview默认选中的背景色去除。
android:cacheColorHint="@null"android:listSelector="#"
12:listview中包含图片等外部数据时,如果现实内容滚动比较卡,原因可能是加载listview是主UI和Listview中的图片等加载界面混淆在一起。
解决方法:设置是否滚动标志,加载getView时以此作为依据,判断是否加载图片。
13:如果给android程序做压力测试,答案是monkey。
adb shell monkey -p com.huawei.basic.android -v 1000
14:工程如果不会自动生成gen文件夹或者报“Unable to resolve target android-9”,解决方法如下
工程-属性-android-选择合适的Project Build Target.
15:"Cannot reduce the visibility of the inherited method from",解决方法如下:
1)选择合适的android platform版本。
2)选择system lib中的layoutlib和android。
16:各个Activity通过Intent传递数据,是通过Bundle携带的,需要判断好Bundle。
17:android开发过程中如果遇见java是提供该类或者其他的,但是就是报(**** is not visible),原因就是sun的jar包和android冲突所致
18:android在实现listview中图片统一风格的方案有两种。1:通过程序做统一处理,但是消耗性能;2:通过在image底部或者上面再罩一个透明的图片,效果非常好。
19:ERROR: Application requires API version 10. Device API version is 8
解决方法:
1:在AndroidManifest.xml 里,
&uses-sdk android:minSdkVersion="8" /& 找到這一行,這行是表示要執行這個應用程式所需要的最低版本,把數字改成模擬器上面的版本。
2:在default.properties 里
target=android-8
把target改为要运行模拟器的版本就OK了。
20:如果工程出现gen文件夹不自动生成、case expressions must be constant expressions、Cannot reduce the visibility of the inherited method from Activity等问题,原因可能是eclipse默认的workspace有问题,可以考虑重新建立一个。
21:Canvas、Paint、SurfaceView这三者之间的关系,Canvas是一个画布,而Paint是一个工具,画布中需要画东西必须通过Paint去画,而SurfaceView是一个显示画布的控件,即最后Canvas画布中的内容都是需要通过SurfaceView去呈现在Android界面中,样例:
GameView gv= new GameView(this);=====surfaceViewLinearLayout
hotWordsContainer = (LinearLayout) findViewById(R.id.linearLayout1);hotWordsContainer.addView(gv);
22:Adapter\LayoutInflater
1)Adapter具体见下图
2)LayoutInflaterInflater英文意思是膨胀,在中应该是扩展的意思吧。 LayoutInflater的作用类似于 findViewById(),不同点是LayoutInflater是用来找layout文件夹下的xml布局文件,并且实例化!而 findViewById()是找具体某一个xml下的具体 widget控件(如:Button,TextView等)。
LayoutInflater inflater = LayoutInflater.from(this);
View view=inflater.inflate(R.layout.ID, null);
或者干脆并成一句:
View view=LayoutInflater.from(this).inflate(R.layout.ID, null);
23:Handler的定义和特点
定义: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发, 比如说, 你要是点击一个 Button, Android会分发事件到Button上,来响应你的操作。
如果此时需要一个耗时的操作,例如: 联网读取数据,或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,会收到Android系统的一个错误提示
"强制关闭".
这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,Android主线程是线程不安全的,也就是说,更新UI只能在主线程中更新,子线程中操作是危险的. 这个时候,Handler就出现了来解决这个复杂的问题,由于Handler运行在主线程中(UI线程中),它与子线程可以通过Message对象来传递数据,这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据)
, 把这些消息放入主线程队列中,配合主线程进行更新UI。
特定:handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),它有两个作用: (1):
安排消息或Runnable 在某个主线程中某个地方执行, (2)安排一个动作在不同的线程中执行。
24:android手机root权限破解
使用SuperOneClick工具即可,但是需要安装net framework。
25:在listview底部增加控件view时,不显示的原因是需要先将lv.addFootView(v)放在setAdapter之前就可解决.
26:程序在设计时需要统一管理Handler,提供一个内存块Map,并提供常用的注册、去注册、发送消息等常用的功能。
27:Listview滚动事件
scrollState有三种状态,分别是
开始滚动(SCROLL_STATE_FLING )
正在滚动(SCROLL_STATE_TOUCH_SCROLL ),
已经停止(SCROLL_STATE_IDLE ),对于滚动事件的处理,很有必要知道
28:adb常用命令
adb shell如果在操作命令是出现“permission denied”,则提示只需要执行su命令即可。
adb server is out of date.
killing...ADB server didn't ACK* failed to start daemon *error:原因:豌豆荚之类的软件开启了USB调试开关,关闭即可。
如果操作android手机时,执行名称出现“read-only file system”mount -o remount rw /
修改权限----chmod 777 文件夹或者文件
29:在使用listview时,如果需要更新listview中的现实的数据时,只需要更新listview绑定的Adapter中的list内存数据,然后再发送adapter.adapter.notifyDataSetChanged();
30:Only the original thread that created a view hierarchy can touch its views.原因:在Activity中使用线程更新UI时,由于单独新建的线程中直接操作了UI内容,导致上面的问题,解决方式是将更新UI放置进handle去处理。
31:sqlite分页语句
select * from table_name order by last_message_date desc Limit 10 offset nBaseRow---从第nBaseRow行(基于0的索引)(包括该行)开始,取其后的10 条记录。
32:android源码下载地址汇总:
33:android好的设计需要考虑1:Handle需要做一个统一管理。2:SharedPreference也需要做一个统一管理
34:Activity中如果listview不执行滑动事件。
原因可能就是没有注册。像这样:listView.setOnScrollListener(this);
35:使用SQLiteOpenHelper对数据库进行版本管理
SQLiteOpenHelper类提供了两个重要的方法,分别是onCreate(SQLiteDatabase db)和onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion),前者用于初次使用软件时生成数据库表,后者用于升级软件时更新数据库表结构。当调用SQLiteOpenHelper的getWritableDatabase()或者getReadableDatabase()方法获取用于操作数据库的SQLiteDatabase实例的时候,如果数据库不存在,Android系统会自动生成一个数据库,接着调用onCreate()方法,onCreate()方法在初次生成数据库时才会被调用,在onCreate()方法里可以生成数据库表结构及添加一些应用使用到的初始化数据。onUpgrade()方法在数据库的版本发生变化时会被调用,一般在软件升级时才需改变版本号,而数据库的版本是由程序员控制的,假设数据库现在的版本是1,由于业务的变更,修改了数据库表结构,这时候就需要升级软件,升级软件时希望更新用户手机里的数据库表结构,为了实现这一目的,可以把原来的数据库版本设置为2(有同学问设置为3行不行?当然可以,如果你愿意,设置为100也行),并且在onUpgrade()方法里面实现表结构的更新。当软件的版本升级次数比较多,这时在onUpgrade()方法里面可以根据原版号和目标版本号进行判断,然后作出相应的表结构及数据更新。
36:Listview使用总结
1---listview在实现分页时,如果每次分页加载数据后滚动条都运行至最顶部,原因可能:每次重新adapter时都重新了new了。2---调试Android程序时,如果新的代码更新了数据库,但是安装调试到手机里面的程序,还是老的,解决方法:删除手机上面该应用的数据即可,重新安装。
1:进行上拉分页时,原理:1)先定义好一个底部加载layout;2)Activity初始化时将1)控件加载至listview中。3)如果触发分页操作,则加载数据,如果无数据,则直接从listview中remove即可。2:进行下拉分页时,list在增加Header、Footer时,在已经setAdapter时,是不能再AddHeader或者AddFooter的,否则出现如下异常:Cannot add header view to list -- setAdapter has already been called.
提示我已经设置了适配器,原来addHeaderView(View v)方法 只能在父控件 setAdapter之前调用!
仔细想想也很容易解释,addHeaderView是为list加入 头视图,而setAdapter是为控件匹配内容。哪有先匹配了内容,再插入view的道理,皮之不存毛将焉附.
37:AsyncTask总结
AsyncTask的执行分为四个步骤,每一步都对应一个回调方法,这些方法不应该由应用程序调用,开发者需要做的就是实现这些方法。   1) 子类化AsyncTask   2) 实现AsyncTask中定义的下面一个或几个方法   
onPreExecute(), 该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条。   
doInBackground(Params...), 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。   
onProgressUpdate(Progress...),在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。   
onPostExecute(Result), 在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,后台的计算结果将通过该方法传递到UI thread.
为了正确的使用AsyncTask类,以下是几条必须遵守的准则:   1) Task的实例必须在UI thread中创建   2) execute方法必须在UI thread中调用   3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法   4) 该task只能被执行一次,否则多次调用时将会出现异常
38:Android中处理崩溃异常
要实现这一机制,不过首先我们还是来了解以下两个类:
android.app.Application和java.lang.Thread.UncaughtExceptionHandler。
Application:用来管理应用程序的全局状态。在应用程序启动时Application会首先创建,然后才会根据情况(Intent)来启动相应的Activity和Service。本示例中将在自定义加强版的Application中注册未捕获异常处理器。
Thread.UncaughtExceptionHandler:线程未捕获异常处理器,用来处理未捕获异常。如果程序出现了未捕获异常,默认会弹出系统中强制关闭对话框。我们需要实现此接口,并注册为程序中默认未捕获异常处理。这样当未捕获异常发生时,就可以做一些个性化的异常处理操作。
39:Caused by: java.lang.ClassNotFoundException: ****.MainActivity in loader dalvik.system.PathClassLoader
原因:1、AndroidManifest.xml配置文件启动Activity配置问题2、重新clean工程,去除历史垃圾数据。
40:android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1(数据库查询得到的cursor里面只有1个结果,你却查找第-1个)
解决方法:
1:检查遍历是否时,是否先执行了cursor.moveToFirst()。
2:检查遍历cursor索引是否正确。
41:当发现sqlist developer 工具查询和Android手机执行的结果不一致时,原因可能是:
1):SQL本身的问题。
2):查询URI指定的数据库不一致
String sql = " canonical_addresses.address, threads._id from canonical_addresses, threads where threads.recipient_ids = canonical_addresses._id --";
cursor = this.mContext.getContentResolver().query(
Uri.parse(FusionField.SMS_PHONE_URI), new String[]{sql}, null, null,null);
42:Android如何做到多个版本(资源文件不同、apk包名不同)公用一份逻辑方案1:新建一个工程,里面包含多个版本的工程目录,同时核心的业务逻辑也是一个单独的工程。2:不同版本公用引用同一个核心的业务逻辑工程,确保本版本可以编译。3:由于不同版本资源不同,且不同版本的包结构也不同,故只需要在编译版本时,将核心模块的工程中设计到res的R.java文件指定的import路径修改即可。
43:其实apk程序的包名不一定需要和工程的包结构一致。
44:导出android系统的短信库(需要获取android用户的root权限)
# cd /data/data/com.android.providers.telephonycd /data/data/com.android.providers.telephony# lslsapp_partsdatabaseslibshared_prefs# cd databasecd databasecd: can't cd to database# cd databasescd databases# lslstelephony.dbmmssms.db# chmod 777 mmssms.dbchmod 777 mmssms.db# cd ..cd ..# chmod 777 databaseschmod 777 databases# cd ..cd ..# chmod 777 com.android.providers.telephonychmod 777 com.android.providers.telephony# cd ..cd ..# chmod 777 datachmod 777 data# cd ..cd ..# chmod 777 datachmod 777 data#
45:Activity类创建后,它里面的声明的对象实例等都和它息息相关,即Activity销毁,则里面的所有实例也就销毁了。
46:android service
Service是android 系统中的一种组件,它跟Activity的级别差不多,但是他不能自己运行,只能后台运行,并且可以和其他组件进行交互。Service的启动有两种方式:context.startService() 和 context.bindService()。 使用context.startService() 启动Service是会会经历:context.startService()
-&onCreate()- &onStart()-&Service runningcontext.stopService() | -&onDestroy() -&Service stop
如果Service还没有运行,则android先调用onCreate()然后调用onStart();如果Service已经运行,则只调用onStart(),所以一个Service的onStart方法可能会重复调用多次。
stopService的时候直接onDestroy,如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。该Service的调用者再启动起来后可以通过stopService关闭Service。 所以调用startService的生命周期为:onCreate --& onStart(可多次调用) --& onDestroy 使用使用context.bindService()启动Service会经历:context.bindService()-&onCreate()-&onBind()-&Service runningonUnbind() -& onDestroy() -&Service stop onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。这个时候把调用者(Context,例如Activity)会和Service绑定在一起,Context退出了,Srevice就会调用onUnbind-&onDestroy相应退出。
所以调用bindService的生命周期为:onCreate --& onBind(只一次,不可多次绑定) --& onUnbind --& onDestory。 在Service每一次的开启关闭过程中,只有onStart可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。 service可以在和多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你地理信息位置的改变等等,总之服务嘛,总是藏在后头的。
47:Android Project在用ant install部署时报taskdef class com.android.ant.SetupTask cannot be found异
原因:local.properties的路径设置问题
解决办法:查看路径是否是单反斜杠,如果是,改成双反斜杠,如:sdk.dir=e:\android-sdk-windows修改成sdk.dir=e:\\android-sdk-windows
48:Android文字高亮计算
主要通过使用SpannableString类即可实现。
49:学习过程中遇见的经典网站
/p/android-unused-resources/(检测资源文件是否被利用)
/tools/help/proguard.html(还原混淆后的log方法)
/forum.php?mod=viewthread&tid=168008
50:android新功能提示指引页面如何实现。
1)通过布局文件实现,正常时未隐藏不显示的,可以通过逻辑让其显示
2)通过SharedPreferences保存使用状态。
51:Tab切换Activity方案
1)通过TabActivity
本方案只是针对通过Tab标签实现Activity切换,不同Tab切换时实现Activity相互切换,其中过度可以实现交互动画,本方案就是针对该需求而设计。
在讲解方案前,需要明确了解如下几个基本知识1:TabActivity2:TabHostTabHost主要由两部分组成,标签和内容,其中内容是一个FrameLayout,当用户单击不同的标签可以显示不同的内容。使用标签可以达到分页的效果,是页面的内容更加丰富,更加具有亲和力,当然与此同时,也会增加页面的复杂程度
3:TabWidgetTabWidget就是Tab的一个集合,也就是Tab栏。
4:TabSpec选项卡的标识,可以设定选项卡的标题、可以设置图片等,并且设置选项卡内容。
TabHost,TabWidget,FrameLayout之间的关系:TabHost好比一个选项卡的容器,包括多个选项卡和选项卡的内容,其中选项卡的内容是一个FrameLayout容器,TabWidget可以理解为选项卡栏.正确的main.xml文件应该包含这三个组件TabHost,TabWidget,FrameLayout
下面是具体的开发设计步骤:1) 定义一个主的Activity,该Activity必须要继承至TabActivity,只有继承了该TabActivity的才可以实现Tab切换,同时必须要实现OnTabChangeListener(用于控制tab切换事件,也可以在这里实现动画效果), OnGestureListener(用户控制何时触发左右tab切换)两个接口。2) 自定义一个TabHost控件(包括TabWidget标签栏+FrameLayout内容),需要重写addTab和setCurrentTab两个方法,第一个方法用于增加标签,而另一个是设置内容(Activity)切换动画。
2)通过ActivityGroup
在一个主界面中做Activity切换一般都会用TabActivity,使用方便,Activity互相之间相对独立,但是可定制性不强,而且修改起来很麻烦。当然也可以把layout分开,把逻辑代码全写在主界面的逻辑代码中,但是很明显可维护性相当差,这里通过ActivityGroup来解决这个问题。
52:android:layout_weight="1"可以实现比例权重,挺方便的。
53:android观察者模式
ContentObserver——内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。触发器分为表触发器、行触发器,相应地ContentObserver也分为“表“ContentObserver、“行”ContentObserver,当然这是与它所监听的Uri MIME Type有关的使用ContentObserver的情况主要有一下两者情况:1、需要频繁检测的数据库或者某个数据是否发生改变,如果使用线程去操作,很不经济而且很耗时2、在用户不知晓的情况下对数据库做一些事件,比如:悄悄发送信息、拒绝接受短信黑名单等;3、需要监控特定的URI内容变化的情况。在上述情形下,使用ContentObserver无疑是最好的利刃了。
54:一种对View(可以使布局,也可以使具体的控件)指定区域进行触碰控方法。
原理很简单:
1)注册View的触碰监听事件view.setOnTouchListener(****);
2)实现该接口接口中的方法,如果是只需要出发点击事件,只需要实现MotionEvent.ACTION_DOWN即可
private OnTouchListener viewOnTouchListener = new OnTouchListener()
public boolean onTouch(View v, MotionEvent event)
int id = v.getId();
int action = event.getAction();
if (id == R.id.viewlayout)
switch (action)
case MotionEvent.ACTION_DOWN:
int screenWidth = v.getWidth();
float leftDistance = v.getWidth() / 3;
float rightDistance = v.getWidth() * 2 / 3;
float fingerPointX = event.getX();
if (fingerPointX & leftDistance && fingerPointX & 0)
else if (fingerPointX & rightDistance && fingerPointX & screenWidth)
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
55:编译Android工程时,如果出现了“the currently displayed page contains invalid values”,原因:
工程中没有project.properties和project.cfg文件,直接拷贝过来即可。
56:编译运行Android工程时,如果出现了“Android library projects cannot be launched ”,原因:
In the Package Explorer, right-click the library project and select Properties.In the Properties window, select the “Android” properties group at left and locate the Library properties at right.Select the “is Library” checkbox and click Apply.Click OK to close the Properties window.发现is Library是选中的,取消选择后,程序可以编译了。
56:Android通过Paint画文本时,如何得到文本占屏幕的宽度。
paint.setTextSize(10);//先设置字体大小float width = paint.measureText("中文字符");//获取字符长度
57:Project **** is missing required source folder: 'gen'解决方法
1)Project--&Properties--&Java Build Path--&Order and Export中把gen目录上下移动一下,OK下去。2)Project--&Properties--&Java Build Path--&Source下把gen目录删除,再通过Add Folder...加上去。Eclipse自动会把gen放在src之前。
58:MotionEvent事件在onInterceptTouchEvent()、onTouchEvent()中的传递顺序 1)onInterceptTouchEvent()用于处理事件并改变事件的传递方向。处理事件这个不用说了,你在函数内部编写代码处理就可以了。而决定传递方向的是返回值,返回为false时事件会传递给子控件的onInterceptTouchEvent();返回值为true时事件会传递给当前控件的onTouchEvent(),而不在传递给子控件,这就是所谓的Intercept(截断)。
2)onTouchEvent() 用于处理事件,返回值决定当前控件是否消费(consume)了这个事件。可能你要问是否消费了又区别吗,反正我已经针对事件编写了处理代码?答案是有区别!比如ACTION_MOVE或者ACTION_UP发生的前提是一定曾经发生了ACTION_DOWN,如果你没有消费ACTION_DOWN,那么系统会认为ACTION_DOWN没有发生过,所以ACTION_MOVE或者ACTION_UP就不能被捕获。
59:Android多种异步刷新机制
2)AsynTask
3)Activity.runOnUiThread
60:经典代码
Listview中点击Item时,选中项上移至顶部的动画效果
public void move(View v) {
int list_child_item_height = 0;
// if (mList.getCount() & 0) {
// View listItem = AppMgrAdapter.this.getView(0, null, mList);
// listItem.measure(0, 0); // 计算子项View 的宽高
// list_child_item_height = listItem.getMeasuredHeight();
// LogX.e(TAG, "itme高度 = " + list_child_item_height);
int nums = mList.getChildCount();
int height = 0;
for (int i = 0; i & i++) {
View view = mList.getChildAt(i);
// mList.onKeyDown(KeyEvent.KEYCODE_DPAD_UP, null);
AppManageMent app = (AppManageMent) view.getTag();
if (app.getChildIndex() == selectedPosition) {
int Pos[] = { -1, -1 }; // 保存当前坐标的数组
view.getLocationOnScreen(Pos); // 获取选中的 Item
// 在屏幕中的位置,以左上角为原点 (0,
LogX.e(TAG, "selected appInfo x = " + Pos[0] + "y = " + Pos[1]);
int Pos[] = { -1, -1 }; // 保存当前坐标的数组
view.getLocationOnScreen(Pos); // 获取选中的 Item
// 在屏幕中的位置,以左上角为原点 (0,
LogX.e(TAG, "appInfo" + i + " x = " + Pos[0] + "y = " + Pos[1]);
if (Pos[1] &= 169) {//169是顶部菜单栏高度
height = height + itmeH// itemHeight是listview每一项高度
height = height + (itmeHeight - (169 - Pos[1]));
LogX.e(TAG, "移动的高度 = " + height);
// if(height & 0){
final int moveHeight =
Animation upAnimation = new TranslateAnimation(0, 0, 0, -height);
if (moveHeight & 0) {
upAnimation.setDuration(1000);
upAnimation.setDuration(0);
// upAnimation.setFillBefore(true);
upAnimation.setAnimationListener(new AnimationListener() {
public void onAnimationStart(Animation animation) {
public void onAnimationEnd(Animation animation) {
mList.setSelectionFromTop(selectedPosition, 0);
mList.clearAnimation();
public void onAnimationRepeat(Animation animation) {
Listview下拉刷新出现Loading加载布局时,当有新数据时,保证当前Listview整体列表不动的核心代码int loadingHeight = 87+30;if (selectIndex == 0){
View listItem = mGroupChatLogAdapter.get().getView(position-1, null, mChatListView);
listItem.measure(0, 0);
int height = listItem.getMeasuredHeight();
if(height == loadingHeight)
mChatListView.setSelectionFromTop(position,0);
else if(height & loadingHeight)
mChatListView.setSelectionFromTop(position,-(height-loadingHeight));
else if(height & loadingHeight && height & 0)
mChatListView.setSelectionFromTop(position,loadingHeight-height);
61:ViewGroup如何实现无限循环,思想如下
1:在最左边View同时将最右边的View加入在其左边;同时在其右边View将最左边的View加入其右边;
2:当用户移动至最左边时,动画执行屏幕移动时,同时发行请求Handler,将View填充至最左边;最右边也同理。
ViewGroup核心代码:
public void snapToScreen(int whichScreen)
boolean isSendHandler =
whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
final int delta = whichScreen * getWidth() - getScrollX();
int delayMills = Math.abs(delta);
//这段代码设计精妙之处在动画之前过程中,发送定时Handle,动画完成后同时执行Handler,绝妙之极
if(whichScreen == 0)
sendHandlerMsg(what0,delayMills);
else if (whichScreen == getChildCount() - 1)
sendHandlerMsg(what1,delayMills);
delayMills = (int) (Math.abs(delta) * 1.5);
mScroller.startScroll(getScrollX(), 0, delta, 0, delayMills);
// 如果需要移动的tab和当前tab是同一个,则不需要发送Handler
if (whichScreen != mCurrentScreenIndex)
isSendHandler =
mCurrentScreenIndex = whichS
selectView(mCurrentScreenIndex, isSendHandler);
invalidate();
62:如果界面中存在多个Listview时,切换时如何保证listivew中第一个可见的条目所在屏幕中的位置保证一致。
private void setListView(ListView sourceListView, ListView desListView)
if (null != sourceListView && null != desListView)
int[] location = new int[2];
if (0 == listViewYLocation)
//获取该VIEW控件相对于手机屏幕的绝对坐标位置
desListView.getLocationOnScreen(location);
listViewYLocation = location[1];
if (sourceListView.getCount() & 0)
//获取源ListView中第一个显示的item---在ListView中,使用getChildAt(index)的取值,只能是当前可见区域(列表可滚动)的子项!
View convertView = sourceListView.getChildAt(0);
if (null != convertView)
//view距离屏幕顶端距离
int convertViewLocationY = 0;
//ListView中item距离ListView的顶部距离
int itemLocationY = 0;
//获取该VIEW控件相对于手机屏幕的绝对坐标位置
convertView.getLocationOnScreen(location);
convertViewLocationY = location[1];
itemLocationY = - (listViewYLocation - convertViewLocationY);
int selectIndex = sourceListView.getFirstVisiblePosition();
desListView.setSelectionFromTop(selectIndex, itemLocationY);
private boolean isFirstItem()
if (mChatListView != null)
if (mChatListView.getCount() == 0)
else if (mChatListView.getFirstVisiblePosition() == 0)
final View firstVisibleChild = mChatListView.getChildAt(0);
final View secondVisibleChild = mChatListView.getChildAt(1);
// 只要Listview中的第一个item是Loading,则触发请求,不论该item在屏幕中可见部分是多少像素。
if (firstVisibleChild != null && firstVisibleChild == headerView)
//开始执行加载Loading动画
headerView.startAnimation(animationHeaderLoading);
int[] firstVisibleLocation = new int[2];
int[] listviewLocation = new int[2];
if (null != firstVisibleChild)
// 获取该VIEW控件相对于手机屏幕的绝对坐标位置
firstVisibleChild.getLocationOnScreen(firstVisibleLocation);
secondVisibleItem = (GroupMessageItem) secondVisibleChild.getTag();
firstVisibleYLocation = firstVisibleLocation[1];
mChatListView.getLocationOnScreen(listviewLocation);
listviewYLocation = listviewLocation[1];
64:Listview特别之处:
1)由于listivew删除头部的前提条件是1)header先要add至listview;2)listview.setAdapter,再可以remove头部
2)如果需要做listview整体上移动作,而listview顶部右一个布局问题,需要实现listivew上移动画是在该布局的下面完成,由于listivew整体移动时依据以其父布局文件,
故而listivew一定要控制在其父布局下面即可。
3)如果listview执行上移动画时,底部会出现空白区域,解决思路可以尝试对包含Listview的容器截图,对图片进行移动。
titleLayout.setDrawingCacheEnabled(true);
titleLayout.buildDrawingCache();
Bitmap bitmap = titleLayout.getDrawingCache();
animationImageView.setImageBitmap(bitmap);
animationImageView.setVisibility(View.VISIBLE);
titleLayout.setVisibility(View.INVISIBLE);
translateAnimation = new TranslateAnimation(0f, 0f, 0f, -lineViewFlow.getHeight());
translateAnimation.setDuration(animationMillilis);
animationImageView.startAnimation(translateAnimation);
lineViewFlow.setVisibility(View.GONE);
65:旋转动画,如果出现没有按照中心点运行,可能的原因就是布局问题。
66:如果需要做在指定的时间内容界面无任何操作,执行某个动作,可以通过发送延时Handle。
67:动画执行和Ui操作不同步时,导致的原因可能是布局文件的层次结构导致。
68:如果布局需要实现上下两层的话,可以通过RelativeLayout实现,同时最上面的布局,应该放置在布局文件的最底部
69:如果view设置成View.INVISIBLE后,未生效,可能的原因
1)布局的问题
2)view是否设置了setFillAfter(true);
70:Android客户端布局文件中的每个空间的位置如果相对于布局本身不动的话,则离左边、右边、上边、下边都是为0,所以大家在理解布局文件的的元素布局是一定要搞清楚,为0的意思不是在手机最顶部的原点位置,切记!
71:性能优化和体验优化总结
1)如果在支持比较费时的操作且需要用户立刻显示界面时,可以采用AsynTask、发送延时Handler、Thread等。
72:Application 'com.hotalk' has its 'debuggable' attribute set to FALSE and cannot be debugged.
是由于AndroidManifest.xml文件中的Application中设置了debug模式.
73:如果运行eclipse时,出现ADB server didn't ACK * failed to start daemon *
error: unknown host service问题,且通过重启adb、eclipse、升级adt,都无效时,可以考虑如下:
1)到任务栏清除ADB.exe
2)关闭PC上面的手机连接助手工具进程。
3)重启adb
74:Android 实现Activity后台运行
第一种方法
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
第二种方法:此方法其实不是主要是屏蔽Keycode_Back,让它不结束(finish())Activity,直接显示HOME界面。
PackageManager pm = getPackageManager();
ResolveInfo homeInfo = pm.resolveActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME), 0);
if (keyCode == KeyEvent.KEYCODE_BACK)
ActivityInfo ai = homeInfo.activityI
Intent startIntent = new Intent(Intent.ACTION_MAIN);
startIntent.addCategory(Intent.CATEGORY_LAUNCHER);
startIntent.setComponent(new ComponentName(ai.packageName,
ai.name));
startActivitySafely(startIntent);
return super.onKeyDown(keyCode, event);
75:解决出现ANR问题的部分技术细节
1)错误的使用SQLiteDatabase事物,需要捕获潜在的异常,不要因为未调用的transExecSQL中的endTransaction方法,导致30秒异常
2)重复Handler注册和发送信息
76:eclipse启动日志中出现如下异常: ***
java list.cache' not found.
解决方法:删除eclipse对应workspace下面的.metadata文件夹
77:有些时候通过程序对控件的位置进行调整(XXX.setMargins(0, 0, 0, 0);)时,往往会在特殊机型中失效,原因可能如下:
控件对应父布局RelativeLayout、LinearLayout使用导致,建议使用RelativeLayout相对布局。
78:onInterceptTouchEvent和onTouchEvent调用时序
SDK中说明:
1. down事件首先会传递到onInterceptTouchEvent()方法
2. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,
  那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最
  终的目标view的onTouchEvent()处理
3. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,
  那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样
  传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。
4. 如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一
  层次的view的onTouchEvent()处理
5. 如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递
  给该view的onTouchEvent()处理
79:代码中合入手势事件
1:实现OnGestureListener接口中的方法,主要是onFling方法
2:定义GestureDetector事件
mGestureDetector = new GestureDetector(this);
new View.OnTouchListener()
public boolean onTouch(View v, MotionEvent event)
if (mGestureDetector.onTouchEvent(event))
3:需要重写Activity中的dispatchTouchEvent方法
public boolean dispatchTouchEvent(MotionEvent event)
if (mGestureDetector.onTouchEvent(event))
event.setAction(MotionEvent.ACTION_CANCEL);
return super.dispatchTouchEvent(event);
http://blog.csdn.net/xiezhenxiang/article/details/6659506
80:ViewPager使用总结
1:在使用过程中如果出现"Could not find class 'android.support.v4.view.ViewPager'",处理方式可以通过设置eclipse中Java Build Path -&Order and Export
中将android-support-v4.jar置顶
2:Matrix类可以完成控件的缩放、移动、翻转、扭曲等效果,针对这个控件不能是.9图片,因为.9图片是没有实际宽度和高度的。
3:ViewPager使用中需要涉及到PagerAdapter\OnPageChangeListener等类。
1)如何实现View循环功能,PagerAdapter中的instantiateItem可以实现页面循环功能,具体看代码
1、初始化时先设置ViewPager.setCurrentItem(无限大),ViewPager控件初始化时,会依据PageAdapter中view的个数平均在选中项的周围初始化View。
2、int newPosition = arg1 % mListViews.size();
((ViewPager) arg0).addView(mListViews.get(newPosition), 0);
catch (Exception e)
return mListViews.get(newPosition);
2)如何实现ViewPager滑动过程中,Tab指示图片也在跟随移动,这个具体需要使用到OnPageChangeListener中的onPageScrolled方法,样例代码如下
int newPosition =
position % views.size();
float toXDelta = (newPosition + arg1) * offsetOfImageByScroll(Tab均分后一屏宽度);
//当从最左边向最右边滑动时
if(viewPagerCurrentIndex == 0 && newPosition == views.size() - 1)
toXDelta = (arg1 - 1) * offsetOfImageByS
setCursorImageLeft(toXDelta + offsetOfImageByParentLeft(Tab指示图片里当前Tab左边的距离));
3)实现Tab点击事件对应各自的View
if(Math.abs(selectIndex - viewPagerCurrentIndex) & 1)
mPager.setCurrentItem(viewPagerVirtualCurrentIndex + (selectIndex - viewPagerCurrentIndex - 1));
mPager.setCurrentItem(viewPagerVirtualCurrentIndex + (selectIndex - viewPagerCurrentIndex));
4:通过dimen尺寸资源文件设置layout布局文件中的高度、宽度等其他参数,具体使用如下:
1)在res中的values目录下定义一个dimens.xml,格式如下
&resources&
&dimen name="key"&value&/dimen&
&/resources&
2)通过程序之间获取该值getResources().getDimension(R.dimen.key);
81:布局文件使用总结
1:当一个layout配置文件中存在多个RelativeLayout(层叠关系),由于它们渲染是依据layout文件上下顺序进行渲染,故需要展示在最上面的,则应该在最下面
2:当自定义一个控件时(嵌入至layout配置文件中),运行后却无法显示,可能的原因如下
1)通过new生产的该控件对象,请修改为通过配置文件中控件ID进行匹配
2)layout配置文件其他控件覆盖了
解决头像异步加载后,显示的头像和实际不符的问题:出现这个问题的原因可能是采用控件缓存holder被其他Item赋值了,导致头像异常
解决方法:可以对handler中的控件设置tag,而在异步加载时通过View.findViewWithTag(tag)再对其进行赋值,确保唯一。
83:Handler是运行在主UI线程能力,故至只能在UI中创建
1)通过在Activity、Service中创建
2)如果需要在后台代码中创建,可以通过借助于Handler(Looper looper),而其中的looper则可以通过HandlerThread.getLooper()
84:某些情况下对ImageView通过程序设置图片时,有些时候会失效,原因:
1)通过setBackgroundResource设置时,可能失效,可以通过setImageResource。
85:Android通过注册广播接收屏幕解锁事件,但是屏幕加锁事件是不能做接收,只能通过亮屏和暗屏广播做处理。
备注:如果是在没有锁屏情况下,亮屏(打电话过程中会出现)--用户没有触发手机的按键事件,示其为解屏。
ACTION_SCREEN_ON:
KeyguardManager keyMan = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
if (!keyMan.inKeyguardRestrictedInputMode()) {
// 如果是在没有锁屏情况下,亮屏(打电话过程中会出现)
FusionField.isScreenUnLocked =
86:如何编写自定义设置字体控件
需求:android中设置字体只是针对文本内容有效,故这个就是需求的根源,在显示该文本内容时借助于TextView控件(或自定义文本控件)的setTextSize,通过
对该方法设置不同的值,再通过刷新所承载该文本控件的父控件(如:Listview),从而完成该功能。
1)编写自定义控件(内嵌拖动条控件),实现拖动控制,需要实现SeekBar.OnSeekBarChangeListener内部的方法。
2)将该自定义控件合入需要的布局中。
87:android中MotionEvent整理:
1:MotionEvent.getX()和getY()得到的值为基于当前控件View相对于手指移动的X、Y坐标,而非基于手机顶部的相对坐标。
88:如何控制程序横竖屏切换
在AndroidManifest.xml文
件中配置对应的Activity即可,如android:screenOrientation="portrait"(andscape是横向,portrait是纵向)
89:更换主题后,导致布局错乱的原因可能是由于布局中设置高度或者宽度等没有设置绝对值,而是wrap_content
90:自定义Menu的设计思路:最好的方案是依据layout去控制menu需要显示的位置,而不是通过代码控制,这样做的好处是可以精确无误的控制布局\减少代码维护从而不是很好适配机型的问题\
可以很好的发挥代码的设计能力。
1)编写布局问题,控制好需要显示的问题。
2)依托PopupWindow类完成相关布局的顶层展示
3)注意事项:
opWindow.setFocusable(true);
popWindow.update();
//显示及位置设置
popWindow.showAtLocation(headView, Gravity.FILL, 0, 0);
//显示及自定义位置设置
popWindow.showAsDropDown(headView, 0, -headView.getHeight());91:先描述下Android加载.so文件的步骤:
1:通过Android NDK生成相应的.so文件,并会在eclipse对应的工程中生成libs\armeabi文件夹,而so文件必须放置到该目录在,java程序才可以通过
System.loadLibrary访问该文件。
2:打包apk时.so文件就可以打包到apk文件里,在apk装到手机上以后
在libs\armeabi下的.so文件应该就会解压到/data/data/package/lib目录下。
3:这样程序就可以直接访问该so文件。
.so的名字必须有'lib'前缀 否则apk解压/安装到手机的时候不会把libs\armeabi下的.so拷贝到/data/data/package/lib目录下。
92:android:sharedUserId权限
通过Shared User id--就是指Linux用户,不同用户所属权限不一样,拥有同一个User id的多个APK可以配置成运行在同一个进程中.所以默认就是
可以互相访问任意数据. 也可以配置成运行成不同的进程, 同时可以访问其他APK的数据目录下的
数据库和文件.就像访问本程序的数据一样.
比如某个公司开发了多个Android 程序, 那么可以把数据,图片等资源集中放到APK
A中去. 然后
这个公司的所有APK都使用同一个User ID, 那么所有的资源都可以从APK A中读取.
当在开发过程中A或者B中任意一个去除了android:sharedUserId属性,可能导致的问题就是A或者B读取相互直接的数据失败。
93:Listview滑动性能优化:
1. getView将获取字符串和图片放入到Adapter的构造方法中,以后getView可以直接使用内存中的数据,不需要进行IO操作
2. 将getView使用的函数变为内联函数,提高运行效率
getView 中费时操作放入Manager层,提高getView效率。
4. 减少变量声明和在getView中new变量,提高内存和性能
5. 使用变量,则直接使用需要的子类,不要使用父类的引用,提高性能。比如,使用ArrayList&String&, 不要使用List&String& list = new ArrayList&String&()
6. 缩短变量应用层次,比如 LayoutInflater.from(mContext).inflate(resID, parent, false),可以将LayoutInflater.from(mContext)变为一个Adapter的私有成员。如LayoutInflater factory = LayoutInflater.from(mContext)
Apk反编译:
1. 首先找到Android软件安装包中的classes.dex
把.apk文件改名为.zip,然后解压缩,得到其中的classes.dex文件,它就是java文件编译再通过dx工具打包成的,所以现在我们就用上述提到的2个工具来逆方向导出java源文件
2. 把classes.dex拷贝到dex2jar.bat所在目录。
在命令行模式下定位到dex2jar.bat所在目录,运行 dex2jar.bat classes.dex
,生成classes.dex.dex2jar.jar
3. 运行JD-GUI工具(它是绿色无须安装的)
打开上面的jar文件,即可看到源代码
94:对于同一个Listview中,需要展示很多布局文件的内容时,大多采用View复用技术,即ConvertView,有些时候列表在滑动过程中不同的布局内容会形成错乱,解决方法:
通过在listview中对应的Adapter需要重新getViewTypeCount和getItemViewType方法。
当ListView中存在不同视图的Item的时候,Adapter中存在一个int getViewTypeCount()方法返回item使用的View类型的数量(默认为1)。
listView根据Adapter的这个方法的返回值,在回收站中建立对应数量的保存区域。而Adapter的int getItemViewType(int position):根据position获取对应item使用的View类型。
ListView会在回收站中根据类型建立不同的保存区域,listView会在调用Adapter 的getView方法之前,根据position获取正确类型的View进行复用。
public int getItemViewType(int position) {
// TODO Auto-generated method stub
if(letter[position].length() == 1) {
return FIRST_LETTER_ITEM;
return WORD_ITEM;
public int getViewTypeCount() {
// TODO Auto-generated method stub
//因为有两种视图,所以返回2
95:通过 LayoutInflater.from(mContext).inflate(R.layout.****, null, false)获取view时,有些时候会出现显示的内容为空,可能的原因:
1:由于该布局文件可能是依附在某个父布局文件中,故而需要将inflate中的第二个参数设置非null
96:android项目中values中文件的作用小结
1、colors.xml——当中定义各种颜色值。
2、strings.xml——当中定义使用到的字符串常量。
3、styles.xml——当中是各个控件的“样式”,样式由一个个属性所组成。我们在编辑xml文件的时候,不同的类所能设置的属性有共同的,也有不同的,都是由样式来控制的。具体可以去看styles.xml这个文件的内容。
4、themes.xml其实也是样式,只是适用的范围大一点
5、attrs.xml——当中定义的是类的属性,属性是为了能在xml文件中被引用到,换句话说就是指定类中变量(也就是属性的实际作用者)的值。
这些属性会在类的构造函数中用到。看过一两个源码就会明白,构造函数中的TypedArray其实就是属性的数组,数组的成员会被赋给类里的成员,完成从xml的初始化。类的构造函数一般有三个,一个是Class(context),这个用于在代码中创建一个类,所以只包含一个上下文;Class(context, attrs)和Class(context, attrs, defStyle)用于从xml创建类的情况。
6、dimens.xml定义常量文件--直接在代码或者布局文件中使用即可
7、array.xml定义的各类数据
8、idxml——为应用的相关资源提供唯一的资源id。id是为了获得xml中的对象而需要的参数,也就是Objects. = findViewById(R.id.id_name)中的id_name。这些值可以在代码中用android.R.id引用到。
若在ids.xml中定义了ID,则在layout中可如下定义@id/price_edit,否则@+id/price_edit。
97:android环境变量配置,直接在cmd中输入adb命令即可:
1:新增一个系统环境变量android,里面的值--:.; D:/****/D:/****/platform-
2: 将该变量(%android%)增加至PATH系统环境值尾部。
98:当点击图片控件等需要背景效果时(selector实现),但是而背景区域是要大于图片本身,这个实现方案有如下两种:
1:通过在该image上层,增加一个RelativeLayout,用于控制背景效果区域。
2:通过图片控件自身的android:background和android:scaleType来完成。android:scaleType用于控制图片在该控件中显示的样式
http://blog.csdn.net/strliu/article/details/7284848
99:Android优化工具使用
1:Android-Lint:查错与代码优化利器
http://blog.csdn.net/thl789/article/details/8037473
2:DDMS中start method profiling--程序每个细节耗时统计工具,可以方便统计出每个程序片段耗时
浏览: 163073 次
来自: 南京
不好意思我看错了
好吧,网上很多方法一的,我不知道大家有验证过没有。我测试了下。 ...
TonyLian 写道下这个包到WEB-INF/libs sp ...
.ComFailException: ...
没有附件?getAnyCellStyle 这个方法,getHd ...

我要回帖

更多关于 安卓画布 的文章

 

随机推荐