android appwidget开发总结

时间:2024.4.13

Android AppWidget开发

从MVC结构上来说,AppWidget是Launcher上的一个View,AppWidgetManager是它的controller,client package(如com.baidu.searchbox)是它的model。

在client package中,AppWidgetProvider用来提供AppWidget的生命周期响应事件,AppWidgetProviderInfo用来提供AppWidget的初始layout id等信息,AppWidget Configuration用来提供AppWidget的配置界面。

AppWidgetManager通过它的updateAppWidget方法驱动AppWidget的View进行UI更新。而AppWidget又通过RemoteViews来获取client package提供的UI更新信息。

由于Launcher与client package通讯属于IPC,所以,一般都使用AlarmManager来实现AppWidget的定期更新。

1 AppWidgetProvider

1.1 本质:

一个可以接收ACTION_APPWIDGET_UPDATE、 ACTION_APPWIDGET_ENABLED、 ACTION_APPWIDGET_DELETED 、以及ACTION_APPWIDGET_DISABLED的broadcast receiver。这些action对应了AppWidget的更新通知和生命周期,即onUpdate、onEnabled、onDeleted、onDisabled。

使用方法:

与其它静态静态注册的receiver一样,在manifest中添加声明,并在代码中定义。

1.2 注意事项:

1. manifest声明处必须显式添加接收ACTION_APPWIDGET_UPDATE的intent filter,否则无法在widget列表中找到该widget。

2. 由于它是个broadcast receiver,所以只在onReceive方法中才被视为foreground组件(被系统杀死的可能性最小的组件),离开了该方法,就相当于onDestroy后的Activity,是个空组件,所以不要在其中执行异步操作,如sendMessage或者另开线程。

3. onReceive方法也在主线程中执行,发生了ANR之后,默认是不弹出Dialog的。如果需要执行耗时的操作,最好使用service来另开线程执行。

4. 生命周期(onEnabled、onUpdate、onDeleted、onDisabled)其实都是在onReceive中执行。

5. onUpdate会在添加widget(有configuration的除外)、覆盖安装应用、系统设置改变等场景触发。它的本质是将widget的UI重置为初始状态后(AppWidgetProviderInfo中的initialLayout),提供给应用程序一个更新UI的机会(调用AppWidgetManager的updateAppWidget方法)。 2 AppWidgetProviderInfo

2.1 本质:

Widget的基本设置信息,包括区域大小、initialLayout以及配置界面等,与AppWidgetProvider一一对应。Android3.0后增加了previewImage项(此项必须设置,否则在3.0以上系统上看不到预览图)。

使用方法:

定义成一个xml,放在res/xml目录中,并在manifest中以meta的形式声明在AppWidgetProvider里,否则widget列表中也无法找到该widget。

2.2 注意事项:

1. Widget执行onUpdate之前,都会根据AppWidgetProviderInfo中的initialLayout来重置UI。因此,尤其在有AppWidget Configuration的widget中,initialLayout最好使用另一种UI形式。如时钟widget,initialLayout设为“正在加载中”的界面,而不是默认为模拟时钟或者数字时钟,以免在widget触发onUpdate时,出现数字时钟变为模拟时钟(或者模拟时钟变为数字时钟)的情况,造成短暂的混乱。

2. AppWidgetProviderInfo由launcher解析后放入自己的进程中,并只能在重新安装应用程序后根据AppWidgetProvider的meta重新解析并更新(参考AppWidgetService.java中的updateProvidersForPackageLocked方法)。如果该AppWidgetProvider在新版中不复存在,那么AppWidgetProviderInfo中的layout id就不会更新,如果在新版中不将该id值固定(在public.xml中声明,使ADT编译资源时避开使用该id值),很可能会与另一个layout id重合,造成UI混乱。

3 AppWidget Configuration

3.1 本质:

一个Activity,用来给同类widget(即AppWidgetProvider相同)的不同实例

(appWidgetId不同)配置不同的UI。原理是在widget添加时,放弃执行本次onUpdate,而是执行startActivityForResult,将更新UI的机会交给Activity(调用AppWidgetManager的updateAppWidget方法即可)。

使用方法:

在AppWidgetProviderInfo中加入configure声明,并在manifest声明该activity处加上android.appwidget.action.APPWIDGET_CONFIGURE动作。

3.2 注意事项:

返回RESULT_OK并在intent中设置EXTRA_APPWIDGET_ID,才能通知系统哪个widget配置成功。如果取消配置(如按back键),则返回RESULT_CANCELED。 4 RemoteViews

4.1 本质:

一个Parcelable,用来将UI信息从本地应用程序传送到launcher中,与实体View可一一对应,但支持的种类不全,参考API文档。

使用方法:

直接根据AppWidgetProvider和AppWidgetId来构造一个属于某个widget的RemoteViews对象。通过AppWidgetManager的updateAppWidget,并传入该RemoteViews对象,即可完成对该widget的UI更新。

4.2 注意事项:

1. 在Android3.0以前,widget更新方法会缓存UI,所以,如果想让同类widget的不同的实例显示不同的内容,最好对该RemoteViews上的所有subViews全部进行更新,否则会导致混乱。Android3.0以后,提供了一种不缓存UI的更新方法。

2. Widget上的动画效果,可以用viewgroup的layoutAnimation属性来实现。如果想多次使用动画,可以借助RemoteViews的removeAllViews和addViews方法,使得新加入的viewgroup执行layout,从而触发动画。

3. 如果想实现更复杂的UI效果,但是RemoteViews中未提供该方法(比如使用个性字体),不妨将view换成ImageView,在将复杂的UI内容以Bitmap的形式传给RemoteViews。RemoteViews size有限,如果Bitmap超大,则可使用setImageViewUri,以contentProvider URI的形式传给RemoteViews。

5 AlarmManager

5.1 本质:

系统的一个常驻Service,应用程序使用PendingIntent向它发起注册,之后它会在规定的时间投递PendingIntent中指定的broadcast。由于它是系统的进程,并常驻内存,所以可无视应用进程的存活状态,通过投递broadcast消息激活receiver。

使用方法:

参考API文档。

5.2 注意事项:

1. 向AlarmManager发起注册时,AlarmManager会通过intent的filterEquals规则来比对已有注册的PendingIntent,如果和某PendingIntent比对返回结果为相同,则只是改变该PendingIntent注册的schedule,并丢弃新的PendingIntent。而filterEquals比对是无视extras的,所以会导致新的extras被丢弃。因此,如果想覆盖原有注册的PendingIntent,并传递新的数据,可使用intent的data来解决。

2. AlarmManager Service监听了PACKAGE_RESTART的广播,在接收到该广播的时候会清楚该package注册的所有AlarmManger PendingIntent。而在应用程序的清除数据操作时,也会发送该广播,从而导致执行完清除数据的操作后,该程序注册的所有AlarmManager都停止运作。

6 Sprint22总结注意事项:

1. 安装到sd卡的应用无法加载widget

因为widget是在启动的时候加载的,而SD卡是在启动以后加载的,有可能导致widget需要加载的时候SD卡还没有载入系统,这样就会导致widget的加载失败,而widget的机制导致其不会再次加载,所以禁止安装到SD卡上的应用开启widget功能。

2. Widget的刷新

最好不使用android:updatePeriodMillions,因为1:这个时间间隔有最大1小时的限制2:不能保证系统一定能按照设定的时间进行onUpdate的调用,因为系统要考虑到电量、资源等问题。因此一定要实现自己的刷新机制,使用AlarmManager自己定更新逻辑。

3. widget布局原始大小minWidth、minHeight的设置

主要用于launcher计算显示几个cell,如果此大小设置超出luancher的显示范围,会导致无法加载widget。关于launcher的每个cell的宽高没有一个标准,每个rom都可能不一样,适配有难度,无法根据分辨率进行。最大范围的适配方式是计算已知的luancher cell的Size,假设widget为4X2,launcher cell大小见下表,则width

应该取一个大于3个cell小于4个cell的值,这样launcher在计算的时候会自动

androidappwidget开发总结

那么launcher2在计算的时候会认为是5个cell,超出laundher横向的最大cell数,那么该widget会被系统认为是错误的,无法加载。目前适配最好的cell Size是72.5dp×59.5dp(经验值,综合了较多的奇葩launcher)


第二篇:android开发总结


Android 图片平铺效果

方法一 XML方式平铺 首先,两个单词的中文意思分别是dither(抖动)和tileMode(平铺) 1,先来介绍tileMode(平铺) tileMode 属性就是用于定义背景的显示模式:

disabled

默认值,表示不使用平铺

clamp

复制边缘色彩

repeat

X、Y 轴进行重复图片显示,也就是我们说要说的平铺

mirror

在水平和垂直方向上使用交替镜像的方式重复图片的绘制 它的效果类似于 让背景小图不是拉伸而是多个重复(类似于将一张小图设置电脑桌面时的效果)

可绘制资源是指能够被绘制到屏幕上的图形的一般化概念,并且能够用诸如getDrawable(int)等API方法来获取这些资源,或者使用诸如android:drawable和android:icon属性把它们应用到另一个XML资源中。以下是几种不同的可绘制资源类型: 位图文件:

位图图形文件(.png、.jpg或.gif)。每个位图资源会创建一个BitmapDrawable对象。

Nine-Patch文件:

Nine-Patch文件是一个带有可拉伸区域的PNG文件,它允许图片基于内容进行尺寸的调整(.9.png)。每个Nine-Patch资源会创建一个NinePatchDrawable对象。

层列表:

层列表管理一个绘制资源数组。它们会按照数组的顺序进行描画,因此索引最大的元素被画在最上面,一个层列表会创建一个LayerDrawable对象。

状态列表:

状态列表是一个XML文件,文件中针对不同的状态定义了要引用的不同位图图形(例如,按钮被按下时,要使用的不同的图片)。一个状态列表会创建一个

StateListDrawable对象。

级别列表:

级别列表是一个定义可替代绘制资源的XML文件,每个资源都会给分配一个最大的数字值,一个状态列表会创建一个LevelListDrawable对象。

过渡绘制资源:

它是一个定义绘制资源的XML文件,文件中的绘制资源能够在两个绘制资源之间渐入渐出。一个XML文件会创建一个TransitionDrawable对象。

插图绘制资源:

它是一个定义绘制资源的XML文件,文件中的绘制资源能够按照指定的距离插入到另一个绘制资源中。当View对象需要绘制的背景比View的实际边框要小时,这个资源是有用的。

剪辑绘制资源:

它是一个定义绘制资源的XML文件,使用文件中的定义,基于绘制资源的当前级别值对另一个绘制资源进行剪辑。它会创建一个ClipDrawable对象。

缩放绘制资源:

它是一个定义绘制资源的XML文件,使用这个文件中的定义会基于当前的级别值来改变另一个绘制资源尺寸。它会创建一个ScaleDrawable对象。

形状绘制资源:

它是一个定义几何图形的XML文件,包括颜色和几何形状。它会创建一个

ShapeDrawable对象。

注意:在XML中,颜色资源也能够用于绘制资源。例如,在创建状态列表绘制资源时,android:drawable属性就可以引用一个颜色资源(如:android:drawable=”@color/green”)。

位图

Android支持三种格式的位图文件:.png(首选)、.jpg(次选)、.gif(不推荐使用)。 可以使用资源ID(文件名)直接引用位图文件,也可以在XML中创建一个别名资源。 注意:在编译期间,位图文件可以被aapt工具用无损图像压缩技术来自动的优化。例如,一个真彩色的PNG图片,不需要超过256色就可以用调试板给转换成8为的PNG图片。这样就会生成同等质量的图片,但却需要很少的内存。因此而要注意,放在这个目录镇南关的二进制图片能够在编译期间发生改变。如果计划用字节流来读取图片,以便把它转换成一个位图,就要把图片放到res/raw/文件夹镇南关,这样它们就不会被优化。

位图文件

这里的位图文件是指.png、.jpg、.gif格式文件。当把这些格式的文件保存在

res/drawable/目录时,Android会给这些文件创建一个绘制资源。

文件位置(FILE LOCATION):

res/drawable/filename.png(.png、.jpg或.gif)。

文件名用于资源ID。

编译资源的数据类型(COMPILED RESOURCE DATATYPE):

资源指向一个BitmapDrawable对象。

资源引用(RESOURCE REFERENCE):

在Java代码中:R.drawable.filename;

在XML中:@[package:]drawable/filename

列子(EXAMPLE):

把一个图片保存在res/drawable/muimage.png中,布局XML把这个图片应用于一个View对象:

<ImageView

android:layout_height="wrap_content"

android:layout_width="wrap_content"

android:src="@drawable/myimage"/>

应用程序在代码中用getDrawable()方法来获取Drawable对象:

Resources res=getResources();

Drawable drawable= res.getDrawable(R.drawable.myimage);

XML位图

XML位图是一个定义在XML中的资源,它指向一个位图文件。它是原始位图文件的一个别名。XML能够给位图指定额外的属性,如仿色和平铺。

注意:能够把<bitmap>元素作为<item>元素的子元素来使用。例如,在创建状态列表或层列表时,能够从<item>元素中排除android:drawable属性,并且在<item>元素内部嵌入一个<bitmap>元素来定义绘制项目。

文件位置(FILE LOCATION):

res/drawable/filename.xml

文件名被用作资源ID。

编译资源的数据类型(COMPILED RESOURCE DATATYPE):

资源指向一个BitmapDrawable对象。

资源引用(RESOURCE REFERENCE):

在Java代码中:R.drawable.filename

在XML中:@[package:]drawable/filename

语法(SYNTAX):

<?xml version="1.0" encoding="utf-8"?>

<bitmap

xmlns:android="/apk/res/android"

android:src="@[package:]drawable/drawable_resource"

android:antialias=["true" |"false"]

android:dither=["true" |"false"]

android:filter=["true" |"false"]

android:gravity=["top" |"bottom" |"left" | "right" |"center_vertical" | "fill_vertical" |"center_horizontal" |"fill_horizontal" | "center" |"fill" |"clip_vertical" |"clip_horizontal"] android:tileMode=["disabled" |"clamp" |"repeat" | "mirror"]/>

元素(ELEMENTS):

<bitmap>

用来定义位图资源和资源属性。

属性(ATTRIBUTES):

xmlns:android

字符串值,定义XML的命名空间,必须是

“/apk/res/android”。如果<bitmap>是根元素,那么这个属性就是必须的。当<bitmap>被嵌套在<item>内时,就不需要了。

android:src

绘制资源。必须的。它指向一个要绘制的资源。

android:antialias

布尔值。启用或禁用抗锯齿效果。

android:dither

布尔值。如果位图没有与屏幕相同的像素配置,这个属性会指示启用或禁用位图的仿色处理。

android:filter

布尔值,启用或禁用位图的过滤处理。在位图收缩或拉伸时,使用过滤处理让外观更平滑。

android:gravity

关键属性。定义位图的重心。如果位图比容器小,重心会指示绘制资源在容器中位置。

必须是下列常量值的组合(组合设定时使用”|”符号分离):

android开发总结

android开发总结

例子(EXAMPLE):

<?xml version="1.0" encoding="utf-8"?>

<bitmapxmlns:android="/apk/res/android"

android:src="@drawable/icon"

android:tileMode="repeat"/>

android开发总结

[html] view plaincopy

1. <xml version="1.0" encoding="utf-8"?>

2. <LinearLayout

3. android:id="@+id/MainLayout"

4. xmlns:android="/apk/res/android"

5. android:layout_width="fill_parent"

6. android:layout_height="fill_parent"

7. android:orientation="vertical"

8. android:background="@drawable/backrepeat"

9. >

backrepeat.xml

[html] view plaincopy

1. <bitmap

2. xmlns:android="/apk/res/android"

3. android:src="@drawable/repeatimg"

4. android:tileMode="repeat"

5. android:dither="true" />

代码方式:

[java] view plaincopy

1. Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon

);

2. BitmapDrawable bd = new BitmapDrawable(bitmap);

3. bd.setTileModeXY(TileMode.REPEAT , TileMode.REPEAT );

4. bd.setDither(true

android开发总结

);

5. view.setBackgroundDrawable(bd);

2,再来解释下 dither(抖动)

Dither(图像的抖动处理,当每个颜色值以低于8位表示时,对应图像做抖动处理可以实现在可显示颜色总数比较低(比如256色)时还保持较好的显示效果: Dither on Wikipedia

方法二 系统API实现

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pic);

//bitmap = Bitmap.createBitmap(100, 20, Config.ARGB_8888);

BitmapDrawable drawable = new BitmapDrawable(bitmap);

drawable.setTileModeXY(TileMode.REPEAT , TileMode.REPEAT );

drawable.setDither(true);

view.setBackgroundDrawable(drawable);

方法三 自己画出来

22 public static Bitmap createRepeater(int width, Bitmap src){

23 int count = (width + src.getWidth() - 1) / src.getWidth();

24

25 Bitmap bitmap = Bitmap.createBitmap(width, src.getHeight(), Config.ARGB_8888); 26 Canvas canvas = new Canvas(bitmap);

27

28 for(int idx = 0; idx < count; ++ idx){

29 canvas.drawBitmap(src, idx * src.getWidth(), 0, null);

30 }

31

32 return bitmap;

Android强制设置横屏或竖屏 全屏

在Activity的onCreate方法中的setContentView(myview)调用之前添加下面代码 requestWindowFeature(Window.FEATURE_NO_TITLE);//隐藏标题

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//设置全屏

横屏

按照下面代码示例修改Activity的onResume方法

@Override

protected void onResume() {

/**

* 设置为横屏

*/

if(getRequestedOrientation()!=ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE){

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

}

super.onResume();

}

或者在配置文件中对Activity节点添加android:screenOrientation属性(landscape是横向,

portrait是纵向)

android:launchMode="singleTask"

android:screenOrientation="portrait">

要设置成竖屏设置成 SCREEN_ORIENTATION_PORTRAIT

// ----------------

常亮

view.setKeepScreenOn(true)

不加任何旋转屏幕的处理代码的时候,旋转屏幕将会导致系统把当前activity关闭,重新打开。

如果只是简单的界面调整,我们可以阻止此问题的发生,屏幕旋转而自己调整屏幕的元素重构。

首先我们需要修改AndroidManifest.xml文件:

<activity android:name=".Magazine">

</activity>

//修改为:

<activity android:name=".Magazine"

android:configChanges="orientation|keyboard">

</activity>

这样是让程序能够响应旋转屏幕的事件。

然后重写onConfigurationChanged方法:

@Override

public void onConfigurationChanged(Configuration newConfig) {

// TODO Auto-generated method stub

super.onConfigurationChanged(newConfig);

Log.v(" == onConfigurationChanged");

processLayout();

}

//----------------------------

在我们用Android开发过程中,会碰到Activity在切换到后台或布局从横屏LANDSCAPE切换

到PORTRAIT,会重新切换Activity会触发一次onCreate方法。

在Android开发中这种情况视可以避免的,我们可以在androidmanifest.xml中的activit元素加入这个属性 android:configChanges="orientation|keyboardHidden" 就能有效避免oncreat方法的重复加载,

androidmanifest.xml内容如下:红色字体为添加部分

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android=""

package="com.demo"

android:versionCode="1"

android:versionName="1.0">

<application android:icon="@drawable/icon" android:label="@string/app_name">

<activity android:name=".DemoGPS"

android:configChanges="orientation|keyboardHidden"

android:label="@string/app_name">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

<uses-library android:name="com.google.android.maps" />

</application>

<uses-sdk android:minSdkVersion="7" />

<uses-permission android:name="android.permission.INTERNET"></uses-permission>

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>

</manifest>

同时在Activity的Java文件中重载onConfigurationChanged(Configuration newConfig)这个方法,这样就不会在布局切换或窗口切换时重载等方法。代码如下:

@Override

public void onConfigurationChanged(Configuration newConfig)

{

super.onConfigurationChanged(newConfig);

if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)

{

//land

}

else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)

{

//port

}

}

//------------------------------------------------------

关于Android中Activity的横竖屏切换问题可以通过AndroidManifest.xml文件中的Activity来配置:

android:screenOrientation=["unspecified" | "user" | "behind" |

"landscape" | "portrait" |

"sensor" | "nonsensor"]

screenOrientation 用来指定Activity的在设备上显示的方向,每个值代表如下含义: "unspecified" 默认值 由系统来判断显示方向.判定的策略是和设备相关的,所以不同的设备会有

不同的显示方向.

"landscape" 横屏显示(宽比高要长)

"portrait" 竖屏显示(高比宽要长)

用户当前首选的方向 "user"

"behind" 和该Activity下面的那个Activity的方向一致(在Activity堆栈中的)

android开发总结

Android应用资源---绘制资源类型(Drawable) 可绘制资源是指能够被绘制到屏幕上的图形的一般化概念,并且能够用诸如

getDrawable(int)等API方法来获取这些资源,或者使用诸如android:drawable和

android:icon属性把它们应用到另一个XML资源中。以下是几种不同的可绘制资源类型:

位图文件:

位图图形文件(.png、.jpg或.gif)。每个位图资源会创建一个BitmapDrawable对象。

Nine-Patch文件:

Nine-Patch文件是一个带有可拉伸区域的PNG文件,它允许图片基于内容进行尺寸的调整(.9.png)。每个Nine-Patch资源会创建一个NinePatchDrawable对象。

层列表:

层列表管理一个绘制资源数组。它们会按照数组的顺序进行描画,因此索引最大的元素被画在最上面,一个层列表会创建一个LayerDrawable对象。

状态列表:

状态列表是一个XML文件,文件中针对不同的状态定义了要引用的不同位图图形(例如,按钮被按下时,要使用的不同的图片)。一个状态列表会创建一个

StateListDrawable对象。

级别列表:

级别列表是一个定义可替代绘制资源的XML文件,每个资源都会给分配一个最大的数字值,一个状态列表会创建一个LevelListDrawable对象。

过渡绘制资源:

它是一个定义绘制资源的XML文件,文件中的绘制资源能够在两个绘制资源之间渐入渐出。一个XML文件会创建一个TransitionDrawable对象。

插图绘制资源:

它是一个定义绘制资源的XML文件,文件中的绘制资源能够按照指定的距离插入到另一个绘制资源中。当View对象需要绘制的背景比View的实际边框要小时,这个资源是有用的。

剪辑绘制资源:

它是一个定义绘制资源的XML文件,使用文件中的定义,基于绘制资源的当前级别值对另一个绘制资源进行剪辑。它会创建一个ClipDrawable对象。

缩放绘制资源:

它是一个定义绘制资源的XML文件,使用这个文件中的定义会基于当前的级别值来改变另一个绘制资源尺寸。它会创建一个ScaleDrawable对象。

形状绘制资源:

它是一个定义几何图形的XML文件,包括颜色和几何形状。它会创建一个

ShapeDrawable对象。

注意:在XML中,颜色资源也能够用于绘制资源。例如,在创建状态列表绘制资源时,android:drawable属性就可以引用一个颜色资源(如:android:drawable=”@color/green”)。

位图

Android支持三种格式的位图文件:.png(首选)、.jpg(次选)、.gif(不推荐使用)。 可以使用资源ID(文件名)直接引用位图文件,也可以在XML中创建一个别名资源。 注意:在编译期间,位图文件可以被aapt工具用无损图像压缩技术来自动的优化。例如,一个真彩色的PNG图片,不需要超过256色就可以用调试板给转换成8为的PNG图片。这样就会生成同等质量的图片,但却需要很少的内存。因此而要注意,放在这个目录镇南关的二进制图片能够在编译期间发生改变。如果计划用字节流来读取图片,以便把它转换成一个位图,就要把图片放到res/raw/文件夹镇南关,这样它们就不会被优化。

位图文件

这里的位图文件是指.png、.jpg、.gif格式文件。当把这些格式的文件保存在

res/drawable/目录时,Android会给这些文件创建一个绘制资源。

文件位置(FILE LOCATION):

res/drawable/filename.png(.png、.jpg或.gif)。

文件名用于资源ID。

编译资源的数据类型(COMPILED RESOURCE DATATYPE):

资源指向一个BitmapDrawable对象。

资源引用(RESOURCE REFERENCE):

在Java代码中:R.drawable.filename;

在XML中:@[package:]drawable/filename

列子(EXAMPLE):

把一个图片保存在res/drawable/muimage.png中,布局XML把这个图片应用于一个View对象:

<ImageView

android:layout_height="wrap_content"

android:layout_width="wrap_content"

android:src="@drawable/myimage"/>

应用程序在代码中用getDrawable()方法来获取Drawable对象:

Resources res=getResources();

Drawable drawable= res.getDrawable(R.drawable.myimage);

XML位图

XML位图是一个定义在XML中的资源,它指向一个位图文件。它是原始位图文件的一个别名。XML能够给位图指定额外的属性,如仿色和平铺。

注意:能够把<bitmap>元素作为<item>元素的子元素来使用。例如,在创建状态列表或层列表时,能够从<item>元素中排除android:drawable属性,并且在<item>元素内部嵌入一个<bitmap>元素来定义绘制项目。

文件位置(FILE LOCATION):

res/drawable/filename.xml

文件名被用作资源ID。

编译资源的数据类型(COMPILED RESOURCE DATATYPE):

资源指向一个BitmapDrawable对象。

资源引用(RESOURCE REFERENCE):

在Java代码中:R.drawable.filename

在XML中:@[package:]drawable/filename

语法(SYNTAX):

<?xml version="1.0" encoding="utf-8"?>

<bitmap

xmlns:android="/apk/res/android"

android:src="@[package:]drawable/drawable_resource"

android:antialias=["true" |"false"]

android:dither=["true" |"false"]

android:filter=["true" |"false"]

android:gravity=["top" |"bottom" |"left" | "right" |"center_vertical" | "fill_vertical" |"center_horizontal" |"fill_horizontal" | "center" |"fill" |"clip_vertical" |"clip_horizontal"] android:tileMode=["disabled" |"clamp" |"repeat" | "mirror"]/>

元素(ELEMENTS):

<bitmap>

用来定义位图资源和资源属性。

属性(ATTRIBUTES):

xmlns:android

字符串值,定义XML的命名空间,必须是

“/apk/res/android”。如果<bitmap>是根元素,那么这个属性就是必须的。当<bitmap>被嵌套在<item>内时,就不需要了。

android:src

绘制资源。必须的。它指向一个要绘制的资源。

android:antialias

布尔值。启用或禁用抗锯齿效果。

android:dither

布尔值。如果位图没有与屏幕相同的像素配置,这个属性会指示启用或禁用位图的仿色处理。

android:filter

布尔值,启用或禁用位图的过滤处理。在位图收缩或拉伸时,使用过滤处理让外观更平滑。

android:gravity

关键属性。定义位图的重心。如果位图比容器小,重心会指示绘制资源在容器中位置。

必须是下列常量值的组合(组合设定时使用”|”符号分离):

android开发总结

android开发总结

例子(EXAMPLE):

<?xml version="1.0" encoding="utf-8"?>

<bitmapxmlns:android="/apk/res/android"

android:src="@drawable/icon"

android:tileMode="repeat"/>

Android自定义Button按钮显示样式

现在的用户对APP的外观看得很重要,如果APP内所有元件都用Android默认样式写,估计下面评论里就有一堆在骂UI丑的。今天学习自定义Button按钮样式。Button样式修改的是Button的背景(Background)属性。

首先写一个定义Button样式的XML文件:

新建Android XML文件,类型选Drawable,根结点选selector,文件名就buton_style吧。

程序自动给我们刚刚建的文件里加了selector结点,我们只需要在selector结点里写上三种状态时显示的背景图片(按下、获取焦点,正常)。

代码如下:

Xml代码

<?xml version="1.0" encoding="utf-8"?>

<item android:state_pressed="true" android:drawable="@drawable/play_press" /> <item android:state_focused="true" android:drawable="@drawable/play_press" /> <item android:drawable="@drawable/play" />

</selector>

我这里获取焦点跟点击时显示的是同一张图片,必须严格照上面的顺序写,不可倒。 接下来只要在布局时写Button控件时应用到Button的Background属性即可。

Xml代码

<Button android:id="@+id/button1"

android:layout_width="wrap_content" android:layout_height="wrap_content"

android:background="@drawable/button_style"

></Button>

最终效果图:

再加上一种自定义样式方法,上面的是用图片,其实我们可以直接通过定义xml文件来实现不同的样式:

在上面的源代码基础上,只需要修改button_style文件,同样三种状态分开定义: Xml代码

<?xml version="1.0" encoding="utf-8"?>

<item android:state_pressed="true">

<shape>

<gradient android:startColor="#0d76e1" android:endColor="#0d76e1"

android:angle="270" />

<stroke android:width="1dip" android:color="#f403c9" />

<corners android:radius="2dp" />

<padding android:left="10dp" android:top="10dp"

android:right="10dp" android:bottom="10dp" />

</shape>

</item>

<item android:state_focused="true">

<shape>

<gradient android:startColor="#ffc2b7" android:endColor="#ffc2b7"

android:angle="270" />

<stroke android:width="1dip" android:color="#f403c9" />

<corners android:radius="2dp" />

<padding android:left="10dp" android:top="10dp"

android:right="10dp" android:bottom="10dp" />

</shape>

</item>

<item>

<shape>

<gradient android:startColor="#000000" android:endColor="#ffffff"

android:angle="180" />

<stroke android:width="1dip" android:color="#f403c9" />

<corners android:radius="5dip" />

<padding android:left="10dp" android:top="10dp"

android:right="10dp" android:bottom="10dp" />

</shape>

</item>

</selector>

gradient 主体渐变 startColor开始颜色,endColor结束颜色 ,angle开始渐变的角度(值只能为90的倍数,0时为左到右渐变,90时为下到上渐变,依次逆时针类推)

stroke 边框 width 边框宽度,color 边框颜色

corners 圆角 radius 半径,0为直角

padding text值的相对位置

Android之自定义Adapter的ListView

在开发中,我们经常使用到ListView这个控件。的API也提供了许多创建ListView适配器的快捷方式。例如ArrayAdapter、SimpleAdapter和SimpleCursorAdapter等。但你是否发现,如果采用这些系统自带的适配器,对于事件的响应只能局限在一个行单位。假设一行里面有一个按钮和一个图片控件,它们之间的响应操作是不一样的。若采用系统自带的适配器,就不能精确到每个控件的响应事件。这时,我们一般采取自定义适配器来实现这个比较精确地请求。

ListView的创建,一般要具备两大元素:

1)数据集,即要映射的字符串、图片信息之类。

2)适配器,实现把要映射的字符串、图片信息映射成视图(如Textview、Image等组件),再添加到ListView中。

下面是一个实操例子:

实现细节:

1、创建数据集,一般定义如下

private List<Map<String, Object>> listItems;

元素添加方式:

Map<String, Object> map = new HashMap<String, Object>();

map.put("image", imgeIDs[i]); //图片资源

map.put("title", "物品名称:"); //物品标题

map.put("info", goodsNames[i]); //物品名称

map.put("detail", goodsDetails[i]); //物品详情

listItems.add(map); //添加一项

2、创建适配器

public class ListViewAdapter extends BaseAdapter{........} //自定义的适配器一般继承BaseAdapter类

listViewAdapter = new ListViewAdapter(this, listItems);

3、给ListView设置适配器

listView.setAdapter(listViewAdapter);

4、这里还有个关键点,如何把list_item.xml布局作为一个视图,添加到listView中:

LayoutInflater listContainer; //视图容器工厂

listContainer = LayoutInflater.from(context); //创建视图容器工厂并设置上下文 convertView = listContainer.inflate(R.layout.list_item, null); //创建list_item.xml布局文件的视图

实例视图如下:

android开发总结

android开发总结

android开发总结

android开发总结

android开发总结

1. <?xml version="1.0" encoding="utf-8"?>

2. <LinearLayout xmlns:"/apk/res/android"

3. :orientation="vertical"

4. :layout_width="fill_parent"

5. :layout_height="fill_parent">

6.

7. <!-- 结算 -->

8. <LinearLayout:gravity="center_horizontal"

9. :orientation="horizontal" android:layout_width="fill_parent"

10. :layout_height="wrap_content">

11. <TextView:text="结算: "

12. :layout_width="wrap_content"

13. :layout_height="wrap_content"

14. :textColor="#FFFFFFFF"

15. :textSize="20px"/>

16. <ImageButton:id="@+id/imgbt_sum"

17. :layout_width="40px"

18. :layout_height="40px"

19. :background = "@drawable/shopping" />

20. </LinearLayout>

21.

22. <TextView:text="商品列表: "

23. :layout_width="wrap_content"

24. :layout_height="wrap_content"

25. :textColor="#FFFFFFFF" />

26.

27. <!-- 商品列表 -->

28. <ListView:id="@+id/list_goods"

29. :layout_width="fill_parent"

30. :layout_height="wrap_content" />

31.

32. </LinearLayout>

列表项布局文件list_item.xml

1. <?xml version="1.0" encoding="utf-8"?>

2. <LinearLayout xmlns:"/apk/res/android"

3. :orientation="horizontal" android:layout_width="fill_parent"

4. :layout_height="fill_parent">

5.

6. <!-- 商品图片 -->

7. <ImageView:id="@+id/imageItem"

8. :layout_width="wrap_content"

9. :layout_height="wrap_content"

10. :layout_margin="5px"/>

11.

12. <!-- 商品信息 -->

13. <LinearLayout:orientation="vertical"

14. :layout_width="wrap_content"

15. :layout_height="wrap_content">

16.

17. <TextView:id="@+id/titleItem"

18. :layout_width="wrap_content"

19. :layout_height="wrap_content"

20. :textColor="#FFFFFFFF"

21. :textSize="13px" />

22. <TextView:id="@+id/infoItem"

23. :layout_width="wrap_content"

24. :layout_height="wrap_content"

25. :textColor="#FFFFFFFF"

26. :textSize="22px" />

27. </LinearLayout>

28.

29. <!-- 购买和商品详情 -->

30. <LinearLayout:gravity="right"

31. :orientation="horizontal" android:layout_width="fill_parent"

32. :layout_height="wrap_content">

33. <CheckBox:id="@+id/checkItem"

34. :layout_width="wrap_content"

35. :layout_height="wrap_content"

36. :layout_margin="5px"/>

37. <Button:id="@+id/detailItem"

38. :layout_width="wrap_content"

39. :layout_height="wrap_content"

40. :layout_margin="5px"/>

41. </LinearLayout>

42. </LinearLayout>

2)代码,主代码:

1. package

2.

3. import java.util.ArrayList;

4. import java.util.HashMap;

5. import java.util.List;

6. import java.util.Map;

7.

8. import

9. import

10. import

11. import

12. import

13. import

14. import

15. import

16. import

17.

18. public class MyListView extends Activity {

19.

20. private ListView listView;

21. private ImageButton imgbt_sum;

22. private ListViewAdapter listViewAdapter;

23. private List<Map<String, Object>> listItems;

24. private Integer[] imgeIDs = {R.drawable.cake,

25. R.drawable.gift, R.drawable.letter,

26. R.drawable.love, R.drawable.mouse,

27. R.drawable.music};

28. private String[] goodsNames = {"蛋糕", "礼物",

29. "邮票", "爱心", "鼠标", "音乐CD"};

30. private String[] goodsDetails = {

31. "蛋糕:好好吃。",

32. "礼物:礼轻情重。",

33. "邮票:环游世界。",

34. "爱心:世界都有爱。",

35. "鼠标:反应敏捷。",

36. "音乐CD:酷我音乐。"};

37.

38. /** Called when the activity is first created. */

39. @Override

40. public void onCreate(Bundle savedInstanceState) {

41. super.onCreate(savedInstanceState);

42. setContentView(R.layout.main);

43.

44. listView = (ListView)findViewById(R.id.list_goods);

45. imgbt_sum = (ImageButton) findViewById(R.id.imgbt_sum);

46. imgbt_sum.setOnClickListener(new ClickEvent());

47. listItems = getListItems();

48. listViewAdapter = new ListViewAdapter(this, listItems); //创建适配

49. listView.setAdapter(listViewAdapter);

50. }

51.

52. /**

53. * 初始化商品信息

54. */

55. private List<Map<String, Object>> getListItems() {

56. List<Map<String, Object>> listItems = new ArrayList<Map<String, Obje

ct>>();

57. for(int i = 0; i < goodsNames.length; i++) {

58. Map<String, Object> map = new HashMap<String, Object>();

59. map.put("image", imgeIDs[i]); //图片资源

60. map.put("title", "物品名称:"); //物品标题

61. map.put("info", goodsNames[i]); //物品名称

62. map.put("detail", goodsDetails[i]); //物品详情

63. listItems.add(map);

64. }

65. return listItems;

66. }

67.

68. class ClickEvent implements OnClickListener{

69.

android开发总结

70. @Override

71. public void onClick(View v) {

72. // TODO Auto-generated method stub

73. String goodsList = "";

74. for(int i = 0; i < listItems.size(); i++) {

75. goodsList += listViewAdapter.hasChecked(i)? goodsNames[i] +

" ": "";

76. }

77. new AlertDialog.Builder(MyListView.this)

78. .setTitle("购物清单:")

79. .setMessage("你好,你选择了如下商品:\n" + goodsList)

80. .setPositiveButton("确定", null)

81. .show(); 82. }

83.

84. }

85. }

1. package

2.

3. import java.util.List;

4. import java.util.Map;

5.

6. import

7. import

8. import

9. import

10. import

11. import

12. import

13. import

14. import

15. import

16. import

17. import

18. import

19.

20. public class ListViewAdapter extends BaseAdapter {

21. private Context context; //运行上下文

22. private List<Map<String, Object>> listItems; //商品信息集合

23. private LayoutInflater listContainer; //视图容器

24. private boolean[] hasChecked; //记录商品选中状态

25. public final class ListItemView{ //自定义控件集合

26. public ImageView image;

27. public TextView title;

28. public TextView info;

29. public CheckBox check;

30. public Button detail;

31. }

32.

33.

34. public ListViewAdapter(Context context, List<Map<String, Object>> listIt

ems) {

35. this.context = context;

36. listContainer = LayoutInflater.from(context); //创建视图容器并设置上

下文

37. this.listItems = listItems;

38. hasChecked = new boolean[getCount()];

39. }

40.

41. public int getCount() {

42. // TODO Auto-generated method stub

43. return listItems.size();

44. }

45.

46. public Object getItem(int arg0) {

47. // TODO Auto-generated method stub

48. return null;

49. }

50.

51. public long getItemId(int arg0) {

52. // TODO Auto-generated method stub

53. return 0;

54. }

55.

56. /**

57. * 记录勾选了哪个物品

58. * @param checkedID 选中的物品序号

59. */

60. private void checkedChange(int checkedID) {

61. hasChecked[checkedID] = !hasChecked[checkedID];

62. }

63.

64. /**

65. * 判断物品是否选择

66. * @param checkedID 物品序号

67. * @return 返回是否选中状态

68. */

69. public boolean hasChecked(int checkedID) {

70. return hasChecked[checkedID];

71. }

72.

73. /**

74. * 显示物品详情

75. * @param clickID

76. */

77. private void showDetailInfo(int clickID) {

78. new AlertDialog.Builder(context)

79. .setTitle("物品详情:" + listItems.get(clickID).get("info"))

80. .setMessage(listItems.get(clickID).get("detail").toString())

81. .setPositiveButton("确定", null)

82. .show();

83. }

84.

85.

86. /**

87. * ListView Item设置

88. */

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

90. // TODO Auto-generated method stub

91. Log.e("method", "getView");

92. final int selectID = position;

93. //自定义视图

94. ListItemView listItemView = null;

95. if (convertView == null) {

96. listItemView = new ListItemView();

97. //获取list_item布局文件的视图

98. convertView = listContainer.inflate(R.layout.list_item, null);

99. //获取控件对象

100. listItemView.image = (ImageView)convertView.findViewById(R.id.i

mageItem);

101. listItemView.title = (TextView)convertView.findViewById(R.id.ti

tleItem);

102. listItemView.info = (TextView)convertView.findViewById(R.id.inf

oItem);

103. listItemView.detail= (Button)convertView.findViewById(R.id.deta

ilItem);

104. listItemView.check = (CheckBox)convertView.findViewById(R.id.ch

eckItem);

105. //设置控件集到convertView

106. convertView.setTag(listItemView);

107. }else {

108. listItemView = (ListItemView)convertView.getTag();

109. }

110. // Log.e("image", (String) listItems.get(position).get("title")); //

测试

111. // Log.e("image", (String) listItems.get(position).get("info")); 112.

113. //设置文字和图片

114. listItemView.image.setBackgroundResource((Integer) listItems.get(

115. position).get("image"));

116. listItemView.title.setText((String) listItems.get(position) 117. .get("title"));

118. listItemView.info.setText((String) listItems.get(position).get("inf

o"));

119. listItemView.detail.setText("商品详情");

120. //注册按钮点击时间爱你

121. listItemView.detail.setOnClickListener(new View.OnClickListener() {

122. @Override

123. public void onClick(View v) {

124. //显示物品详情

125. showDetailInfo(selectID);

126. }

127. });

128. // 注册多选框状态事件处理

129. listItemView.check

130. .setOnCheckedChangeListener(new CheckBox.OnCheckedChangeLis

tener() {

131. @Override

132. public void onCheckedChanged(CompoundButton buttonView,

133. boolean isChecked) {

134. //记录物品选中状态

135. checkedChange(selectID);

136. }

137. });

138.

139. return convertView;

140. }

141. }

至于,如何实现系统自带的适配器,如ArrayAdapter、SimpleAdapter和SimpleCursorAdapter等,有机会再补充。

更多相关推荐:
《Android应用开发》个人总结报告

Android应用开发个人总结报告刚开始接触Android感觉到它很有意思在界面开发上和web也可以形成了相通的架构更加方便视觉上也是非常的酷在前期我通过的大量的AndroidSDK开发范例大全中的例子以及An...

android开发总结

Android开发简介Android应用程序的五大基本组件Activity应用表示层基类Activity一个活动表示一个可视化的用户界面关注一个用户从事的事件例如一个活动可能表示一个用户可选择的菜单项列表或者可...

《Android项目开发实训》项目总结报告

实训报告姓名祝新学号1144131专业软件技术课程名称android实训项目名称闹铃指导教师王皓实训日期20xx年10月28日至20xx年1月2日20xx年1月2日Android项目开发实训总结报告目录第一章概...

android软件开发工程师转正个人总结

个人总结我于20xx年x月x日进入公司,根据公司的需要,目前担任Android软件工程师一职,负责综合代维,考务通手机客户端的开发工作。将近3个月的时候在这个新的工作环境我收获颇深。开始让我独立完成整个项目,…

Android开发总结

出来工作半年多了没啥好交代的就说说自己半年来的Android开发经历1IDE这半年来从Eclipse到AndroidStudio经历了两个IDE在这里做一下简单的评价如果真要说AndroidStudio是基本上...

Android开发知识点总结

如何获取标题栏和状态栏高度1获取状态栏高度decorView是window中的最顶层view可以从window中获取到decorView然后decorView有个getWindowVisibleDisplayF...

Qualcomm平台android开发总结

1高通平台android开发总结711搭建高通平台环境开发环境712搭建高通平台环境开发环境7121高通android智能平台概述71211什么是L4REXBREWAMSS以及相互之间的关系7122选择合适的源...

Android 实训总结

Android实训总结XXXX三周的Android实训已接近尾声在这短暂的三周之内有成功有失败有喜悦有辛酸在实训老师的带领下我学会了很多我们小组在实训老师的协助下最终成功的完成实训项目实训前二周由于我在java...

android开发实习报告总结

Android开发实习总结有一名话叫做不经过风雨怎么见彩虹我想改一下不真正进入社会怎能了解社会呢在这次实习中给我收获最大的是我觉得很多工作需要我去摸索和探讨要不怕吃苦勇于激流勇进有的工作虽然单挑又重复但这是磨练...

android开发总结

Android图片平铺效果方法一XML方式平铺首先两个单词的中文意思分别是dither抖动和tileMode平铺1先来介绍tileMode平铺tileMode属性就是用于定义背景的显示模式disabled默认值...

Android手机游戏开发知识点总结

Android手机游戏知识点总结Android手机游戏开发学习笔记第一部分其实游戏就是让状态机不断的让Canvas在View上画你想要的东西这个状态机包括内部的执行还包括外部的输入Android开发的MVC模式...

【嵌入式】android教程JNI开发疑点总结

android教程JNI开发疑点总结很多Android新手对于JNI开发过程中的疑问不是很清楚根据android123163com邮箱中反馈的内容我们整理如下1JNI中什么情况才处理jstringjintjob...

android开发总结(30篇)