如果您想了解AndroidPaint类详解的相关知识,那么本文是一篇不可错过的文章,我们将对androidcupsprint进行全面详尽的解释,并且为您提供关于AndroidActivity类详解、A
如果您想了解Android Paint类详解的相关知识,那么本文是一篇不可错过的文章,我们将对android cups print进行全面详尽的解释,并且为您提供关于Android Activity类详解、Android IPC进程间通信详解最新AndroidStudio的AIDL操作)、android Paint 设置颜色问题?、Android Studio入门:Android应用界面详解(中)(Android控件详解、AdapterView及其子类)的有价值的信息。
本文目录一览:- Android Paint类详解(android cups print)
- Android Activity类详解
- Android IPC进程间通信详解最新AndroidStudio的AIDL操作)
- android Paint 设置颜色问题?
- Android Studio入门:Android应用界面详解(中)(Android控件详解、AdapterView及其子类)
Android Paint类详解(android cups print)
Android Paint类详解
- 概述
- 提供了三种初始化方法
- 常用方法
- 线条样式
- 着色渐变
- 颜色优化
- 阴影或者上层效果
- 获取路径
概述
android中绘制特定图案类似显示中的绘画需要画笔和画纸,为此android提供了Paint和Canvas。
Paint和Canvas分别代表画笔和画布。
Paint类似画笔,保存着绘制文本,图形,图片的样式和颜色信息。(颜色,宽度,粗细,透明度,字体样式,字体大小)。
大体上可以分为两类,一类与图形绘制相关,一类与文本绘制相关
提供了三种初始化方法
1.Paint()
2.Paint(int flags)
3.Paint(Paint paint)
常用方法
方法 | 说明 |
---|---|
setTextSize(float textSize) 设置字体大小;单位是px | 例:paint.setTextSize(20); 注意:如果是dp要注意转换 |
setFakeBoldText(boolean fakeBoldText) 实现粗体文字 | 例:paint.setFakeBoldText (true); |
setTextSkewX(float skewX) 设置斜体文字 | 例: paint.setTextSkewX(20); |
setTypeface(Typeface typeface) 设置字体样式 | typeface有以下5种: 1.ypeface.DEFAULT:默认字体 2.Typeface.DEFAULT_BOLD:加粗字体 3.Typeface.MONOSPACE:monospace字体 4.Typeface.SANS_SERIF:sans字体 5.Typeface.SERIF:serif字体 例:paint.setTypeface(Typeface.SANS_SERIF); |
setTextScaleX(float scaleX) 设置绘制文字x轴的缩放比例,实现文字的拉伸的效果 | 例:paint.setTextScaleX((float) 0.7); |
setStrikeThruText(boolean strikeThruText) 设置文字带有删除线的效果 | 例:paint.setStrikeThruText(true); |
setUnderlineText(boolean underlineText) 设置带有下划线的文字效果 | 例:paint.setUnderlineText(true); |
setTextAlign() 设置字体对齐方式;是相对于开始绘制的坐标点 | 有以下三种对齐方式: 1.Paint.Align.LEFT 左对齐 2.Paint.Align.CENTER 居中 3.Paint.Align.RIGHT 右对齐 例:paint.setTextAlign(Paint.Align.RIGHT) |
setSubpixelText(boolean subpixelText) 提升文本在LCD屏幕上的显示效果 | 例:paint.setSubpixelText(true) |
setColor(int a) 设置画笔颜色 | 例:paint.setColor(Color.RED); |
setARGB(int a,int r,int g,int b) 设置alpha | red,green,blue;取值范围都是 0~255 例:paint.setARGB(100,0,0,0); |
setstrokeWidth(float width) 设置画笔宽度;单位px | 例:paint.setstrokeWidth(10); |
setAlpha(int a) 设置透明度 | 取值得范围0到255; 0是透明,255不透明 例:paint.setAlpha(255); 注意:需要先调用setColor(),再调用setAlpha才会生效,否则将会被覆盖,因为setColor中包含了alpha |
setAntiAlias(boolean) 抗锯齿使边界更顺滑;消耗较大资源 | 例:paint.setAntiAlias(true); |
setStyle(Paint.Style style) 设置填充样式; | 有以下三种形式: 1.Paint.Style.FILL 填充内部,会把闭合区域填充颜色 2.Paint.Style.FILL_AND_stroke填充内部和描边 3.Paint.Style.stroke 仅描边,仅仅绘制边界 例:paint.setStyle(Paint.Style.FILL); |
线条样式
方法 | 说明 |
---|---|
setstrokeJoin(Paint.Join join) 连接点的样式 | 有以下三种形式: 1.Join.MITER(结合处为锐角) 2.Join.Round(结合处为圆弧) 3.Join.BEVEL(结合处为直线) 例:paint.setstrokeJoin(Paint.Join.BEVEL); |
setstrokeCap(Paint.Cap cap) 画笔的样式(落笔,收笔时) | 有以下三种形式: 1.Cap.ROUND(圆形) 2.Cap.SQUARE(方形) 3.Cap.BUTT(无) 例:paint.setstrokeCap(Paint.Cap.ROUND); |
setPathEffect(PathEffect effect) 给path设置样式(效果) | 一般使用其六个子类: 1.CornerPathEffect 2.DashPathEffect 3.discretePathEffect 4.PathDashPathEffect 5.ComposePathEffect 6.SumPathEffect 例: PathEffect pathEffect= new CornerPathEffect(20); paint.setPathEffect(pathEffect); |
CornerPathEffect(float radius) 将Path的各个连接线段之间的夹角用一种更平滑的方式连接,类似于圆弧与切线的效果 | radius:指定圆弧的半径 例: CornerPathEffect cornerPathEffect = new CornerPathEffect(50); mPaint.setPathEffect(cornerPathEffect); |
DashPathEffect(float[] intervals, float phase) 将Path的线段虚线化 | intervals:为虚线的ON和OFF的数组,数组中元素数目需要 >= 2个 phase:为绘制时的偏移量,动态改变其值会让路径产生动画的效果 例: DashPathEffect dashPathEffect= new DashPathEffect(new float[] {20, 10}, 1); mPaint.setPathEffect(dashPathEffect); |
PathDashPathEffect(Path shape, float advance, float phase, PathDashPathEffect.Style style) 使用Path图形来填充当前的路径 PathDashPathEffect和DashPathEffect是类似的,不同的是PathDashPathEffect可以自己定义路径虚线的样式 | shape:填充图形 advance:每个图形间的间隔 phase:为绘制时的偏移量,动态改变其值会让路径产生动画的效果 style:是该类自由的枚举值,有三种情况: 1.ROTATE:线段连接处的图形转换旋转到与下一段移动方向相一致的角度进行连接 2.MORPH:图形会以发生拉伸或压缩等变形的情况与下一段相连接 3.TRANSLATE:图形会以位置平移的方式与下一段相连接 例: PathDashPathEffect pathDashPathEffect= new PathDashPathEffect(path, 12, phase, PathDashPathEffect.Style.ROTATE); mPaint.setPathEffect(pathDashPathEffect); |
discretePathEffect(float segmentLength, float deviation) 打散Path的线段,使得在原来路径的基础上发生打散效果 在路径上绘制很多“杂点”的突出来模拟一种类似生锈铁丝的效果 | segmentLength:指定最大的段长 deviation:为绘制时的偏离量 例: discretePathEffect discretePathEffect= new discretePathEffect(3.0F, 5.0F); mPaint.setPathEffect(discretePathEffect); |
ComposePathEffect(PathEffect outerpe, PathEffect innerpe) 组合效果,会首先将innerpe变现出来,接着在innerpe的基础上来增加outerpe效果 | 例: CornerPathEffect cornerPathEffect = new CornerPathEffect(50); DashPathEffect dashPathEffect= new DashPathEffect(new float[] {20, 10}, 1) ComposePathEffect composePathEffect= new ComposePathEffect(cornerPathEffect ,dashPathEffect) |
SumPathEffect(PathEffect first, PathEffect second) 叠加效果,和ComposePathEffect不同,在表现时会将两个参数的效果都独立的表现出来, 接着将两个效果简单的重叠在一起显示出来 | 例: CornerPathEffect cornerPathEffect = new CornerPathEffect(50); DashPathEffect dashPathEffect= new DashPathEffect(new float[] {20, 10}, 1) SumPathEffect sumPathEffect= new SumPathEffect(cornerPathEffect ,dashPathEffect) |
着色渐变
方法 | 说明 |
---|---|
渐变模式 | ABAB型:两种颜色重复变化,通过 TileMode 类的 REPEAT 常量来表示; ABBA型:两种颜色镜像变化,通过 TileMode 类的 MIRROR 常量来表示; AABB型:两种颜色只出现一次,通过 TileMode类的 CLAMP 常量来表示 |
setShader(Shader shader) 使用已定义的Shader对象 | 例: paint.setShader(linearGradient); |
LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, TileMode tile) 线性渐变 | x0、y0:用于决定线性方向的起始点的坐标(x0,y0) x1、y1:用于决定线性方向的终止点的坐标(x1,y1) color0:第一种颜色 color1:第二种颜色 tile:渐变模式 例: LinearGradient linearGradient = new LinearGradient(100,100,200,100,Color.RED,Color.BLUE,Shader.TileMode.MIRROR) ; paint.setShader(linearGradient); |
LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[], TileMode tile) 线性渐变 | x0、y0:用于决定线性方向的起始点的坐标(x0,y0) x1、y1:用于决定线性方向的终止点的坐标(x1,y1) color0[]:多种颜色 positions[]:颜色的位置(比例) tile:渐变模式 例: LinearGradient linearGradient = new LinearGradient(100,100,800,100,new int [] {Color.RED,Color.YELLOW,Color.BLUE},new float[]{0,0.5f,1},Shader.TileMode.CLAMP) ;; paint.setShader(linearGradient); 注意:参数 colors[] 和 positions[] 都是数组,前者用于指定多种颜色,后者用于指定每种颜色的起始比例位置。positions 数组中的元素个数与 colors 要相同 |
RadialGradient(float x, float y, float radius, int color0, int color1, TileMode tile) 径向渐变是以指定的点为中心,向四周以渐变颜色进行圆周扩散 | x、y:中心点坐标 radius:渐变半径 color0:起始颜色 color1:结束颜色 tile:渐变模式 例: RadialGradient radialGradient = new RadialGradient(400,400,300,Color.RED,Color.BLUE,Shader.TileMode.CLAMP) ; paint.setShader(radialGradient); |
RadialGradient(float x, float y, float radius, int colors[], float positions[], TileModetile) 径向渐变是以指定的点为中心,向四周以渐变颜色进行圆周扩散 | x、y:中心点坐标 radius:渐变半径 colors[]:多种颜色 positions[]:颜色的位置(比例) tile:渐变模式 例: radialGradient = new RadialGradient(400,1200,300,new int[]{Color.RED,Color.YELLOW,Color.GRAY,Color.BLUE},new float[]{0,0.4f,0.8f,1},Shader.TileMode.CLAMP) ; paint.setShader(radialGradient); 注意:参数 colors[] 和 positions[] 都是数组,前者用于指定多种颜色,后者用于指定每种颜色的起始比例位置。positions 数组中的元素个数与 colors 要相同 |
SweepGradient(float cx, float cy, int color0, int color1) 扫面渐变 ,类似于军事雷达一样,不断围绕圆心扫描 | cx、cy:圆点坐标 color0:起始颜色 color1:结束颜色 例: SweepGradient sweepGradient = new SweepGradient(400,400,Color.RED,Color.BLUE) paint.setShader(sweepGradient); |
SweepGradient(float cx, float cy, int colors[], float positions[]) 支持多种颜色的扫描渐变 | x、y:中心点坐标 colors[]:多种颜色 positions[]:颜色的位置(比例);null为均分 例: sweepGradient = new SweepGradient(400,1200,new int[]{Color.RED,Color.YELLOW,Color.GRAY,Color.BLUE},null) ; paint.setShader(sweepGradient); 注意:参数 colors[] 和 positions[] 都是数组,前者用于指定多种颜色,后者用于指定每种颜色的起始比例位置。positions 数组中的元素个数与 colors 要相同 |
BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY) 位图渐变 | bitmap:使用的位图 tileX: 位图在上X轴方向上的模式 tileY:位图在上Y轴方向上的模式 例: bitmapShader = new BitmapShader(bitmap, Shader.TileMode.MIRROR,Shader.TileMode.REPEAT); paint.setShader(bitmapShader ); |
ComposeShader (Shader shaderA, Shader shaderB, PorterDuff.Mode mode) 使两个Shader组合在一起作为一个新Shader | shaderA:第一个Shader对象 shaderB:第二个Shader对象 mode:混合效果如图 radialGradient = new RadialGradient(200, 200, 200, Color.RED, Color.GREEN, Shader.TileMode.CLAMP); sweepGradient = new SweepGradient(200, 200, new int[] { Color.GREEN, Color.WHITE, Color.GREEN }, null); composeShader =new ComposeShader (radialGradient ,sweepGradient ,PorterDuff.Mode.DARKEN ) paint.setShader(composeShader ); |
ComposeShader (Shader shaderA, Shader shaderB, Xfermode mode) 使两个Shader组合在一起作为一个新Shader() 此方法已过时 | shaderA:第一个Shader对象 shaderB:第二个Shader对象 mode:混合效果 |
颜色优化
方法 | 说明 |
---|---|
setDither(boolean dither) 否使用图像抖动处理,绘制的图片颜色更加平滑和饱满在实际的应用场景中,抖动更多的作用是在图像降低色彩深度绘制时,避免出现大片的色带与色块 | 例:paint.setDither(true); |
setFilterBitmap(boolean filter) 线性过滤;如果该项设置为true,结果图像显得更加平滑 | 例:paint.setFilterBitmap(true); |
阴影或者上层效果
方法 | 说明 |
---|---|
setShadowLayer(float radius, float dx, float dy, int shadowColor) 设置阴影;在绘制层下方的附加效果 | radius:设置角度 dx:x轴偏移量(正负代表右左) dy:y轴偏移量(正负代表右左) shadowColor: 阴影颜色 例:paint.setShadowLayer(10, 0, 0, Color.BLUE); |
setMaskFilter(MaskFilter maskfilter) 在绘制层上方使用附加效果 | maskfilter:MaskFilter对象 例:paint.setMaskFilter(paint.setMaskFilter(blurMaskFilterOUTER)) |
BlurMaskFilter(float radius, BlurMaskFilter.Blur style) 指定了一个模糊的样式和半径来处理Paint的边缘,让目标部分模糊不清;在绘制层下方的附加效果 | radius:模糊半径 style它有四种如下模式: 1.norMAL: 内外都模糊绘制 2.soLID: 内部正常绘制,外部模糊 3.INNER: 内部模糊,外部不绘制 4.OUTER: 内部不绘制,外部模糊 例: BlurMaskFilter blurMaskFilterOUTER = new BlurMaskFilter(50,BlurMaskFilter.Blur.OUTER); paint.setMaskFilter(blurMaskFilterOUTER) |
embossMaskFilter(float[] direction, float ambient, float specular, float blurRadius) 指定了光源的方向和环境光强度来添加浮雕效果,是让目标部分有凹凸的水印图案 | direction :是一个 3 个元素的数组,指定了光源的方向 ambient :是环境光的强度,数值范围是 0 到 1 specular :是炫光的系数 blurRadius :是应用光线的范围 例: embossMaskFilter embossMaskFilter = new embossMaskFilter(new float[]{10, 10, 10}, 0.1f, 5, 5); paint.setMaskFilter(embossMaskFilter); |
获取路径
方法 | 说明 |
---|---|
getFillPath(Path src, Path dst) 获取实际路径 | src :原路径 dst :实际路径的保存位置 |
getTextPath(String text, int start, int end, float x, float y, Path path) 获取文字路径 | Text:文字 Start:开始获取位置 End:结束获取的位置 X:文字所在的X坐标 Y:文字所在的Y坐标 Path:保存的路径 例: String text = “测试文本 Test”; Path desPath = new Path(); srcPaint.getTextPath(text,0,text.length(),50,100,desPath); |
Android Activity类详解
1.java.lang.Object
2.android.content.Context
3.android.app.ApplicationContext
4.android.app.Activity
activity是单独的,用于处理用户操作。几乎所有的activity都要和用户打交道,所以activity类创建了一个窗口,开发人员可以通过setContentView(View)接口把UI放到activity创建的窗口上,当activity指向全屏窗口时,也可以用其他方式实现:作为漂浮窗口(通过windowIsFloating的主题集合),或者嵌入到其他的activity(使用ActivityGroup)。大部分的Activity子类都需要实现以下两个接口:
onCreate(Bundle)接口是初始化activity的地方. 在这儿通常可以调用setContentView(int)设置在资源文件中定义的UI, 使用findViewById(int) 可以获得UI中定义的窗口.
onPause()接口是使用者准备离开activity的地方,在这儿,任何的修改都应该被提交(通常用于ContentProvider保存数据).
为了能够使用Context.startActivity(),所有的activity类都必须在AndroidManifest.xml文件中定义有相关的“activity”项。
activity类是Android 应用生命周期的重要部分。
Activity生命周期
在系统中的Activity被一个Activity栈所管理。当一个新的Activity启动时,将被放置到栈顶,成为运行中的Activity,前一个Activity保留在栈中,不再放到前台,直到新的Activity退出为止。
Activity有四种本质区别的状态:
在屏幕的前台(Activity栈顶),叫做活动状态或者运行状态(active or running)
如果一个Activity失去焦点,但是依然可见(一个新的非全屏的Activity 或者一个透明的Activity 被放置在栈顶),叫做暂停状态(Paused)。一个暂停状态的Activity依然保持活力(保持所有的状态,成员信息,和窗口管理器保持连接),但是在系统内存极端低下的时候将被杀掉。
如果一个Activity被另外的Activity完全覆盖掉,叫做停止状态(Stopped)。它依然保持所有状态和成员信息,但是它不再可见,所以它的窗口被隐藏,当系统内存需要被用在其他地方的时候,Stopped的Activity将被杀掉。
如果一个Activity是Paused或者Stopped状态,系统可以将该Activity从内存中删除,Android系统采用两种方式进行删除,要么要求该Activity结束,要么直接杀掉它的进程。当该Activity再次显示给用户时,它必须重新开始和重置前面的状态。
下面的图显示了Activity的重要状态转换,矩形框表明Activity在状态转换之间的回调接口,开发人员可以重载实现以便执行相关代码,带有颜色的椭圆形表明Activity所处的状态。
在上图中,Activity有三个关键的循环:
整个的生命周期,从onCreate(Bundle)开始到onDestroy()结束。Activity在onCreate()设置所有的“全局”状态,在onDestory()释放所有的资源。例如:某个Activity有一个在后台运行的线程,用于从网络下载数据,则该Activity可以在onCreate()中创建线程,在onDestory()中停止线程。
可见的生命周期,从onStart()开始到onStop()结束。在这段时间,可以看到Activity在屏幕上,尽管有可能不在前台,不能和用户交互。在这两个接口之间,需要保持显示给用户的UI数据和资源等,例如:可以在onStart中注册一个IntentReceiver来监听数据变化导致UI的变动,当不再需要显示时候,可以在onStop()中注销它。onStart(),onStop()都可以被多次调用,因为Activity随时可以在可见和隐藏之间转换。
前台的生命周期,从onResume()开始到onPause()结束。在这段时间里,该Activity处于所有Activity的最前面,和用户进行交互。Activity可以经常性地在resumed和paused状态之间切换,例如:当设备准备休眠时,当一个Activity处理结果被分发时,当一个新的Intent被分发时。所以在这些接口方法中的代码应该属于非常轻量级的。
Activity的整个生命周期都定义在下面的接口方法中,所有方法都可以被重载。所有的Activity都需要实现onCreate(Bundle)去初始化设置,大部分Activity需要实现onPause()去提交更改过的数据,当前大部分的Activity也需要实现onFreeze()接口,以便恢复在onCreate(Bundle)里面设置的状态。
public class Activity extends ApplicationContext {
protected void onCreate(Bundle icicle);
protected void onStart();
protected void onRestart();
protected void onResume();
protected void onFreeze(Bundle outIcicle);
protected void onPause();
protected void onStop();
protected void onDestroy();
}
http://blog.sina.com.cn/s/blog_59f3b7970100em5a.html
Android IPC进程间通信详解最新AndroidStudio的AIDL操作)
前言
前面梳理了Android的线程间的通信《Thread、Handler和HandlerThread关系何在?》 ,这些都是在同一个进程中,那进程间的通信,或者说不同的应用间的通信该如何实现呢?这个时候就要用到AIDL(Android Interface DeFinition LanguageAndroid接口定义语言 )。
使用方法(AndroidStudio)
我发现现在AIDL的教程基本上还是eclipse的,但是在AndroidStudio里面使用AIDL还是有一些不同的,来看看怎么用,首先新建一个工程当做server服务端:
创建好后在任意文件夹右键New-->AIDL-->AIDL File,编辑文件名后会自动在src/main目录下面新建aidl文件夹,包的目录结构如下:
main
aidl
com.example.tee.testapplication.aidl
java
com.example.tee.testapplication
res
AndroidManifest.xml
自动生成的aidl文件如下:
// AidlInterface.aidl package com.example.tee.testapplication.aidl; // Declare any non-default types here with import statements interface AidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt,long aLong,boolean aBoolean,float aFloat,double aDouble,String aString); }
我们可以看到aidl文件的代码格式跟java很像,支持java的基础类型以及List、Map等,如果是自定义类的话需要手动导入,我们后面再说,先来最简单的,新建一个 IMyAidlInterface.aidl文件,修改如下:
package com.example.tee.testapplication.aidl; interface IMyAidlInterface { String getValue(); }
在接口中定义一个getValue方法,返回一个字符串,现在可以编译一下工程,找到app/build/generated/source/aidl/debug目录,在我们应用包名下会发现生成了一个Interface类,名字跟我们定义的aidl的文件名字一样,这说明其实aidl文件在最后还是会转换成接口来实现,而且这个文件不需要我们维护,在编译后自动生成。
然后新建一个类继承Service:
public class MAIDLService extends Service{ public class MAIDLServiceImpl extends IMyAidlInterface.Stub{ @Override public String getValue() throws remoteexception { return "get value"; } } @Nullable @Override public IBinder onBind(Intent intent) { return new MAIDLServiceImpl(); } }
在MAIDLService类中定义一个内部类继承IMyAidlInterface.Stub,并且重写我们在aidl也就是在接口中定义的getValue方法,返回字符串get value。
到了这里,我们就新建好了这个服务端,作用是在调用后返回一个字符串,最后在AndroidManifest文件中声明:
<service android:name=".MAIDLService" android:process=":remote"//加上这句的话客户端调用会创建一个新的进程 android:exported="true"//默认就为true,可去掉,声明是否可以远程调用 > <intent-filter> <category android:name="android.intent.category.DEFAULT" /> <action android:name="com.example.tee.testapplication.aidl.IMyAidlInterface" /> </intent-filter> </service>
android:process=":remote"这一行的作用是声明是否调用时新建进程,接下来写客户端代码,新建一个工程,将刚才创建的aidl文件拷贝到这个工程中,注意同样也是要放在aidl文件夹下,然后在MainActivity中编写代码如下:
public class MainActivity extends AppCompatActivity { private TextView mValueTV; private IMyAidlInterface mAidlInterface = null; private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name,IBinder service) { mAidlInterface = IMyAidlInterface.Stub.asInterface(service); } @Override public void onServicedisconnected(ComponentName name) { } }; @Override protected void onCreate(Bundle savedInstanceState) { Intent intent = new Intent("com.example.tee.testapplication.aidl.IMyAidlInterface"); bindService(intent,mServiceConnection,BIND_AUTO_CREATE); mValueTV = (TextView) findViewById(R.id.tv_test_value); mValueTV.setonClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { mValueTV.setText(mAidlInterface.getValue()); } catch (remoteexception e) { e.printstacktrace(); } } }); } @Override protected void onDestroy() { if(mAidlInterface != null){ unbindService(mServiceConnection); } super.onDestroy(); } }
注意这里新建Intent的传入的参数字符串是在manifest里面自定义的action标签,并且在onDestroy记得取消绑定服务。
执行结果就是我们在点击TextView时会显示服务端给我们返回的get value字符串
自定义的对象
刚才我们使用的是基础类型String,在使用我们自己定义的类的时候用上面的方法是不行的,用我们自定义的类需要手动导入,修改刚才我们创建的作为服务端的工程
首先在开始生成的aidl包下(所有aidl相关的文件都要放在这个包下)新建Student.java
public class Student implements Parcelable{ public String name; public int age; protected Student(Parcel in) { readFromParcel(in); } public Student() { } public static final Creator<Student> CREATOR = new Creator<Student>() { @Override public Student createFromParcel(Parcel in) { return new Student(in); } @Override public Student[] newArray(int size) { return new Student[size]; } }; @Override public int describeContents() { return 0; } @Override public void writetoParcel(Parcel dest,int flags) { dest.writeInt(age); dest.writeString(name); } public void readFromParcel(Parcel in){ age = in.readInt(); name = in.readString(); } @Override public String toString() { return String.format(Locale.ENGLISH,"STUDENT[%s:%d]",name,age); } }
需要实现Parcelable序列化接口,AndroidStudio会自动生成静态内部类CREATOR和describeContents方法,这些部分我们都不需要修改,用自动生成的就好。然后重写writetoParcel方法,自定义readFromParcel方法,注意这两个方法里面的属性顺序必须一致,一个是写入,一个是读取。在构造方法Student(Parcel in)中调用readFromParcel(in)方法。
接下来新建Student.aidl文件(也是在aidl包中):
// Student.aidl package com.example.tee.testapplication.aidl; // Declare any non-default types here with import statements parcelable Student;
注意这里Student前面的关键字parcelable首字母是小写哦,再修改IMyAidlInterface.aidl文件如下:
// IMyAidlInterface.aidl package com.example.tee.testapplication.aidl; // Declare any non-default types here with import statements import com.example.tee.testapplication.aidl.Student; interface IMyAidlInterface { Student getStudent(); void setStudent(in Student student); String getValue(); }
定义了两个方法,一个是设置Student,一个是获取Student,在setStudent这个方法注意参数在类型前面有个in关键字,在aidl里参数分为in输入,out输出
现在在MAIDLService.java中重写新加的两个方法:
private Student mStudent; public class MAIDLServiceImpl extends IMyAidlInterface.Stub{ @Override public Student getStudent() throws remoteexception { return mStudent; } @Override public void setStudent(Student student) throws remoteexception { mStudent = student; } @Override public String getValue() throws remoteexception { return "get value : " + Thread.currentThread().getName() + Thread.currentThread().getId(); } }
服务端代码修改完毕,来到客户端工程,同样要把刚才的aidl包下的文件拷贝覆盖过来,保持两边一致,然后在MainActivity.java中修改如下:
mValueTV = (TextView) findViewById(R.id.tv_test_value); mStudentTV = (TextView) findViewById(R.id.tv_test_student); mValueTV.setonClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { mValueTV.setText(mAidlInterface.getValue()); } catch (remoteexception e) { e.printstacktrace(); } } }); mStudentTV.setonClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { Student student = new Student(); student.age = 10; student.name = "Tom"; mAidlInterface.setStudent(student); mStudentTV.setText(mAidlInterface.getStudent().toString()); } catch (remoteexception e) { e.printstacktrace(); } } });
现在编译工程,会发现工程会报错,找不到类Student,我们需要在app目录下的build.gradle文件添加代码如下:
android { sourceSets { main { manifest.srcFile 'src/main/AndroidManifest.xml' java.srcDirs = ['src/main/java','src/main/aidl'] resources.srcDirs = ['src/main/java','src/main/aidl'] aidl.srcDirs = ['src/main/aidl'] res.srcDirs = ['src/main/res'] assets.srcDirs = ['src/main/assets'] } } }
也就是指定一下文件目录,现在再编译就没有问题了
总结
Android的IPC使用起来还是挺简单的,AIDL文件的语法也跟我们平时使用接口的时候很相似,但是它只支持基础类型,只能引用AIDL文件,需要使用自定义类的时候要稍微麻烦一点。
以上就是对Android IPC 进程通信的资料整理,后续继续补充相关资料谢谢大家对本站的支持!
android Paint 设置颜色问题?
想做一个画板,Paint 每一次设置颜色都会改变原来已经画好的颜色,怎么样能让已经画好的不被Paint 新设置的颜色改变覆盖??望高手指点
Android Studio入门:Android应用界面详解(中)(Android控件详解、AdapterView及其子类)
Android Studio入门:Android应用界面详解(上)(View、布局管理器)
文章目录
- Android控件详解
- TextView(文本框)
- EditText(输入框)
- Button(按钮)
- ImageView(图像视图)
- RadioButton(单选按钮)和CheckBox(多选框)
- ProgressBar(进度条)
- SeekBar(拖动条)
- AdapterView及其子类
- ListView和ListActivity
- Adapter接口
Android控件详解
在学习过安卓的布局方式以后,要进行UI界面的设计,还需要熟练掌握各种控件的应用。开始一个界面的设计都是先创建容器,然后不断地向容器中添加组件,最后形成一个UI界面。掌握这些基本用户界面组件是学好Android编程的基础。接下来将详细地介绍各个组件如何地使用。
TextView(文本框)
TextView直接继承了View,它还是EditText和Button两个UI组件类的父类。
TextView的作用就是在界面上显示文字,通过在布局文件当中或者在Activity中修改文字的内容。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="red">#ff0000</color>
</resources>
values/dimens.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="paddingLeft">555dp</dimen>
</resources>
EditText(输入框)
EditText与TextView非常的相似,许多XML属性都能共用,与TextView的最大区别就是EditText能够接受用户的输入。
EditText的重要属性就是inputType,该属性相当于Html的<input…/>元素的type属性,用于将EditText设置为指定类型的输入组件,如手机号、密码、日期等。还有一个属性是当提示用户当前文本框要输入的内容是什么,使用android:hint=“”来提示用户,当用户点击文本框这些文字就会消失。
inputType属性在EditText输入值时, 启动虚拟键盘的风格。有时需要虚拟键盘
只能输入字符或数字。所以inputType尤为重要。
android:inputType=“textCapCharacters” 字母大写
android:inputType=“textMultiLine” 多行输入
android:inputType=“textEmailAddress” 电子邮件地址
android:inputType=“textPassword” 密码,隐藏字符
android:inputType=“textVisiblePassword” 密码,字符可见
android:inputType=“number” 数字
android:inputType=“phone” 拨号键盘
android:inputType=“datetime” 时间日期
android:inputType=“date” 日期键盘
android:inputType=“time” 时间键盘
Button(按钮)
Button继承了TextView,它主要是UI界面上生成的一个按钮,用户可以点击按钮,并且能为按钮添加onClick事件即点击事件。按钮使用起来相对容易,可以通过android:background为按钮设置背景或者自定义样式,关于Button的xml属性和TextView相似,大多数属性能够共用。
<Button
android:layout_height="40dp"
android:layout_width="wrap_content"
android:minWidth="100dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="2dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="10dp"
android:background="@drawable/button"
android:text="@string/login"
android:textColor="#fff"
android:textSize="18sp"
android:id="@+id/login"
android:textAllCaps="true"
android:onClick=“onLoginClick” //单击事件处理方法
/>
ImageView(图像视图)
ImageView,它的主要功能是用于显示图片,任何Drawable对象都可以使用ImageView显示。ImageView还派生了ImageButton组件,因此ImageView支持的XML属性、方法,基本上也可以应用于这两个组件。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@mipmap/ic_launcher" />
<ImageButton
android:id="@+id/imageButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher" />
</LinearLayout>
RadioButton(单选按钮)和CheckBox(多选框)
单选按钮(RadioButton)和复选框(CheckBox)是用户界面中最普通的UI组件,它们都继承自Button类,因此可以直接使用Button支持的各种属性和方法。
RadioButton和CheckBox都多了一个可选中的功能,因此可以额外指定一个android:checked属性,用于指定RadioButton和CheckBox初始时是否被选中。
RadioButton和CheckBox的不同之处在于,一组RadioButton只能只能选中其中一个,因此RadioButton通常要和RadioGroup一起使用,用于定义一组单选按钮。
CheckBox:同时可以选择多个选项的控件
RadioButton:仅可以选择一个选项的控件
RadioGroup是RadioButton的承载体,程序运行时不可见,应用程序中可能包含一个或多个RadioGroup。
RadioGroup继承至LinearLayout,所以LinearLayout的属性RadioGroup都可以使用android:orientation属性控制RadioButton 的排列方向。
一个RadioGroup包含多个RadioButton,在每个RadioGroup中,用户仅能够选择其中一RadioButton
checked 属性:android:checked=“true” 或 “false”
RadioButton必须设置id属性,才能实现单选
<!--单选按钮-->
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RadioButton
android:id="@+id/radioButton2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="男" />
<RadioButton
android:id="@+id/radioButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="女" />
</RadioGroup>
<!--复选框-->
<CheckBox
android:id="@+id/checkBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="读书" />
<CheckBox
android:id="@+id/checkBox2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="看电影" />
。。。。。。
ProgressBar(进度条)
ProgressBar也是一组重要的组件,ProgressBar本身代表了进度条组件,它还派生了两个常用的组件:seekBar和ratingBar。ProgressBar及其子类十分相似,只是在显示上有一定的区别。
进度条通常用于向用户显示某个耗时操作完成的百分比。进度条可以动态地显示进度,因此避免长时间地执行某个耗时操作时,让用户感觉程序失去了响应,从而带给用户更好的体验。
ProgressBar分为确定的和不确定的,不确定的就是不确定一个操作需要多长时间来完成,这个时候就需要用的不确定的ProgressBar。这个是由属性android:indeterminate来控制的,如果设置为true的话,那么ProgressBar就可能是圆形的滚动条或者水平的滚动条(由样式决定)。默认情况下,如果是水平进度条,那么就是确定的。
Android支持多种风格的进度条,通过style属性可以为ProgressBar指定风格:
使用时候。
另外还有一种方式就是使用系统的attr:
?android:attr/progressBarStyleHorizontal"
?android:attr/progressBarStyleSmallTitle"
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ProgressBar
android:id="@+id/progressBar5"android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ProgressBar
android:id="@+id/progressBar4"android:layout_width="145dp"
android:layout_height="25dp"
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:background="@android:color/holo_green_light" />
</LinearLayout>
SeekBar(拖动条)
拖动条(SeekBar)与进度条非常相似,只是进度条采用颜色填充来表示进度完成的程度,而拖动条则通过滑块的位置来标识数字。拖动条允许用户拖动滑块来改变值,因此拖动条通常用于对系统的某种数值进行调节,比如音量调节等。
由于拖动条继承了进度条,因此进度条所支持的XML属性和方法同样适用于拖动条。进度条允许用户改变拖动条的滑块外观,改变滑块外观通过android:thumb属性来指定,这个属性指定一个Drawable对象,该对象将作为自定义滑块。为了让程序能够响应拖动条滑块位置的改变,程序可以为它绑定一个OnSeekBarchangelistener监听器。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SeekBar
android:id="@+id/seekBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="@android:color/holo_green_light"
android:layout_weight="1" />
</LinearLayout>
AdapterView及其子类
AdapterView是一组重要的组件,AdapterView本身是一个抽象基类,它派生的子类在用法上十分相似,只是显示界面上有一定的区别。AdapterView具有如下特征:
AdapterView继承了ViewGroup,它的本质是容器。
AdapterView可以包括多个“列表项”,并以合适的方式显示出来。
AdapterView显示的多个“列表项”由Adapter提供。调用AdapterView的setAdapter(Adapter)方法设置Adapter。
ListView和ListActivity
ListView是手机系统中使用非常广泛的一种组件,它以垂直列表的形式显示所有的列表项。
手机屏幕空间有限,能显示的内容不多。可以借助ListView来显示更多的内容。
ListView允许用户通过上下滑动来将屏幕外的数据滚动到屏幕内,同时屏幕内原有的数据滚动出屏幕,从而显示更多的数据内容。
生成列表视图有如下两种方式:
直接使用ListView进行创建。
创建一个继承ListActivity的Activity(相当于该Activity显示的组件为ListView)。
一旦在程序中获得了ListView之后,接下来就需要为ListView设置它要显示的列表项。通过setAdapter(Adapter)方法为ListView提供Adapter, 由Adapter提供列表项。
使用ListActivity用来显示列表数据
ListActivity的使用步骤:
1)继承自ListActivity,如:xxx extends ListActivity
2)重写onCreate方法,在该方法中,需要做三件事情:
a)准备数据源
b)设置适配器
c)绑定适配器
3)重写点击事件
void onListItemClick(ListView l, View v, int position, long id)
public class MainActivity extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
//1.数据源
String[] data = {"武汉","北京","上海","成都","西安"};
//2.适配器
@SuppressWarnings("unchecked")
ArrayAdapter arrayAdapter = new ArrayAdapter(this,
android.R.layout.simple_list_item_1, data);
//3.绑定
setlistadapter(arrayAdapter);
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Toast.makeText(MainActivity.this
,"点中了第"+position+"个"+" "+l.getAdapter().getItem(position).toString()
,Toast.LENGTH_LONG).show();
} }
ListView常用的XML属性
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--直接使用数组资源给list view添加列表项-->
<!--设置分割条的颜色-->
<!--设置分割条的高度--> <ListView
android:id="@+id/listview1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="#C4C4C4“
android:dividerHeight="1dp">
android:entries="@array/teacher_name" </ListView>
</LinearLayout>
values/arrays.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--添加数组元素-->
<string-array name="teacher_name">
<item>张三</item>
<item>李四</item>
<item>王五</item>
<item>赵六</item>
</string-array>
</resources>
在res文件夹下新建array.xm
Adapter接口
Adapter本身只是一个接口,它派生了listadapter和SpinnerAdapter两个子接口,其中listadapter为AbsListView提供列表项,而SpinnerAdapter为Absspinner提供列表项。
Adapter常用的实现类如下:
ArrayAdapter:支持泛型操作,最为简单,只能展示一行字。
SimpleAdapter:有最好的扩充性,可以自定义出各种效果。
BaseAdapter:是一个抽象类,继承它需要实现较多的方法,所以也就具有较高的灵活性。
实例一:基于ArrayApter创建ListView
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listview_layout);
ListView listView=findViewById(R.id.listview1);
//定义一个数组,用来填充listview
String[] arr={"章节1","章节2","章节3"};
ArrayAdapter<String>adapter=newArrayAdapter<String>(
this,android.R.layout.simple_expandable_list_item_1,arr);
//为listview设置adapter
listView.setAdapter(adapter);
} }
实例二:基于SimpleAdapter创建ListView
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/listview1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</ListView>
</LinearLayout>
list_item_layout.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<!--定义一个ImageView组件,用来显示头像--> <ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--定义一个TextView组件,用来显示名字--> <TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"/>
<!--定义一个TextView组件,用来显示人物的描述--> <TextView
android:id="@+id/dexc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"/>
</LinearLayout>
</LinearLayout>
Activity代码:
public class MainActivity extends AppCompatActivity {
//定义名字数组
private String[] name={"张三","王五","赵六"};
//定义描述任务数组
private String[] desc={"唱歌","跳舞","打球"};
//定义头像数组
private int[] icon=new int[]
{R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launch
er};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = findViewById(R.id.listview1);
//创建一个list集合,list集合的元素是MAP
List<Map<String,Object>> list=
new ArrayList<Map<String,Object>>();
for(int i=0;i<name.length;i++){
Map<String, Object> listitem=new HashMap<String, Object>();
listitem.put("icon",icon[i]);
listitem.put("name",name[i]);
listitem.put("desc",desc[i]);
list.add(listitem);
//创建一个SimpleAdapter
SimpleAdapter adapter=
new SimpleAdapter(this,list,R.layout.list_item_layout,
new String[]{"name","icon","desc"},
new int[]{R.id.name,R.id.icon,R.id.dexc});
listView.setAdapter(adapter); } }
使用SimpleAdapter最重要的是它的5个参数,尤其是后面4个,第二个参数是List<Map<String,?>>类型的集合对象,该集合中每个Map<String,?>对象生成一行;第三个参数是指定一个界面布局的ID,这里引用了一个自定义的布局list_item_layout.xml文件;第四个参数是String[]类型的参数,该参数决定提取哪些内容显示在listview的每一行;最后一个是int[]类型的参数,决定显示哪些组件。
实例三:基于BaseAdapter创建ListView
在使用SimpleAdapter时,用户可以在布局当中定义按钮,但是当用户点击时,由于点击操作被ListView的Item所覆盖,导致按钮无法获取到焦点,这时候最方便的方法就是使用灵活的适配器BaseAdapter了。BaseAdapter是最基础的Adapter,具有全能性,不会像ArrayAdapter等的封装好的类有那么多局限性,但是这样的话,使用起来自然会更加麻烦一点。
(1)自定义布局文件list_item_layout.xml作为每一行的布局样式
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" > <LinearLayout
android:layout_width="200dip"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageview"
android:layout_width="50dip"
android:layout_height="50dip" />
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingTop="8dip"
android:textSize="20sp" />
</LinearLayout>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
(2)自定义一个MyAdapter类继承自BaseAdapter,然后重写里边的方法
public class MyAdapter extends BaseAdapter {
private List<Map<String, Object>> datas;
private Context mContext;
public MyAdapter(List<Map<String, Object>> datas, Context
mContext) {
this.datas = datas;
this.mContext = mContext; }
public int getCount() {
// 返回数据的总数
return datas.size(); }
public Object getItem(int position) {
// 返回在list中指定位置的数据的内容
return datas.get(position); }
public long getItemId(int position) {
// 返回数据在list中所在的位置
return position; }
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
// 使用自定义的布局文件作为Layout
convertView = LayoutInflater.from(mContext).inflate(
R.layout.list_item_layout, null);
// 减少findView的次数
holder = new ViewHolder();
// 初始化布局中的元素
holder.mImageView
convertView.findViewById(R.id.imageview);
holder.mTextView =
convertView.findViewById(R.id.textview);
holder.mButton =
convertView.findViewById(R.id.button);
holder.mButton.setonClickListener(new View.OnClickListener() {
public void onClick(View view) {
Toast.makeText(mContext,"你点了我!哈哈",
Toast.LENGTH_SHORT).show(); }
});
convertView.setTag(holder); } else {
holder = (ViewHolder) convertView.getTag(); }
// 从传入的数据中提取数据并绑定到指定的view中
holder.mImageView.setimageResource((Integer) datas.
get(position).get("img"));
holder.mTextView.setText(datas.get(position).get("title").
toString());
holder.mButton.setText(datas.get(position).get("button").
toString());
return convertView; }
static class ViewHolder {
ImageView mImageView;
TextView mTextView;
Button mButton; } }
(3)MainActivity中添加数据以及为ListView添加上文自定义的Adapter
public class MainActivity extends Activity {
private ListView mListView;
private MyAdapter myAdapter;
private List<Map<String, Object>> list =
new ArrayList<Map<String, Object>>();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
mListView =
findViewById(R.id.listview);
myAdapter = new MyAdapter(list, this);
mListView.setAdapter(myAdapter); }
private void initData() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("img", R.drawable.android);
map.put("title", "Android");
map.put("button", "学习");
list.add(map);
map = new HashMap<String, Object>();
map.put("img", R.drawable.java1);
map.put("title", "JAVA");
map.put("button", "学习");
list.add(map);
map = new HashMap<String, Object>();
map.put("img", R.drawable.html5);
map.put("title", "HTML5");
map.put("button", "学习");
list.add(map);
//。。。。。。
} }
(4)关于ViewHolder
在itemView相同的情况下,每一次创建itemView的时候都要重复的去绑定控件(findViewById)。重复的findViewById是很消耗性能的,特别是在listView中的itemView很多的情况下。
View中的setTag(Onbect),可以给View添加一个格外的数据,以后可以用getTag()将这个数据取出来。
setTag()是把Object对象作为参数对view进行存储的。也就是说,我们要把一个itemView中的控件抽取成一个Object,因此创建了一个ViewHolder。
在第一次创建itemView的时候,完成对控件的绑定,同时控件作为一个 object–holder , 把 它 通 过 setTag() 存到itemView中,第二次使用的时候就可以通过getTag()把holder取出来直接使用,也就是说,在list中itemView相同的情况下,我们只进行了一次的控件资源绑定。
Spinner:能够从多个选项中选一选项的控件,类似于桌面程序的组合框(ComboBox),但没有组合框的下拉菜单,而是使用浮动菜单为用户提供选择
使用ArrayAdapter数组适配器,将界面控件和底层数据绑定在一起
为在代码中使用Spinner 组件,需要引入:
import android.widget.Spinner;
import android.widget.ArrayAdapter;
import android.widget.AdapterView;
import java.util.ArrayList;
import java.util.List;
<Spinner
android:id="@+id/spCity“
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:prompt="请选择城市"
android:spinnerMode="dialog"
android:entries="@array/cities"/
>
entries属性,spinner列表中的数据
spinnerMode属性,spinner显示为对话框或者是下拉框形式;android:spinnerMode=[“dialog”|“dropdown”]
prompt属性表示spinner列表上方的提示
android:prompt 必须要引用 strings.xml 中资源 ID ,而不能在这里直接用 raw text 。
只有在android:spinnerMode=“dialog”时才能显示文字
spinnerMode=“dialog”
spinnerMode=“dropdown”
values/arrays.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="cities">
<item >武汉</item>
<item >北京</item>
<item >上海</item>
<item >成都</item>
<item >西安</item>
</string-array>
</resources>
Spinner设置事件监听器的方法 ItemSelected
spinner.setonItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
// Todo Auto-generated method stub
Toast.makeText(MainActivity.this, adapter.getItem(arg2), Toast.LENGTH_LONG).show();
// list.get(arg2)
// arg0.getAdapter().getItem(arg2).toString()
}
@Override
public void onnothingSelected(AdapterView<?> arg0) {
// Todo Auto-generated method stub
}
});
arg0表示适配器控件,即spinner; arg1表示适配器内部的控件,即spinner中的子项; arg2表 示选中子项的位置position ; arg3表示子项的ID
我们今天的关于Android Paint类详解和android cups print的分享就到这里,谢谢您的阅读,如果想了解更多关于Android Activity类详解、Android IPC进程间通信详解最新AndroidStudio的AIDL操作)、android Paint 设置颜色问题?、Android Studio入门:Android应用界面详解(中)(Android控件详解、AdapterView及其子类)的相关信息,可以在本站进行搜索。
本文标签: