免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 13410 | 回复: 1
打印 上一主题 下一主题

android界面效果全汇总 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-21 08:41 |只看该作者 |倒序浏览
(一)Activity 页面切换的效果
Android 2.0 之后有了 overridePendingTransition() ,其中里面两个参
数,一个是前一个 activity 的退出两一个 activity 的进入,
Java 代码
1. @Override
public void onCreate(Bundle savedInstanceState) {
2. super.onCreate(savedInstanceState);
3.
4. setContentView(R.layout.SplashScreen);
5.
6. new Handler().postDelayed(new Runnable() {
7. @Override
8. public void run() {
9. Intent mainIntent = new Intent(SplashScreen.this,
AndroidNews.class);
10. SplashScreen.this.startActivity(mainIntent);
11. SplashScreen.this.finish();
12.
13. overridePendingTransition(R.anim.mainfadein,
14. R.anim.splashfadeout);
15. }
16.}, 3000);
}
上面的代码只是闪屏的一部分。
Java 代码
1. getWindow (). setWindowAnimations ( int );
这可没有上个好但是也可以 。
实现淡入淡出的效果
Java代码
1. overridePendingTransition(Android.R.anim.fade_in,android.R.anim.fade_out);
由左向右滑入的效果
Java代码
1. overridePendingTransition(Android.R.anim.slide_in_left,android.R.anim.slide_out_right);
实现zoomin和zoomout,即类似iphone的进入和退出时的效果
Java代码
1. overridePendingTransition(R.anim.zoomin, R.anim.zoomout);
新建zoomin.xml文件
Xml代码
1. <?xml version="1.0" encoding="utf-8"?>
2. <set
3. xmlns:Android="http://schemas.android.com/apk/res/android"
4. Android:interpolator="@android:anim/decelerate_interpolator"> <scale Android:fromXScale="2.0" android:toXScale="1.0"
5. Android:fromYScale="2.0" android:toYScale="1.0"
6. Android:pivotX="50%p" android:pivotY="50%p"
7. Android:duration="@android:integer/config_mediumAnimTime" /> </set>
新建zoomout.xml文件
Xml代码
1. <?xml version="1.0" encoding="utf-8"?>
2. <set
3. xmlns:Android="http://schemas.android.com/apk/res/android"
4. Android:interpolator="@android:anim/decelerate_interpolator"
5. Android:zAdjustment="top">
6. <scale Android:fromXScale="1.0" android:toXScale=".5"
7. Android:fromYScale="1.0" android:toYScale=".5"
8. Android:pivotX="50%p" android:pivotY="50%p"
9. Android:duration="@android:integer/config_mediumAnimTime" />
10.<alpha Android:fromAlpha="1.0" android:toAlpha="0"
11.Android:duration="@android:integer/config_mediumAnimTime"/>
12.</set>
(二)android菜单动画 先请注意,这里的菜单并不是按机器上的MENU出现在那种菜单,而是基于Android SDK提供的android.view.animation.TranslateAnimation(extends android.view.animation.Animation)类实例后附加到一个Layout上使之产生的有动画出现和隐藏效果的菜单。 原理:Layout(菜单)从屏幕内(挨着屏幕边沿,其实并非一定,视需要的初态和末态而定)动态的移动到屏幕外(在外面可以挨着边沿,也可以离远点,这个无所谓了),这样就可以达到动态菜单的效果了。但是由于Animation的一些奇怪特性(setFill**() 函数的作用效果,这个在我使用的某几个Animation当中出现了没有想明白的效果),就暂不理会这个东西了,所以使得我们还需要用上XML属性android:visibility。当Layout(菜单)显示的时候,设置android:visibility="visible",当Layout(菜单)隐藏的时候,设置android:visibility="gone",这里android:visibility可以有3个值,"visible"为可见,"invisible"为不可见但占空间,"gone"为不可见且不占空间(所谓的占不占空间,这个可以自己写个XML来试试就明白了)。 Class TranslateAnimation的使用:Animation有两种定义方法,一种是用Java code,一种是用XML,这里只介绍用code来定义(因为用XML来定义的那种我没用过。。嘿嘿。。)。多的不说,看代码。 这里是TranslateAnimationMenu.java(我在里面还另加入了ScaleAnimation产生的动画,各位朋友可以照着SDK以及程序效果来理解): package com.TranslateAnimation.Menu; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener;
import android.view.animation.Animation; import android.view.animation.TranslateAnimation; import android.widget.Button; import android.widget.LinearLayout; public class TranslateAnimationMenu extends Activity { /** Called when the activity is first created. */ //TranslateAnimation showAction, hideAction; Animation showAction, hideAction; LinearLayout menu; Button button; boolean menuShowed; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); menu = (LinearLayout) findViewById(R.id.menu); button = (Button) findViewById(R.id.button); // 这里是TranslateAnimation动画 showAction = new TranslateAnimation( Animation.RELATIVE_TO_SELF,0.0f,Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, -1.0f, Animation.RELATIVE_TO_SELF, 0.0f); // 这里是ScaleAnimation动画 //showAction = new ScaleAnimation( // 1.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.0f, // Animation.RELATIVE_TO_SELF, 0.0f); showAction.setDuration(500); // 这里是TranslateAnimation动画 hideAction = new TranslateAnimation( Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, -1.0f);
// 这里是ScaleAnimation动画 //hideAction = new ScaleAnimation( // 1.0f, 1.0f, 1.0f, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f); hideAction.setDuration(500); menuShowed = false; menu.setVisibility(View.GONE); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub if (menuShowed) { menuShowed = false; menu.startAnimation(hideAction); menu.setVisibility(View.GONE); } else { menuShowed = true; menu.startAnimation(showAction); menu.setVisibility(View.VISIBLE); } } }); } } 这里是main.xml: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <LinearLayout android:id="@+id/menu" android:layout_height="100px" android:layout_width="fill_parent" android:layout_alignParentTop="true" android:background="#ffffff"> <TextView android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="I am a menu"
android:gravity="center" /> </LinearLayout> <Button android:id="@+id/button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:text="Click to show/hide menu" /> </RelativeLayout>Android基于TranslateAnimation的动画动态菜单
android 布局属性
文章分类:移动开发
第一类:属性值为true或false android:layout_centerHrizontal 水平居中 android:layout_centerVertical 垂直居中 android:layout_centerInparent 相对于父元素完全居中 android:layout_alignParentBottom 贴紧父元素的下边缘 android:layout_alignParentLeft 贴紧父元素的左边缘 android:layout_alignParentRight 贴紧父元素的右边缘 android:layout_alignParentTop 贴紧父元素的上边缘 android:layout_alignWithParentIfMissing 如果对应的兄弟元素找不到的话就以父元素做参照物 第二类:属性值必须为id的引用名“@id/id-name” android:layout_below 在某元素的下方 android:layout_above 在某元素的的上方 android:layout_toLeftOf 在某元素的左边 android:layout_toRightOf 在某元素的右边 android:layout_alignTop 本元素的上边缘和某元素的的上边缘对齐 android:layout_alignLeft 本元素的左边缘和某元素的的左边缘对齐 android:layout_alignBottom本元素的下边缘和某元素的的下边缘对齐 android:layout_alignRight本元素的右边缘和某元素的的右边缘对齐 第三类:属性值为具体的像素值,如30dip,40px android:layout_marginBottom 离某元素底边缘的距离 android:layout_marginLeft 离某元素左边缘的距离 android:layout_marginRight 离某元素右边缘的距离 android:layout_marginTop 离某元素上边缘的距离
EditText的android:hint 设置EditText为空时输入框内的提示信息。 android:gravity android:gravity属性是对该view 内容的限定.比如一个button 上面的text. 你可以设置该text 在view的靠左,靠右等位置.以button为例,android:gravity="right"则button上面的文字靠右 android:layout_gravity android:layout_gravity是用来设置该view相对与起父view 的位置.比如一个button 在linearlayout里,你想把该button放在靠左、靠右等位置就可以通过该属性设置.以button为例,android:layout_gravity="right"则button靠右 android:layout_alignParentRight 使当前控件的右端和父控件的右端对齐。这里属性值只能为true或false,默认false。 android:scaleType: android:scaleType是控制图片如何resized/moved来匹对ImageView的size。ImageView.ScaleType / android:scaleType值的意义区别: CENTER /center 按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的居中部分显示 CENTER_CROP / centerCrop 按比例扩大图片的size居中显示,使得图片长(宽)等于或大于View的长(宽) CENTER_INSIDE / centerInside 将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽等于或小于View的长/宽 FIT_CENTER / fitCenter 把图片按比例扩大/缩小到View的宽度,居中显示 FIT_END / fitEnd 把图片按比例扩大/缩小到View的宽度,显示在View的下部分位置 FIT_START / fitStart 把图片按比例扩大/缩小到View的宽度,显示在View的上部分位置 FIT_XY / fitXY 把图片•不按比例扩大/缩小到View的大小显示 MATRIX / matrix 用矩阵来绘制,动态缩小放大图片来显示。 ** 要注意一点,Drawable文件夹里面的图片命名是不能大写的。
2010-10-28
android 翻页
:
之前看到不少翻页,不过人家没有分享出代码来,我也一直没有搞出来.
想了好久,实现原理并不是那么的难,怎么实现就比较难了.
当然像 3D 现实模拟分页的难度是比较大的.
平面的分页,简单点说就是用三张􀨮片,模拟分页时可见区,
这里我弄了一个 View,里面有翻页的效果.
OnDraw 中;
最底一张是将要显示的,先画出来,
接着画原来那张,放􀩘中间,叠为这张􀨮片要􀩘翻页的过程中慢慢消失,一点一点
被拉出去,
最后一张就是最上面的,为什么要用这张􀨮片呢?当页面被翻起后,一个角消失了,
就比如第二张不显示的部分,那这部分,就是第三张了,再覆盖􀩘第二张上面,形
成一种看似翻书的.效果.
然后􀩘第二张(假设从左边开始被翻起,左边先消失),左边缘再画出一条线,当然
这条线要粗点,然后设置颜色渐变,还要透明的,就有一种阴影的效果.
我开始一直􀩘想,像这样的,不难实现啊,当然只限于矩形的,叠为当时没有想到
如何处理第二张消失部分为一个三角形.
可以通过 Rect 来设置一个 Bitmap,的宽度.
Rect rect = new Rect(mWidth, 0, width, height);
canvas.drawBitmap(image2, null, rect, paint2);
mWidth 就是左边消失部分的宽度.通过不断改变这个值,然后再刷新 View 就可以
看到一种滚动的效果.第二张􀨮片左边慢慢消失, width,height 为画面目的宽高.
然后可以添加一个第三张􀨮片,也用同样的方法设置了它显示的宽,高,
通过上面 Rect 的处理,看到一般的效果.比较常见的是从一个角开始,然后慢慢
的卷起来,而不是像上面平行的,(上面只能看到平行的效果.)
这里就涉及到了一个角,就是三角形如何产生的问题,这个问题台扰了好久.今天
想到办法了.就是用 Path 去画多边形.一个矩形,减去一个多边形,就剩下一个三
角形了.
先讨论上面那种效果的处理方式:
首先是 View:的 OnDraw 方法.
Java 代码
1. width = getWidth();
2. height = getHeight();
3. //画最底下一张将要显示的图片
4. Rect rect = new Rect(0, 0, width, height);
5. canvas.drawBitmap(image1, null, rect, paint1);
6. //画上面卷起的那张.实现平行翻页效果.
7. rect = new Rect(mWidth, 0, width, height);
8. canvas.drawBitmap(image2, null, rect, paint2);
9. //当然之后再处理卷起边缘阴影,模糊等效果,这里省略了.还有图片Image1,image2自己准备了
10.然后就是手势,没有手势,翻页显得很呆板.
11.这个View实现OnGestureListener,自然有一些方法要覆盖的.
12.其它方法随便了,有返回值的给它一个True,主要是
13.public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)这个方法,比较有用.
14.myHandler.removeMessage(0);/../我觉得要先移除上一次翻页的动作,然后会马上从上一次运行中停止,而立即向当前需要的方向变化.
15.if(e1.getX() - e2.getX() > 0){
16. turnLeft(5);//向左翻
17.}else if(e2.getX() - e1.getX() > 0){
18. turnRight(5);//向右翻
19.}
20.两个方法差不多,也可以合并,传入正负值.
21.delta = speed;参数就是上面的5,作为变化速度.
22.myHandler.sendEmptyMessage(0);
23.普通的View要Handler来更新.之前试过了,以为在View直接Invalidate可以.
24.虽然没有提示非UI线程的问题,但是循环了多次只看到OnDraw执行一次而以.
25.public void handleMessage(Message message){
26. invalidate();
27. mWidth += delta;//变化第二张图片的宽.
28. if(delta > 0){//向右滚动
29. if(mWidth < width){//当第二张图片的左侧空白超过了画布的宽 时停止
30. sendEmptyMessage(0);
31. }
32.}else{//向左滚动
33.if(mWidth > 0){
34. sendEmptyMessage(0);
35.}
36.}
37.}
38.
39.然后在XML里用这个View,最后Activity里SetContentView就OK了/
40.<com.me.page.PageView
41.android:id="@+id/pageView1"
42.android:layout_gravity="center"
43.android:layout_marginTop="5px"
44.android:layout_width="fill_parent"
45.android:layout_height="fill_parent"/>
46.
47.由于使用XML,所以构造方法必须要有,带两个参数的.
48.public PageView(Context context, AttributeSet attrs){
49. super(context, attrs);
50. initView();
51.}
52.InitView:
53.private void initView(){
54. image1 = Bitmap.createBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.aac));
55. image2 = Bitmap.createBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.q1));
56. image3 = Bitmap.createBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.q2));
57.
58. myHandler = new MyHandler();
59. gestureDetector = new GestureDetector(this);
60. mShader = new LinearGradient(10, 250, 250, 250,
61. new int[]{Color.RED, Color.GREEN, Color.BLUE},
62. null, Shader.TileMode.MIRROR);
63. paint1 = new Paint();
64. paint1.setFlags(Paint.ANTI_ALIAS_FLAG); //去除插刺
65. paint2 = new Paint(paint1);
66. paint3 = new Paint(paint2);
67. paint3.setColor(0x45111111);
68. //paint.setShader(mShader);//其间颜色会有变化.
69. paint3.setStrokeWidth(12);
70. paint4 = new Paint(paint2);
71. paint4.setColor(0xff111111);
72. paint4.setShader(mShader);//其间颜色会有变化.
73. paint4.setStrokeWidth(12);
74. }
75.
76.代码就到这里了.关于三角形卷动翻页,代码没有写完整,(第三张图片还没有弄,也没有阴影),先不写了,而且似乎也不止我这样一种写法的,网上看到的翻页还有其它的,比如我见到一个,OnDraw里得到画布的高,然后
一行一行描述,并逐行递减宽度,这样造成一个三角形,速度也不那么地慢.还可接受.
77.
78.来些图片.
79.page-15.png到page-16.png,宽度越来越小了.
80.page-12.png到page-14.png是三角形的,里面具体操作复杂一些,当前差上面那张遮罩.以后再完善了.
81. android中颜色对应的值
82.文章分类:移动开发
83. < ?xml version="1.0" encoding="utf-8" ?> < resources> < color name="white">#FFFFFF< /color>< !--白色 --> < color name="ivory">#FFFFF0< /color>< !--象牙色 --> < color name="lightyellow">#FFFFE0< /color>< !--亮黄色 --> < color name="yellow">#FFFF00< /color>< !--黄色 --> < color name="snow">#FFFAFA< /color>< !--雪白色 --> < color name="floralwhite">#FFFAF0< /color>< !--花白色 --> < color name="lemonchiffon">#FFFACD< /color>< !--柠檬绸色 --> < color name="cornsilk">#FFF8DC< /color>< !--米绸色 --> < color name="seashell">#FFF5EE< /color>< !--海贝色 --> < color name="lavenderblush">#FFF0F5< /color>< !--淡紫红 --> < color name="papayawhip">#FFEFD5< /color>< !--番木色 --> < color name="blanchedalmond">#FFEBCD< /color>< !--白杏色 --> < color name="mistyrose">#FFE4E1< /color>< !--浅玫瑰色 --> < color name="bisque">#FFE4C4< /color>< !--桔黄色 --> < color name="moccasin">#FFE4B5< /color>< !--鹿皮色 -->
< color name="navajowhite">#FFDEAD< /color>< !--纳瓦白 --> < color name="peachpuff">#FFDAB9< /color>< !--桃色 --> < color name="gold">#FFD700< /color>< !--金色 --> < color name="pink">#FFC0CB< /color>< !--粉红色 --> < color name="lightpink">#FFB6C1< /color>< !--亮粉红色 --> < color name="orange">#FFA500< /color>< !--橙色 --> < color name="lightsalmon">#FFA07A< /color>< !--亮肉色 --> < color name="darkorange">#FF8C00< /color>< !--暗桔黄色 --> < color name="coral">#FF7F50< /color>< !--珊瑚色 --> < color name="hotpink">#FF69B4< /color>< !--热粉红色 --> < color name="tomato">#FF6347< /color>< !--西红柿色 --> < color name="orangered">#FF4500< /color>< !--红橙色 --> < color name="deeppink">#FF1493< /color>< !--深粉红色 --> < color name="fuchsia">#FF00FF< /color>< !--紫红色 --> < color name="magenta">#FF00FF< /color>< !--红紫色 --> < color name="red">#FF0000< /color>< !--红色 --> < color name="oldlace">#FDF5E6< /color>< !--老花色 --> < color name="lightgoldenrodyellow">#FAFAD2< /color>< !--亮金黄色 --> < color name="linen">#FAF0E6< /color>< !--亚麻色 --> < color name="antiquewhite">#FAEBD7< /color>< !--古董白 --> < color name="salmon">#FA8072< /color>< !--鲜肉色 --> < color name="ghostwhite">#F8F8FF< /color>< !--幽灵白 -->
< color name="mintcream">#F5FFFA< /color>< !--薄荷色 --> < color name="whitesmoke">#F5F5F5< /color>< !--烟白色 --> < color name="beige">#F5F5DC< /color>< !--米色 --> < color name="wheat">#F5DEB3< /color>< !--浅黄色 --> < color name="sandybrown">#F4A460< /color>< !--沙褐色 --> < color name="azure">#F0FFFF< /color>< !--天蓝色 --> < color name="honeydew">#F0FFF0< /color>< !--蜜色 --> < color name="aliceblue">#F0F8FF< /color>< !--艾利斯兰 --> < color name="khaki">#F0E68C< /color>< !--黄褐色 --> < color name="lightcoral">#F08080< /color>< !--亮珊瑚色 --> < color name="palegoldenrod">#EEE8AA< /color>< !--苍麒麟色 --> < color name="violet">#EE82EE< /color>< !--紫罗兰色 --> < color name="darksalmon">#E9967A< /color>< !--暗肉色 --> < color name="lavender">#E6E6FA< /color>< !--淡紫色 --> < color name="lightcyan">#E0FFFF< /color>< !--亮青色 --> < color name="burlywood">#DEB887< /color>< !--实木色 --> < color name="plum">#DDA0DD< /color>< !--洋李色 --> < color name="gainsboro">#DCDCDC< /color>< !--淡灰色 --> < color name="crimson">#DC143C< /color>< !--暗深红色 --> < color name="palevioletred">#DB7093< /color>< !--苍紫罗兰色 --> < color name="goldenrod">#DAA520< /color>< !--金麒麟色 -->
< color name="orchid">#DA70D6< /color>< !--淡紫色 --> < color name="thistle">#D8BFD8< /color>< !--蓟色 --> < color name="lightgray">#D3D3D3< /color>< !--亮灰色 --> < color name="lightgrey">#D3D3D3< /color>< !--亮灰色 --> < color name="tan">#D2B48C< /color>< !--茶色 --> < color name="chocolate">#D2691E< /color>< !--巧可力色 --> < color name="peru">#CD853F< /color>< !--秘鲁色 --> < color name="indianred">#CD5C5C< /color>< !--印第安红 --> < color name="mediumvioletred">#C71585< /color>< !--中紫罗兰色 --> < color name="silver">#C0C0C0< /color>< !--银色 --> < color name="darkkhaki">#BDB76B< /color>< !--暗黄褐色 < color name="rosybrown">#BC8F8F< /color>< !--褐玫瑰红 --> < color name="mediumorchid">#BA55D3< /color>< !--中粉紫色 --> < color name="darkgoldenrod">#B8860B< /color>< !--暗金黄色 --> < color name="firebrick">#B22222< /color>< !--火砖色 --> < color name="powderblue">#B0E0E6< /color>< !--粉蓝色 --> < color name="lightsteelblue">#B0C4DE< /color>< !--亮钢兰色 --> < color name="paleturquoise">#AFEEEE< /color>< !--苍宝石绿 --> < color name="greenyellow">#ADFF2F< /color>< !--黄绿色 --> < color name="lightblue">#ADD8E6< /color>< !--亮蓝色 --> < color name="darkgray">#A9A9A9< /color>< !--暗灰色 -->
< color name="darkgrey">#A9A9A9< /color>< !--暗灰色 --> < color name="brown">#A52A2A< /color>< !--褐色 --> < color name="sienna">#A0522D< /color>< !--赭色 --> < color name="darkorchid">#9932CC< /color>< !--暗紫色 --> < color name="palegreen">#98FB98< /color>< !--苍绿色 --> < color name="darkviolet">#9400D3< /color>< !--暗紫罗兰色 --> < color name="mediumpurple">#9370DB< /color>< !--中紫色 --> < color name="lightgreen">#90EE90< /color>< !--亮绿色 --> < color name="darkseagreen">#8FBC8F< /color>< !--暗海兰色 --> < color name="saddlebrown">#8B4513< /color>< !--重褐色 --> < color name="darkmagenta">#8B008B< /color>< !--暗洋红 --> < color name="darkred">#8B0000< /color>< !--暗红色 --> < color name="blueviolet">#8A2BE2< /color>< !--紫罗兰蓝色 < color name="lightskyblue">#87CEFA< /color>< !--亮天蓝色 --> < color name="skyblue">#87CEEB< /color>< !--天蓝色 --> < color name="gray">#808080< /color>< !--灰色 --> < color name="grey">#808080< /color>< !--灰色 --> < color name="olive">#808000< /color>< !--橄榄色 --> < color name="purple">#800080< /color>< !--紫色 --> < color name="maroon">#800000< /color>< !--粟色 --> < color name="aquamarine">#7FFFD4< /color>< !--碧绿色 --> < color name="chartreuse">#7FFF00< /color>< !--黄绿色 -->
< color name="lawngreen">#7CFC00< /color>< !--草绿色 --> < color name="mediumslateblue">#7B68EE< /color>< !--中暗蓝色 --> < color name="lightslategray">#778899< /color>< !--亮蓝灰 --> < color name="lightslategrey">#778899< /color>< !--亮蓝灰 --> < color name="slategray">#708090< /color>< !--灰石色 --> < color name="slategrey">#708090< /color>< !--灰石色 --> < color name="olivedrab">#6B8E23< /color>< !--深绿褐色 --> < color name="slateblue">#6A5ACD< /color>< !--石蓝色 --> < color name="dimgray">#696969< /color>< !--暗灰色 --> < color name="dimgrey">#696969< /color>< !--暗灰色 --> < color name="mediumaquamarine">#66CDAA< /color>< !--中绿色 --> < color name="cornflowerblue">#6495ED< /color>< !--菊兰色 --> < color name="cadetblue">#5F9EA0< /color>< !--军兰色 --> < color name="darkolivegreen">#556B2F< /color>< !--暗橄榄绿 < color name="indigo">#4B0082< /color>< !--靛青色 --> < color name="mediumturquoise">#48D1CC< /color>< !--中绿宝石 --> < color name="darkslateblue">#483D8B< /color>< !--暗灰蓝色 --> < color name="steelblue">#4682B4< /color>< !--钢兰色 --> < color name="royalblue">#4169E1< /color>< !--皇家蓝 --> < color name="turquoise">#40E0D0< /color>< !--青绿色 --> < color name="mediumseagreen">#3CB371< /color>< !--中海蓝 -->
< color name="limegreen">#32CD32< /color>< !--橙绿色 --> < color name="darkslategray">#2F4F4F< /color>< !--暗瓦灰色 --> < color name="darkslategrey">#2F4F4F< /color>< !--暗瓦灰色 --> < color name="seagreen">#2E8B57< /color>< !--海绿色 --> < color name="forestgreen">#228B22< /color>< !--森林绿 --> < color name="lightseagreen">#20B2AA< /color>< !--亮海蓝色 --> < color name="dodgerblue">#1E90FF< /color>< !--闪兰色 --> < color name="midnightblue">#191970< /color>< !--中灰兰色 --> < color name="aqua">#00FFFF< /color>< !--浅绿色 --> < color name="cyan">#00FFFF< /color>< !--青色 --> < color name="springgreen">#00FF7F< /color>< !--春绿色 --> < color name="lime">#00FF00< /color>< !--酸橙色 --> < color name="mediumspringgreen">#00FA9A< /color>< !--中春绿色 --> < color name="darkturquoise">#00CED1< /color>< !--暗宝石绿 --> < color name="deepskyblue">#00BFFF< /color>< !--深天蓝色 --> < color name="darkcyan">#008B8B< /color>< !--暗青色 --> < color name="teal">#008080< /color>< !--水鸭色 --> < color name="green">#008000< /color>< !--绿色 --> < color name="darkgreen">#006400< /color>< !--暗绿色 --> < color name="blue">#0000FF< /color>< !--蓝色 --> < color name="mediumblue">#0000CD< /color>< !--中兰色 -->
< color name="darkblue">#00008B< /color>< !--暗蓝色 --> < color name="navy">#000080< /color>< !--海军色 --> < color name="black">#000000< /color>< !--黑色 --> < /resources> android ListView详解
在android开发中ListView是比较常用的组件,它以列表的形式展示具体内容,并且能够根据数据的长度自适应显示。抽空把对ListView的使用做了整理,并写了个小例子,如下图。
列表的显示需要三个元素:
1.ListVeiw 用来展示列表的View。
2.适配器 用来把数据映射到ListView上的中介。
3.数据 具体的将被映射的字符串,图片,或者基本组件。
根据列表的适配器类型,列表分为三种,ArrayAdapter,SimpleAdapter和SimpleCursorAdapter
其中以ArrayAdapter最为简单,只能展示一行字。SimpleAdapter有最好的扩充性,可以自定义出各种效果。SimpleCursorAdapter可以认为是SimpleAdapter对数据库的简单结合,可以方面的把数据库的内容以列表的形式展示出来。
我们从最简单的ListView 开始:
print?
01 /**
02 * @author allin
03 *
04 */
05 public class MyListView extends Activity {
06
07 private ListView listView;
08 //private List<String> data = new ArrayList<String>();
09 @Override
10 public void onCreate(Bundle savedInstanceState){
11 super.onCreate(savedInstanceState);
12
13 listView = new ListView(this);
14
listView.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_expandable_list_item_1,getData()));
15 setContentView(listView);
16 }
17
18
19
20 private List<String> getData(){
21
22 List<String> data = new ArrayList<String>();
23 data.add("测试数据1");
24 data.add("测试数据2");
25 data.add("测试数据3");
26 data.add("测试数据4");
28 return data;
29 }
30 }
上面代码使用了ArrayAdapter(Context context, int textViewResourceId, List<T>
objects)来装配数据,要装配这些数据就需要一个连接ListView 视图对象和数组数据的
适配器来两者的适配工作,ArrayAdapter 的构造需要三个参数,依次为this,布局文件(注
意这里的布局文件描述的是列表的每一行的布局,android.R.layout.simple_list_item_
1 是系统定义好的布局文件只显示一行文字,数据源(一个List 集合)。同时用setAdapter
()完成适配的最后工作。运行后的现实结构如下图:
SimpleCursorAdapter
sdk 的解释是这样的:An easy adapter to map columns from a cursor to T
extViews or ImageViews defined in an XML file. You can specify which colu
mns you want, which views you want to display the columns, and the XML
file that defines the appearance of these views。简单的说就是方便把从游标得到
的数据进行列表显示,并可以把指定的列映射到对应的TextView 中。
下面的程序是从电话簿中把联系人显示到类表中。先在通讯录中添加一个联系人作为数
据库的数据。然后获得一个指向数据库的Cursor 并且定义一个布局文件(当然也可以使用
系统自带的)。
view source
print?
01 /**
02 * @author allin
03 *
04
*/
05
public class MyListView2 extends Activity {
07
private ListView listView;
08
//private List<String> data = new ArrayList<String>();
09
@Override
10
public void onCreate(Bundle savedInstanceState){
11
super.onCreate(savedInstanceState);
13
listView = new ListView(this);
15
Cursor cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null);
16
startManagingCursor(cursor);
18
ListAdapter listAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_1,
19
cursor,
20
new String[]{People.NAME},
21
new int[]{android.R.id.text1});
23
listView.setAdapter(listAdapter);
24
setContentView(listView);
25
}
Cursor cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null);先获得一个指向系统通讯录数据库的Cursor对象获得数据来源。
startManagingCursor(cursor);我们将获得的Cursor对象交由Activity管理,这样Cursor的生命周期和Activity便能够自动同步,省去自己手动管理Cursor。
SimpleCursorAdapter 构造函数前面3个参数和ArrayAdapter是一样的,最后两个参数:一个包含数据库的列的String型数组,一个包含布局文件中对应组件id的int型数组。其作用是自动的将String型数组所表示的每一列数据映射到布局文件对应id的组件上。上面的代码,将NAME列的数据一次映射到布局文件的id为text1的组件上。
注意:需要在AndroidManifest.xml中如权限:<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
运行后效果如下图:
SimpleAdapter
simpleAdapter 的扩展性最好,可以定义各种各样的布局出来,可以放上ImageView(图
片),还可以放上Button(按钮),CheckBox(复选框)等等。下面的代码都直接继承了
ListActivity,ListActivity 和普通的Activity 没有太大的差别,不同就是对显示ListView
做了许多优化,方面显示而已。
下面的程序是实现一个带有图片的类表。
首先需要定义好一个用来显示每一个列内容的xml
vlist.xml
view source
print?
01 <?xml version="1.0" encoding="utf-8"?>
02
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
03
android:orientation="horizontal"
android:layout_width="fill_parent"
04 android:layout_height="fill_parent">
07 <ImageView android:id="@+id/img"
08 android:layout_width="wrap_content"
09 android:layout_height="wrap_content"
10 android:layout_margin="5px"/>
11
12 <LinearLayout android:orientation="vertical"
13 android:layout_width="wrap_content"
14 android:layout_height="wrap_content">
15
16 <TextView android:id="@+id/title"
17 android:layout_width="wrap_content"
18 android:layout_height="wrap_content"
19 android:textColor="#FFFFFFFF"
20 android:textSize="22px" />
21 <TextView android:id="@+id/info"
22 android:layout_width="wrap_content"
23 android:layout_height="wrap_content"
24 android:textColor="#FFFFFFFF"
25 android:textSize="13px" />
26
27 </LinearLayout>
30 </LinearLayout>
下面是实现代码:
view source
print?
01 /**
02 * @author allin
03 *
04 */
05 public class MyListView3 extends ListActivity {
08 // private List<String> data = new ArrayList<String>();
09 @Override
10 public void onCreate(Bundle savedInstanceState) {
11 super.onCreate(savedInstanceState);
13
SimpleAdapter adapter =
new SimpleAdapter(this,getData(),R.layout.vlist,
14 new String[]{"title","info","img"},
1 5 new int[]{R.id.title,R.id.info,R.id.img});
16 setListAdapter(adapter);
17 }
18
19 private List<Map<String, Object>> getData() {
20
List<Map<String, Object>> list =
new ArrayList<Map<String, Object>>();
22 Map<String, Object> map = new HashMap<String, Object>();
23 map.put("title", "G1");
24
map.put("info", "google 1");
25
map.put("img", R.drawable.i1);
26
list.add(map);
27
28
map = new HashMap<String, Object>();
29
map.put("title", "G2");
30
map.put("info", "google 2");
31
map.put("img", R.drawable.i2);
32
list.add(map);
33
34
map = new HashMap<String, Object>();
35
map.put("title", "G3");
36
map.put("info", "google 3");
37
map.put("img", R.drawable.i3);
38
list.add(map);
39
40
return list;
41
}
42
}
使用simpleAdapter的数据用一般都是HashMap构成的List,list的每一节对应ListView的每一行。HashMap的每个键值数据映射到布局文件中对应id的组件上。因为系统没有对应的布局文件可用,我们可以自己定义一个布局vlist.xml。下面做适配,new一个SimpleAdapter参数一次是:this,布局文件(vlist.xml),HashMap的 title 和 info,img。布局文件的组件id,title,info,img。布局文件的各组件分别映射到HashMap的各元素上,完成适配。
运行效果如下图:
有按钮的ListView
但是有时候,列表不光会用来做显示用,我们同样可以在在上面添加按钮。添加按钮首先要写一个有按钮的xml文件,然后自然会想到用上面的方法定义一个适配器,然后将数据映射到布局文件上。但是事实并非这样,因为按钮是无法映射的,即使你成功的用布局文件显示出了按钮也无法添加按钮的响应,这时就要研究一下ListView是如何现实的了,而且必须要重写一个类继承BaseAdapter。下面的示例将显示一个按钮和一个图片,两行字如果单击按钮将删除此按钮的所在行。并告诉你ListView究竟是如何工作的。效果如下:
vlist2.xml
view source
print?
01 <?xml version="1.0" encoding="utf-8"?>
02
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
03 android:orientation="horizontal"
04
android:layout_width="fill_parent
"
05 android:layout_height="fill_parent">
06
07
08 <ImageView android:id="@+id/img"
09 android:layout_width="wrap_content"
10 android:layout_height="wrap_content"
11 android:layout_margin="5px"/>
12
13 <LinearLayout android:orientation="vertical"
14 android:layout_width="wrap_content"
15 android:layout_height="wrap_content">
16
17 <TextView android:id="@+id/title"
18 android:layout_width="wrap_content"
19 android:layout_height="wrap_content"
20 android:textColor="#FFFFFFFF"
21 android:textSize="22px" />
22 <TextView android:id="@+id/info"
23 android:layout_width="wrap_content"
24 android:layout_height="wrap_content"
25 android:textColor="#FFFFFFFF"
26 android:textSize="13px" />
27
28 </LinearLayout>
29
30
31 <Button android:id="@+id/view_btn"
32 android:layout_width="wrap_content"
33 android:layout_height="wrap_content"
34 android:text="@string/s_view_btn"
35 android:layout_gravity="bottom|right" />
36 </LinearLayout>
程序代码:
view source
print?
001 /**
002 * @author allin
003 *
004 */
005 public class MyListView4 extends ListActivity {
008 private List<Map<String, Object>> mData;
010 @Override
011 public void onCreate(Bundle savedInstanceState) {
012 super.onCreate(savedInstanceState);
013 mData = getData();
014 MyAdapter adapter = new MyAdapter(this);
015 setListAdapter(adapter);
016 }
017
018 private List<Map<String, Object>> getData() {
019
List<Map<String, Object>> list = new ArrayList<Map<String,
Object>>();
020
021 Map<String, Object> map = new HashMap<String, Object>();
022 map.put("title", "G1");
023 map.put("info", "google 1");
024 map.put("img", R.drawable.i1);
025 list.add(map);
026
027 map = new HashMap<String, Object>();
028 map.put("title", "G2");
029 map.put("info", "google 2");
030 map.put("img", R.drawable.i2);
031 list.add(map);
032
033 map = new HashMap<String, Object>();
034 map.put("title", "G3");
035
map.put("info", "google 3");
036
map.put("img", R.drawable.i3);
037
list.add(map);
038
039
return list;
040
}
041
042
// ListView 中某项被选中后的逻辑
043
@Override
044
protected void onListItemClick(ListView l, View v, int position, long id) {
045
046
Log.v("MyListView4-click", (String)mData.get(position).get("title"));
047
}
048
049
/**
050
* listview中点击按键弹出对话框
051
*/
052
public void showInfo(){
053
new AlertDialog.Builder(this)
054
.setTitle("我的listview")
055
.setMessage("介绍...")
056
.setPositiveButton("确定",
new DialogInterface.OnClickListener() {
057
@Override
058
public void onClick(DialogInterface dialog, int which) {
059
}
060
})
061
.show();
062
067
public final class ViewHolder{
068
public ImageView img;
069
public TextView title;
070
public TextView info;
071
public Button viewBtn;
072
}
075
public class MyAdapter extends BaseAdapter{
076
077
private LayoutInflater mInflater;
080
public MyAdapter(Context context){
081
this.mInflater = LayoutInflater.from(context);
082
}
083
@Override
084
public int getCount() {
085
// TODO Auto-generated method stub
086
return mData.size();
087
}
088
089
@Override
090
public Object getItem(int arg0) {
091
// TODO Auto-generated method stub
092
return null;
093
}
094
095
@Override
096
public long getItemId(int arg0) {
097
// TODO Auto-generated method stub
098
return 0;
099
}
100
101
@Override
102
public View getView(int position, View convertView, ViewGroup parent) {
103
104
ViewHolder holder = null;
105
if (convertView == null) {
107
holder=new ViewHolder();
109
convertView = mInflater.inflate(R.layout.vlist2, null);
110
holder.img = (ImageView)convertView.findViewById(R.id.img);
111
holder.title = (TextView)convertView.findViewById(R.id.title);
112
holder.info = (TextView)convertView.findViewById(R.id.info);
113
holder.viewBtn = (Button)convertView.findViewById(R.id.view_btn);
114
convertView.setTag(holder);
115
116
}else {
117
118
holder = (ViewHolder)convertView.getTag();
119
}
120
122
holder.img.setBackgroundResource((Integer)mData.get(position).get("img"));
123
holder.title.setText((String)mData.get(position).get("title"));
124
holder.info.setText((String)mData.get(position).get("info"));
125
126
holder.viewBtn.setOnClickListener(new View.OnClickListener() {
127
128
@Override
129
public void onClick(View v) {
130
showInfo();
131
}
132
});
133
134
135
return convertView;
136
}
137
下面将对上述代码,做详细的解释,listView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到listView的长度(这也是为什么在开始的第一张图特别的标出列表长度),然后根据这个长度,调用getView()逐一绘制每一行。如果你的getCount()返回值是0的话,列表将不显示同样return 1,就只显示一行。
系统显示列表时,首先实例化一个适配器(这里将实例化自定义的适配器)。当手动完成适配时,必须手动映射数据,这需要重写getView()方法。系统在绘制列表的每一行的时候将调用此方法。getView()有三个参数,position表示将显示的是第几行,covertView是从布局文件中inflate来的布局。我们用LayoutInflater的方法将定义好的vlist2.xml文件提取成View实例用来显示。然后将xml文件中的各个组件实例化(简单的findViewById()方法)。这样便可以将数据对应到各个组件上了。但是按钮为了响应点击事件,需要为它添加点击监听器,这样就能捕获点击事件。至此一个自定义的listView就完成了,现在让我们回过头从新审视这个过程。系统要绘制ListView了,他首先获得要绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面首先获得一个View(实际上是一个ViewGroup),然后再实例并设置各个组件,显
示之。好了,绘制完这一行了。那 再绘制下一行,直到绘完为止。在实际的运行过程中会发现listView的每一行没有焦点了,这是因为Button抢夺了listView的焦点,只要布局文件中将Button设置为没有焦点就OK了。
Android API Demo研究(2)
文章分类:移动开发
1. Forwarding
这个实现很简单,就是启动新的Activity或者Service后,增加一个finish()语句就可以了,这个语句会主动将当前 activity从历史stack中清除,这样back操作就不会打开当前activity。
做这个实验的时候,发现开发Android程序需要注意的一点小问题:增加新的activity时,不能只增加一个class,一定要记得要在manifest文件中增加该activity的描述。(这个简单的功能,未来google应该给增加吧)
“android:name中的点”意义:首先manifest会有一个默认指定的package属性,比如指定为"com.android.sample",如果我们增加的activity的实现也在这个package下,则android:name为实现的类名,这个类名前加不加点都没有关系,都会自动找到该实现,比如实现为forwardtarget,则android:name写成forwardtarget或者.forwardtarget都可以。唯一有区别的是,如果activity的实现是在默认包的子包里面,则前面这个点就尤为重要,比如activity的实现是com.android.sample.app.forwardtarget,则android:name必须写成.app.forwardtarget或者com.android.sample.app.forwardtarget。如果只写app.forwardtarget,通常编辑器就会提示该类找不到,但不巧的是,你恰好有一个类是app.forwardtarget,那你只有等着运行时报错吧。 所以建议养成习惯只要是默认package下面的类,无论是否是在子包里面,前面都要加上一个点,现在当前实现是在默认package下。
2.Persistent
这里的持久化其实就是本地配置文件的读写,实现方法是通过Activity.getPreferences(int)获取SharedPreferences对象,然后操作配置文件的读写,值得注意的是以下几点:
1)Activity.getPreferences(int mode)等价于Content.getSharedPreferences(String filename,int mode),这里面的filename就是当前class的名称,例如在PersistentTest类中调用getPreferences(0),等价于调用getPreferences("PersistentTest", 0)。如不想用class name做文件名,可以直接调用getSharedPreferences方法,自己指定配置文件的名称。
2)mode值的定义:
MODE_PRIVATE = 0,表示当前配置文件为私有文件,只有当前的应用可以访问。
MODE_WORLD_READABLE = 1,表示当前配置文件可以被其他应用读取。
MODE_WORLD_WRITEABLE = 2,表示当前配置文件可以被其他应用写入。
如果配置文件又想被人读又想被写人,怎么办呢,呵呵,当然是MODE_WORLD_READABLE&MODE_WORLD_WRITEABLE,真的怀疑设计android的人以前是做C/C++的。
3)SharedPreferences是个很有意思的实现,读取数据的时候,直接用get方法就可以了,可是写数据的时候,没用给set方法,呵呵,第一次用这个类一定会以为只能读不能写。如果要写数据的话,需要用editor()方法(为什么不是getEditor()呢?看来设计的人一定是做C/C++的)获取SharedPreferences.Editor类,然后用这个类的put方法写文件。为什么要这样做呢?好久没有看设计模式了,不知道他采用是哪种高级模式,等以后有时间,看看它的实现再做研究吧。
4)在这个实现中,读文件是放在onResume()中,写文件是在onPause()中,为什么要这么做呢,看字面意思,好像只有恢复和暂停的时候才会被执行,那程序第一次创建的时候会读文件吗?来让我们看看Activity的生命周期,就会发现这么做的巧妙之处:
文章分类:移动开发
1. Custom Dialog
Android支持自定义窗口的风格:
1)首先在资源里面建立style的value;
example:
<style name="Theme.CustomDialog" parent="android:style/Theme.Dialog">
<item name="android:windowBackground">@drawable/filled_box
</item>
</style>
drawable/filled_box.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#f0600000"/> <stroke android:width="3dp" color="#ffff8080"/> <corners android:radius="3dp" /> <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" /> </shape>
PS:关于Styles的学习,可以参见:http://code.google.com/android/reference/available-resources.html#stylesandthemes
2)设置当前activity的属性,两种方式:1.在manifest文件中给指定的activity增加属性
android:theme="@android:style/Theme.CustomDialog"。2.在程序中增加语句setTheme(R.style.Theme_CustomDialog);
PS1:如果只是将Acticity显示为默认的Dialog, 跳过第一步,只需要在manifest文中增加属性:android:theme="@android:style/Theme.Dialog"或者在程序中增加setTheme(android.R.style.Theme_Dialog).
PS2:其他创建Dialog的方法:创建app.Dialog类或者创建app.AlertDialog类。
Next Study:能不能在Activity已经打开以后动态修改当前Activity的风格?
在测试中发现,在onCreate()事件中增加setTheme(),必须在setContentView()之前,否则指定Style不能生效
2.Custom Title
Android除了可以为指定的Activity设置显示风格,此外也可以为指定的Activity设置一些特效,比如自定义Title,没有Title的Activity或者增加一个ICON等。
有意思的一点是,这些特效并不是你想设置的时候就行设置,你需要在Activity显示之前向系统申请要显示的特效,这样才能在下面的程序中为这些特效进行设置。(这样是不是多此一举有待研究)
为一个Activity设置自定义Title的流程:
1)为自定义的Title建立一个layout(custom_title_1.xml)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/screen" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <TextView android:id="@+id/left_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:text="Left" /> <TextView android:id="@+id/right_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text="Right" /> </RelativeLayout>
关于为什么采用RelativeLayout,可以参见:http://code.google.com/android/devel/ui/layout.html
2)为activity设定自定义Title特效并指定Title的layout:
在onCreate()事件中增加:
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); setContentView(R.layout.custom_title); getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title_1);
这三条语句的次序不能颠倒,依次为申请特效,创建view,设置特效属性。其中requestWindowFeature等价于getWindow().requestFeature()
3)在需要修改Title的地方,获取left_text或者right_text进行设置即可。
Next Study:Activity的其他显示特效
Window还有其他一些feature,比如FEATURE_CONTEXT_MENU,FEATURE_NO_TITLE,FEATURE_LEFT_ICON等,有待继续学习研究。
Animations(转)
文章分类:移动开发
仅用于方便查找 Animations 链接 Android支持2种类型的动画。内插动画可以应用于旋转、平移、放缩和渐变;frame-by-frame动画用来显示一系列的图片。关于创建、使用和应用动画的广泛概述可以在11章找到。 把动画定义成外部资源,有利于在多个地方使用,并且能基于设备硬件或方向选择适应的动画。 Tweened Animations 每个内插动画以独立的XML文件存储在/res/anim文件夹下。和layouts和drawable资源一样,动画XML的文件名用作资源的标识。 每个动画可以用来定义以下的变化:alpha(渐变)、scale(放缩)、translate(平移)和rotate(旋转)。 每个类型的动画都有特性来定义内插序列如何作用: Alpha fromAlpha/toAlpha 0-1 Scale fromXScale/toXScale 0-1 fromYScale/toYScale 0-1 pivotX/pivotY 图像的宽度/高度的百分比字符串 0%-100%
Translate fromX/toX 0-1 fromY/toY 0-1 Rotate fromDegrees/toDegrees 0-360 pivotX/pivotY 图像的宽度/高度的百分比字符串 0%-100% 你可以使用<set/>标签来创建多个动画。一个动画集包含一个到多个动画变化,并且支持一些额外的标签和特性来定制动画集中的动画何时以及怎样运行。 接下来的列表给了一些set标签一些特性: ❑ duration 动画的持续时间(毫秒) ❑ startOffset 启动动画的延时(毫秒) ❑ fillBefore True表示在动画开始前应用动画变换 ❑ fillAfter True表示动画开始后应用动画变换 ❑ interpolator 设置整个时间范围如何影响动画的速度。在11章中会探讨这个变量。指定interpolator时需要引用系统的动画资源(android:anim/interpolatorName)。 如果你不使用startOffset标签,动画集中的动画将同步执行。 接下来的例子显示了动画集控制目标在缩小淡出的同时旋转360度: Xml代码
Java代码
1. <?xml version=”1.0” encoding=”utf-8”?>
2.
3. <set xmlns:android=”http://schemas.android.com/apk/res/android”
4.
5. android:interpolator=”@android:anim/accelerate_interpolator”>
6.
7. <rotate
8.
9. android:fromDegrees=”0”
10.
11.android:toDegrees=”360”
12.
13.android:pivotX=”50%”
14.
15.android:pivotY=”50%”
16.
17.android:startOffset=”500”
18.
19.android:duration=”1000” />
20.
21.<scale
22.
23.android:fromXScale=”1.0”
24.
25.android:toXScale=”0.0”
26.
27.android:fromYScale=”1.0”
28.
29.android:toYScale=”0.0”
30.
31.android:pivotX=”50%”
32.
33.android:pivotY=”50%”
34.
35.android:startOffset=”500”
36.
37.android:duration=”500” />
38.
39.<alpha
40.
41.android:fromAlpha=”1.0”
42.
43.android:toAlpha=”0.0”
44.
45.android:startOffset=”500”
46.
47.android:duration=”500” />
48.
49.</set>
Frame-by-Frame Animations Frame-by-Frame动画用于View的背景上,显示一系列的图片,每张图片显示指定的时间。 因为Frame-by-Frame动画显示drawables,所以,它们也被放在/res/drawble文件夹下(和Tweened动画不同),并且使用它们的文件名作为它们的资源标识。 接下来的XML片段显示了一个简单的动画,它循环显示一些位图资源,每张位图显示0.5秒。为了能使用这个XML片段,你需要创建rocket1-rocket3 三个新的图片资源。
Java代码
1. Xml代码
2. <animation-list
3.
4. xmlns:android=”http://schemas.android.com/apk/res/android”
5.
6. android:oneshot=”false”>
7.
8. <item android:drawable=”@drawable/rocket1” android:duration=”500” />
9.
10.<item android:drawable=”@drawable/rocket2” android:duration=”500” />
11.
12.<item android:drawable=”@drawable/rocket3” android:duration=”500” />
13.
14.</animation-list>
看到了吧,在Activity运行的前后,无论状态怎么转移,onResume()和onPause()一定会被执行,与其说实现的巧妙,还不如赞一下这个生命周期的设计的巧妙,这个巧妙不是说说而已,有时间的话,看看MFC中一个windows或者dialog的生命周期,你就知道这个巧妙的含义了,我们可以省多少的事情啊!所以值得记住的是,在android中想在运行前后必须要执行的语句,就应该放在onResume()和onPause()中。
4)最后说一个对android小不爽的地方:drawable,什么鬼东西啊!在res/drawable放一个文件,访问的时候是drawable/name,如果在values里面建立一个drawable的变量,访问的时候也是drawable/name,例如在
drawable目录下放入一个red.xml文件,访问的时候是@drawable/red,如果建立一个drawable的变量red,访问也是@drawable/red,这完全就是两个东西啊,虽然最新的编辑器会提示重名,但查找的时候真的很不方便啊,尤其是drawable变量,可以放在一个abc.xml中,以后资源文件多了,管理起来想想都头麻,就不能把其中一个改改名字吗?把drawable变量叫成drawable_value不行吗?
用GridView实现Gallery的效果(转)
在实现横向的类似Gallery的效果中做了实现Gallery的尝试,但是效果不好。使用的是TableLayout,出现了横向拖动图片的时候,因为有倾斜(轻微的竖向拖动),会整个列表竖向滚动。其实这个问题可以将TableRow中条目设置为clickable来解决。但是效果依然不好。
这次尝试通过GridView来解决问题,效果很好,见截图:
基本思路是:
 每个可选的图,包括文字部分,是GridView中的一个条目;
 一个GridView条目是相对布局(RelativeLayout),里面包含一个图片(ImageView)和一个文字(TextView);
 关键点是GridView如何保持横向,默认的情况下会折行的,首先要用一个HorizontalScrollView提供横向滚动容器,然后内部放置一个FrameLayout,如果不放置FrameLayout布局,直接放入下面的布局或者视图,GridView将会变成单列纵向滚动,在FrameLayout布局中加入横向的LinearLayout布局,要设置它的layout_width,要足够大,这样在其中加入GridView就能横向排列了。
首先看一下GridView中条目的布局: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:paddingBottom="10.0dip" android:layout_width="90.0dip" android:layout_height="140.0dip"> <ImageView android:id="@+id/ItemImage" android:layout_width="80.0dip" android:layout_height="108.0dip" android:layout_marginLeft="10.0dip" android:layout_centerHorizontal="true"> </ImageView> <TextView android:layout_below="@+id/ItemImage" android:id="@+id/ItemText" android:ellipsize="end" android:layout_width="80.0dip" android:layout_height="26.0dip" android:layout_marginTop="5.0dip" android:singleLine="true" android:layout_centerHorizontal="true"> </TextView> </RelativeLayout>
这里使用了相对布局的特性,android:layout_below,表示TextView在ImageView下面。这里的图都是用的res/drawable目录下的静态图形文件,正式情况下,应该是从网络获取,可参见用Java concurrent编写异步加载图片功能的原型实现,二者结合可用于正式生产环境。
ListView的Header使用了自定义视图,更简单的示例可参见为ListView增加Header。表头(ListView Header)的布局文件: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="200dp"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="最近访问人物" /> <HorizontalScrollView android:layout_width="fill_parent" android:layout_height="160dp"> <FrameLayout android:layout_width="fill_parent" android:layout_height="match_parent">
<LinearLayout android:layout_width="1100dp" android:layout_height="match_parent" android:orientation="horizontal"> <GridView android:id="@+id/grid" android:layout_width="fill_parent" android:gravity="center" android:layout_height="fill_parent" android:horizontalSpacing="1.0dip" android:verticalSpacing="1.0dip" android:stretchMode="spacingWidthUniform" android:numColumns="auto_fit" android:columnWidth="80dip"> </GridView> </LinearLayout> </FrameLayout> </HorizontalScrollView> </LinearLayout>
这是比较关键的布局文件,GridView能实现横向滚动主要靠它了。其中: <LinearLayout android:layout_width="1100dp"
我是写死了1100dp,正式使用的时候,因为图片都可能是动态从服务器上获取的,可以根据数量以及图片的宽度,空白边动态计算这个长度。
GridView和ListView类似,都需要ViewAdapter来适配数据和视图。
见Activity的源代码: package com.easymorse.grid.demo; import java.util.ArrayList; import java.util.HashMap; import android.app.ListActivity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.widget.ArrayAdapter; import android.widget.GridView; import android.widget.ListView; import android.widget.SimpleAdapter; public class GridDemoActivity extends ListActivity { /** Called when the activity is first created. */ @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); LayoutInflater layoutInflater = (LayoutInflater) this .getSystemService("layout_inflater"); View headerView=layoutInflater.inflate(R.layout.list_header, null); setGridView(headerView); ListView listView=(ListView) this.findViewById(android.R.id.list); listView.addHeaderView(headerView); listView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,new String[]{"隋","唐","宋","元","明","清"})); } private void setGridView(View view) { GridView gridView = (GridView) view.findViewById(R.id.grid); gridView.setNumColumns(10); ArrayList<HashMap<String, Object>> items = new ArrayList<HashMap<String, Object>>(); for (int i = 0; i < 10; i++) { HashMap<String, Object> map = new HashMap<String, Object>(); map.put("ItemImage", R.drawable.k); map.put("ItemText", "清.康熙" + "(" + i + ")"); items.add(map); } SimpleAdapter adapter = new SimpleAdapter(this, items, R.layout.item, new String[] { "ItemImage", "ItemText" }, new int[] { R.id.ItemImage, R.id.ItemText }); gridView.setAdapter(adapter); } }
Android画图之Matrix(一)
Matrix ,中文里叫矩阵,高等数学里有介绍,在图像处理方面,主要是用于平面的缩放、平移、旋转等操作。
首先介绍一下矩阵运算。加法和减法就不用说了,太简单了,对应位相加就好。图像处理,主要用到的是乘法 。下面是一个乘法的公式:
在 Android 里面, Matrix 由 9 个 float 值构成,是一个 3*3 的矩阵。如下图。
没专业工具,画的挺难看。解释一下,上面的 sinX 和 cosX ,表示旋转角度的 cos 值和 sin 值,注意,旋转角度是按顺时针方向计算的。 translateX 和 translateY 表示 x 和 y 的平移量。 scale 是缩放的比例, 1 是不变, 2 是表示缩放 1/2 ,这样子。
下面在 Android 上试试 Matrix 的效果。
Java代码 1. public class MyView extends View { 2. 3. private Bitmap mBitmap; 4. 5. private Matrix mMatrix = new Matrix(); 6. 7. public MyView(Context context) { 8. 9. super(context); 10. 11. initialize(); 12. 13. } 14. 15. private void initialize() { 16. 17. mBitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.show)).getBitmap(); 18.
19. float cosValue = (float) Math.cos(-Math.PI/6); 20. 21. float sinValue = (float) Math.sin(-Math.PI/6); 22. 23. mMatrix.setValues( 24. 25. new float[]{ 26. 27. cosValue, -sinValue, 100, 28. 29. sinValue, cosValue, 100, 30. 31. 0, 0, 2}); 32. 33. } 34. 35. @Override protected void onDraw(Canvas canvas) { 36. 37. // super.onDraw(canvas); //当然,如果界面上还有其他元素需要绘制,只需要将这句话写上就行了。 38. 39. canvas.drawBitmap(mBitmap, mMatrix, null); 40. 41. } 42. 43. }
运行结果如下:
以左上角为顶点,缩放一半,逆时针旋转30度,然后沿x轴和y轴分别平移50个像素,代码 里面写的是100,为什么是平移50呢,因为缩放了一半。
大家可以自己设置一下Matrix的值,或者尝试一下两个Matrix相乘,得到的值设置进去,这样才能对Matrix更加熟练。
这里讲的直接赋值的方式也许有点不好理解,不过还好, andrid 提供了对矩阵的更方便的方法,下一篇介绍 。
Android画图之Matrix(二)
文章分类:移动开发
上一篇Android画图之Matrix(一) 讲了一下Matrix的原理和运算方法,涉及到高等数学,有点难以理解。还好Android里面提供了对Matrix操作的一系 列方便的接口。
Matrix的操作,总共分为translate(平移),rotate(旋转),scale(缩放)和skew(倾斜)四种,每一种变换在 Android的API里都提供了set, post和pre三种操作方式,除了translate,其他三种操作都可以指定中心点。
set是直接设置Matrix的值,每次set一次,整个Matrix的数组都会变掉。
post是后乘,当前的矩阵乘以参数给出的矩阵。可以连续多次使用post,来完成所需的整个变换。例如,要将一个图片旋 转30度,然后平移到(100,100)的地方,那么可以这样做:
Java代码
1. Matrix m = new Matrix();
2.
3. m.postRotate(30 );
4.
5. m.postTranslate(100 , 100 );
这样就达到了想要的效果。
pre是前乘,参数给出的矩阵乘以当前的矩阵。所以操作是在当前矩阵的最前面发生的。例如上面的例子,如果用pre的话 ,就要这样:
Java代码
1. Matrix m = new Matrix();
2.
3. m.setTranslate(100 , 100 );
4.
5. m.preRotate(30 );
旋转、缩放和倾斜都可以围绕一个中心点来进行,如果不指定,默认情况下,是围绕(0,0)点来进行。
下面给出一个例子。
Java代码
1. package chroya.demo.graphics;
2.
3. import android.content.Context;
4. import android.graphics.Bitmap;
5. import android.graphics.Canvas;
6. import android.graphics.Matrix;
7. import android.graphics.Rect;
8. import android.graphics.drawable.BitmapDrawable;
9. import android.util.DisplayMetrics;
10.import android.view.MotionEvent;
11.import android.view.View;
12.
13.public class MyView extends View {
14.
15. private Bitmap mBitmap;
16. private Matrix mMatrix = new Matrix();
17.
18. public MyView(Context context) {
19. super (context);
20. initialize();
21. }
22.
23. private void initialize() {
24.
25. Bitmap bmp = ((BitmapDrawable)getResources().getDrawable(R.drawable.show)).getBitmap();
26. mBitmap = bmp;
27. /*首先,将缩放为100*100。这里scale的参数是比例。有一点要注意,如果直接用100/
28.bmp.getWidth()的话,会得到0,因为是整型相除,所以必须其中有一个是float型的,直接用100f就好。*/
29. mMatrix.setScale(100f/bmp.getWidth(), 100f/bmp.getHeight());
30. //平移到(100,100)处
31. mMatrix.postTranslate(100 , 100 );
32. //倾斜x和y轴,以(100,100)为中心。
33. mMatrix.postSkew(0 .2f, 0 .2f, 100 , 100 );
34. }
35.
36. @Override protected void onDraw(Canvas canvas) {
37.// super.onDraw(canvas); //如果界面上还有其他元素需要绘制,只需要将这句话写上就行了。
38.
39. canvas.drawBitmap(mBitmap, mMatrix, null );
40. }
41.}
运行效果如下:
红色的x和y表示倾斜的角度,下面是x,上面是y。看到了没,Matrix就这么简单 。
XML属性
文章分类:移动开发
一、属性分类
1. View的属性
2. TextView的属性
二、View的属性
1. 基础属性
 android:id : 设定view的id。之后在代码里面可以通过View.findViewById()来获取相应的View
 android:tag : 设定view的tag。之后可以再代码里面通过View.findViewByTag来获取相应的View
2. 事件相关
2.1 Click事件相关
 android:clickable : view是否能对click事件作出反应。值域【true,false】
 android:onClick : 当view被click之后,view的context的哪个方法被呼叫。通常这个context是指vieW所在的Acitvity。例如:android:onClick = 'sayHello'.则相应的Activity里面有一个方法public void sayHello(View view)方法。当这个view被click之后,sayHello方法就会被调用。
 android:longClickable : view是否可以对长时间的click事件作出反应。值域【true,false】
2.1 Focus事件相关
 android:focusable : view是否能响应焦点事件
 android:
三、TextView的属性
其他的属性请参考:View的属性
1 文本相关的属性
1.1 文本属性
 android:text 文字
 android:typeface : 设定字体
 android:textStyle : 风格。值域【bold,italic,normal】。可以组合设定。例如:bold | italic
 android:textSize : 文字大小
 android:textColor : 文字的颜色
 android:textColorHight : 文字被选择的时候,高亮的颜色
1.2 提示文本相关的属性
 android:hint 当文本内容为空时,提示信息
 android:textColorHint 提示文本的颜色
2. 输入内容的控制
 android:number 只能输入数字。值域【integer , decimal , signed】,可以组合设定。例如:integer | signed
 2010-10-22
Android中的长度单位详解(dp、sp、px、in、pt、mm)
 文章分类:移动开发
 看到有很多网友不太理解dp、sp和px的区别:现在这里介绍一下dp和sp。dp也就是dip。这个和sp基本类似。如果设置表示长度、高度等属性时可以使用dp 或sp。但如果设置字体,需要使用sp。dp是与密度无关,sp除了与密度无关外,还与scale无关。如果屏幕密度为160,这时dp和sp和px是一样的。1dp=1sp=1px,但如果使用px作单位,如果屏幕大小不变(假设还是3.2寸),而屏幕密度变成了320。那么原来TextView的宽度设成160px,在密度为320的3.2寸屏幕里看要比在密度为160的3.2寸屏幕上看短了一半。但如果设置成160dp或160sp的话。系统会自动将width属性值设置成320px的。也就是160 * 320 / 160。其中320 / 160可称为密度比例因子。也就是说,如果使用dp和sp,系统会根据屏幕密度的变化自动进行转换。
下面看一下其他单位的含义 px:表示屏幕实际的象素。例如,320*480的屏幕在横向有320个象素,在纵向有480个象素。 in:表示英寸,是屏幕的物理尺寸。每英寸等于2.54厘米。例如,形容手机屏幕大小,经常说,3.2(英)寸、3.5(英)寸、4(英)寸就是指这个单位。这些尺寸是屏幕的对角线长度。如果手机的屏幕是3.2英寸,表示手机的屏幕(可视区域)对角线长度是3.2*2.54 = 8.128厘米。读者可以去量一量自己的手机屏幕,看和实际的尺寸是否一致。 mm:表示毫米,是屏幕的物理尺寸。 pt:表示一个点,是屏幕的物理尺寸。大小为1英寸的1/72。
原创--解剖android Style原理从Button入手
文章分类:移动开发
转载 声明原处 :博客http://pk272205020.blog.163.com/ 参考论坛外国android论坛http://www.androidpeople.com/ 参考资料:android Button 原理 这几日都是看android SDK原码,想封装一个HERO 效果的UI界面。刚想以为很容易,但越做越难,为有百度,Google求救,但这方面的资料还是不多,这个我也不怪了,可能android 在中国的市场还是刚刚起步。外面的一些网站 android 技术论坛打不开,闷 ... 但我发现http://www.android.com/ 可以打开了,以前要用XX软件先打得开,但里面的developer标签还是俾中国网关封,这个更郁闷... 不讲了,直入正题 android Styel原理 刚刚开始得写时从最简单的Button 入手,下载SDK原码候Button 继续TextView 原码里就三个构造方法....
Java代码
1. @RemoteView
2. public class Button extends TextView {
3. public Button(Context context) {
4. this(context, null);
5. }
6.
7. public Button(Context context, AttributeSet attrs) {
8. this(context, attrs, com.android.internal.R.a ttr.buttonStyle);
9. }
10.
11. public Button(Context context, AttributeSet attrs, int defStyle) {
12. super(context, attrs, defStyle);
13. }
14.}[
默认样式:com.android.internal.R.attr.buttonStyle ,android 的style 太强大, 网上有人说过是 GWT模式, 在校的时候我也用过GWT写过小网页,HTML文件里标签里嵌入GWT标签,通过服务端Java代码生成页面,GWT就讲到这里,有开展过GWT的同志就知道这个也很像android的Layout布局文件,哈哈 我也是认同网上的人说。 知道android 的Style模式后,我们要进一步了解内部的实现,我们要打开 com.android.internal.R.attr.buttonStyle这个对应的XML
Xml代码
1. < style name="Widget.Button" >
2.
3. < item name="android:background">@android:drawable/btn_default< /item>
4.
5. < item name="android:focusable" >true< /item >
6.
7. < item name="android:clickable" >true< /item >
8.
9. < item name="android:textSize" >20sp< /item >
10.
11.< item name="android:textStyle" >normal< /item >
12.
13.< item name="android:textColor" >@android:color/button_text </item >
14.
15.<item name="android:gravity">center_vertical|center_horizontal>
16.< /item>
17.
18.< /style >
这个文件定义了好多style相关的属性,每个属性都好理解,这个backgroud属性难道仅仅是一个drawable图片?如果仅仅是一个图片的化,怎么能够实现button各种状态下表现出不同背景的功能呢?还是来看看这个drawable到底是什么东西。 还是埋头苦干地找出答案 在drwable目录中发现这个btn_default这个文件,还有许多这样的xml文件,看名字可以估到是什么来的 btn_default.xml 内容
Xml代码
1. < selector xmlns:android="http://schemas.android.com/apk/res/android">
2.
3. < item android:state_window_focused="false" android:state_enabled="true"
4. android:drawable="@drawable/btn_default_normal" / >
5.
6. < item android:state_window_focused="false" android:state_enabled="false"
7. android:drawable="@drawable/btn_default_normal_disable" / >
8.
9. < item android:state_pressed="true"
10.android:drawable="@drawable/btn_default_pressed" / >
11.
12.< item android:state_focused="true" android:state_enabled="true"
13.android:drawable="@drawable/btn_default_selected" / >
14.
15.< item android:state_enabled="true"
16.android:drawable="@drawable/btn_default_normal" / >
17.
18.< item android:state_focused="true"
19.android:drawable="@drawable/btn_default_normal_disable_focused" / >
20.
21.< item android:drawable="@drawable/btn_default_normal_disable" / >
22.
23.< /selector >
在android 中drawable文件是看图片存放的,最普通的就是一个图片。而这里用到的是StateListDrawable。当Android的解析器解析到上面的xml时,会自动转化成一个StateListDrawable类的实例,看看SDK是这样说的 Lets you assign a number of graphic images to a single Drawable and swap out the visible item by a string ID value. It can be defined in an XML file with the <selector> element. Each state Drawable is defined in a nested <item> element. For more information, see the guide to Drawable Resources. 意思就是通过字符串标识符值ID 分配单个可绘制可切换 的可视图形项 看看核心代码吧:大部多代码删除了
Java代码
1. public class StateListDrawable extends DrawableContainer {
2. /**
3. * To be proper, we should have a getter for dither (and alpha, etc.)
4. * so that proxy classes like this can save/restore their delegates'
5. * values, but we don't have getters. Since we do have setters
6. * (e.g. setDither), which this proxy forwards on, we have to have some
7. * default/initial setting.
8. *
9. * The initial setting for dither is now true, since it almost always seems
10.* to improve the quality at negligible cost.
11.*/
12.private static final boolean DEFAULT_DITHER = true;
13.private final StateListState mStateListState;
14.private boolean mMutated;
15.
16.public StateListDrawable() {
17.this(null, null);
18.}
19.
20./**
21.* Add a new image/string ID to the set of images.
22.*
23.* @param stateSet - An array of resource Ids to associate with the image.
24.* Switch to this image by calling setState().
25.* @param drawable -The image to show.
26.*/
27.public void addState(int[] stateSet, Drawable drawable) {
28.if (drawable != null) {
29.mStateListState.addStateSet(stateSet, drawable);
30.// in case the new state matches our current state...
31.onStateChange(getState());
32.}
33.}
34.
35.@Override
36.public boolean isStateful() {
37.return true;
38.}
39.
40.@Override
41.protected boolean onStateChange(int[] stateSet) {
42.int idx = mStateListState.indexOfStateSet(stateSet);
43.if (idx < 0) {
44.idx = mStateListState.indexOfStateSet(StateSet.WILD_CARD);
45.}
46.if (selectDrawable(idx)) {
47.return true;
48.}
49.return super.onStateChange(stateSet);
50.}
51.
52.
53./**
54.* Gets the state set at an index.
55.*
56.* @param index The index of the state set.
57.* @return The state set at the index.
58.* @hide pending API council
59.* @see #getStateCount()
60.* @see #getStateDrawable(int)
61.*/
62.public int[] getStateSet(int index) {
63.return mStateListState.mStateSets[index];
64.}
65.
66.
67.static final class StateListState extends DrawableContainerState {
68.private int[][] mStateSets;
69.
70.StateListState(StateListState orig, StateListDrawable owner, Resources res) {
71.super(orig, owner, res);
72.
73.if (orig != null) {
74.mStateSets = orig.mStateSets;
75.} else {
76.mStateSets = new int[getChildren().length][];
77.}
78.}
79.
80.
81.
82.
83. int addStateSet(int[] stateSet, Drawable drawable) {
84. final int pos = addChild(drawable);
85. mStateSets[pos] = stateSet;
86. return pos;
87. }
88.
89.
90.}
91.
92.private StateListDrawable(StateListState state, Resources res) {
93.StateListState as = new StateListState(state, this, res);
94.mStateListState = as;
95.setConstantState(as);
96.onStateChange(getState());
97.}
98.}
xml中每一个Item就对应一种状态,而每一个有state_的属性就是描述状态,drawable则是真正的drawable图片。当把这个实例付给View作为Background的时候,View会根据不同的state来切换不同状态的图片,从而实现了Press等诸多效果。简单看一下View中有关状态切换的代码吧:
Java代码
1. /**
2. * The order here is very important to {@link #getDrawableState()}
3. */
4. private static final int[][] VIEW_STATE_SETS = {
5. EMPTY_STATE_SET, // 0 0 0 0 0
6. WINDOW_FOCUSED_STATE_SET, // 0 0 0 0 1
7. SELECTED_STATE_SET, // 0 0 0 1 0
8. SELECTED_WINDOW_FOCUSED_STATE_SET, // 0 0 0 1 1
9. FOCUSED_STATE_SET, // 0 0 1 0 0
10.FOCUSED_WINDOW_FOCUSED_STATE_SET, // 0 0 1 0 1
11.FOCUSED_SELECTED_STATE_SET, // 0 0 1 1 0
12.FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 0 0 1 1 1
13.ENABLED_STATE_SET, // 0 1 0 0 0
14.ENABLED_WINDOW_FOCUSED_STATE_SET, // 0 1 0 0 1
15.ENABLED_SELECTED_STATE_SET, // 0 1 0 1 0
16.ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 0 1 0 1 1
17.ENABLED_FOCUSED_STATE_SET, // 0 1 1 0 0
18.ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET, // 0 1 1 0 1
19.ENABLED_FOCUSED_SELECTED_STATE_SET, // 0 1 1 1 0
20.ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 0 1 1 1 1
21.PRESSED_STATE_SET, // 1 0 0 0 0
22.PRESSED_WINDOW_FOCUSED_STATE_SET, // 1 0 0 0 1
23.PRESSED_SELECTED_STATE_SET, // 1 0 0 1 0
24.PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 0 0 1 1
25.PRESSED_FOCUSED_STATE_SET, // 1 0 1 0 0
26.PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET, // 1 0 1 0 1
27.PRESSED_FOCUSED_SELECTED_STATE_SET, // 1 0 1 1 0
28.PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 0 1 1 1
29.PRESSED_ENABLED_STATE_SET, // 1 1 0 0 0
30.PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET, // 1 1 0 0 1
31.PRESSED_ENABLED_SELECTED_STATE_SET, // 1 1 0 1 0
32.PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 1 0 1 1
33.PRESSED_ENABLED_FOCUSED_STATE_SET, // 1 1 1 0 0
34.PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET, // 1 1 1 0 1
35.PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET, // 1 1 1 1 0
36.PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 1 1 1 1
37.};
详细打开View.java 自己看 下面是setBackground方法,红字就是是state切换 ,View 这个类太长了, android2.2 版一共9321行
Java代码
1. /**
2. * Set the background to a given Drawable, or remove the background. If the
3. * background has padding, this View's padding is set to the background's
4. * padding. However, when a background is removed, this View's padding isn't
5. * touched. If setting the padding is desired, please use
6. * {@link #setPadding(int, int, int, int)}.
7. *
8. * @param d The Drawable to use as the background, or null to remove the
9. * background
10. */
11. public void setBackgroundDrawable(Drawable d) {
12. boolean requestLayout = false;
13.
14. mBackgroundResource = 0;
15.
16. ...............
17.
18. if (d.isStateful()) {
19. d.setState(getDrawableState());
20. }
21. d.setVisible(getVisibility() == VISIBLE, false);
22. mBGDrawable = d;
23.
24. ...............
25.
26. mBackgroundSizeChanged = true;
27. invalidate();
28.}
setBackgound方法先判断Drawable对象是否支持state切换 如果支持,设置状态就可达到图片切换的效果。 就写到这里
Android-----使用Button特效 selector+shape
文章分类:移动开发
当然除了使用drawable这样的图片外今天谈下自定义图形shape的方法,对于Button控件Android上支持以下几种属性shape、gradient、stroke、corners等。
我们就以目前系统的Button的selector为例说下:
Java代码
1. <shape>
2. <gradient
3. android:startColor="#ff8c00"
4. android:endColor="#FFFFFF"
5. android:angle="270" />
6. <stroke
7. android:width="2dp"
8. android:color="#dcdcdc" />
9. <corners
10. android:radius="2dp" />
11.<padding
12. android:left="10dp"
13. android:top="10dp"
14. android:right="10dp"
15. android:bottom="10dp" />
16.</shape>
对于上面,这条shape的定义,分别为渐变,在gradient中startColor属性为开始的颜色,endColor为渐变结束的颜色,下面的angle是角度。接下来是stroke可以理解为边缘,corners为拐角这里radius属性为半径,最后是相对位置属性padding。
对于一个Button完整的定义可以为:
Java代码
1. <?xml version="1.0" encoding="utf-8"?>
2. <selector
3. xmlns:android="http://www.norkoo.com">
4. <item android:state_pressed="true" >
5. <shape>
6. <gradient
7. android:startColor="#ff8c00"
8. android:endColor="#FFFFFF"
9. android:angle="270" />
10. <stroke
11. android:width="2dp"
12. android:color="#dcdcdc" />
13. <corners
14. android:radius="2dp" />
15. <padding
16. android:left="10dp"
17. android:top="10dp"
18. android:right="10dp"
19. android:bottom="10dp" />
20. </shape>
21. </item>
22.
23. <item android:state_focused="true" >
24. <shape>
25. <gradient
26. android:startColor="#ffc2b7"
27. android:endColor="#ffc2b7"
28. android:angle="270" />
29. <stroke
30. android:width="2dp"
31. android:color="#dcdcdc" />
32. <corners
33. android:radius="2dp" />
34. <padding
35. android:left="10dp"
36. android:top="10dp"
37. android:right="10dp"
38. android:bottom="10dp" />
39. </shape>
40. </item>
41.
42. <item>
43. <shape>
44. <gradient
45. android:startColor="#ff9d77"
46. android:endColor="#ff9d77"
47. android:angle="270" />
48. <stroke
49. android:width="2dp"
50. android:color="#fad3cf" />
51. <corners
52. android:radius="2dp" />
53. <padding
54. android:left="10dp"
55. android:top="10dp"
56. android:right="10dp"
57. android:bottom="10dp" />
58. </shape>
59. </item>
60.</selector>
注意!提示大家,以上几个item的区别主要是体现在state_pressed按下或state_focused获得焦点时,当当来判断显示什么类型,而没有state_xxx属性的item可以看作是常规状态下。
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:color="hex_color"
android:state_pressed=["true" | "false"]
android:state_focused=["true" | "false"]
android:state_selected=["true" | "false"]
android:state_active=["true" | "false"]
android:state_checkable=["true" | "false"]
android:state_checked=["true" | "false"]
android:state_enabled=["true" | "false"]
android:state_window_focused=["true" | "false"] />
</selector>
Elements:
<selector>
必须。必须是根元素。包含一个或多个<item>元素。
Attributes:
xmlns:android
String,必须。定义XML的命名空间,必须是
“http://schemas.android.com/apk/res/android”.
<item>
定义特定状态的color,通过它的特性指定。必须是<selector>的子元素。
Attributes:
android:color
16进制颜色。必须。这个颜色由RGB值指定,可带Alpha。
这个值必须以“#”开头,后面跟随Alpha-Red-Green-Blue信息:
 #RGB
 #ARGB
 #RRGGBB
 #AARRGGBB
android:state_pressed
Boolean。“true”表示按下状态使用(例如按钮按下);“false”表示非按下状态使用。
android:state_focused
Boolean。“true”表示聚焦状态使用(例如使用滚动球/D-pad聚焦Button);“false”表示非聚焦状态使用。
android:state_selected
Boolean。“true”表示选中状态使用(例如Tab打开);“false”表示非选中状态使用。
android:state_checkable
Boolean。“true”表示可勾选状态时使用;“false”表示非可勾选状态使用。(只对能切换可勾选—非可勾选的构件有用。)
android:state_checked
Boolean。“true”表示勾选状态使用;“false”表示非勾选状态使用。
android:state_enabled
Boolean。“true”表示可用状态使用(能接收触摸/点击事件);“false”表示不可用状态使用。
android:window_focused
Boolean。“true”表示应用程序窗口有焦点时使用(应用程序在前台);“false”表示无焦点时使用(例如Notification栏拉下或对话框显示)。
注意:记住一点,StateList中第一个匹配当前状态的item会被使用。因此,如果第一个item没有任何状态特性的话,那么它将每次都被使用,这也是为什么默认的值必须总是在最后(如下面的例子所示)。
Examples:
XML文件保存在res/color/button_text.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:color="#ffff0000"/> <!-- pressed -->
<item android:state_focused="true"
android:color="#ff0000ff"/> <!-- focused -->
<item android:color="#ff000000"/> <!-- default -->
</selector>
这个Layout XML会应用ColorStateList到一个View上:
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/button_text"
android:textColor="@color/button_text" />
Android——字符高亮显示(转载)
文章分类:移动开发
Java代码
1. String str="adsjoiasdjpaisdjpaidj";
2. /** Called when the activity is first created. */
3. @Override
4. public void onCreate(Bundle savedInstanceState) {
5. super.onCreate(savedInstanceState);
6. setContentView(R.layout.main);
7. TextView textview=(TextView)findViewById(R.id.textView);
8. SpannableStringBuilder style=new SpannableStringBuilder(str);
9. style.setSpan(new ForegroundColorSpan(Color.RED),3,8,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
10. textview.setText(style);
11.}
Android SDCard操作(文件读写,容量计算)
文章分类:移动开发
android.os.Environment 提供访问环境变量 java.lang.Object android.os.Environment Environment 静态方法:
方法 : getDataDirectory () 返回 : File 解释 : 返回Data的目录 方法 : getDownloadCacheDirectory () 返回 : File 解释 : 返回下载缓冲区目录 方法 : getExternalStorageDirectory () 返回 : File 解释 : 返回扩展存储区目录(SDCard) 方法 : getExternalStoragePublicDirectory (String type) 返回 : File 解释 : 返回一个高端的公用的外部存储器目录来摆放某些类型的文件(来自网上) 方法 : getRootDirectory () 返回 : File 解释 : 返回Android的根目录 方法 : getExternalStorageState () 返回 : String 解释 : 返回外部存储设备的当前状态
getExternalStorageState () 返回的状态String 类型常量 : 常量 : MEDIA_BAD_REMOVAL 值 : "bad_removal" 解释 : 在没有正确卸载SDCard之前移除了 常量 :MEDIA_CHECKING 值 : "checking" 解释 : 正在磁盘检查 常量 : MEDIA_MOUNTED 值 : "mounted" 解释 : 已经挂载并且拥有可读可写权限 常量 : MEDIA_MOUNTED_READ_ONLY 值 : "mounted_ro" 解释 : 已经挂载,但只拥有可读权限 常量 :MEDIA_NOFS 值 : "nofs" 解释 : 对象空白,或者文件系统不支持 常量 : MEDIA_REMOVED 值 : "removed" 解释 : 已经移除扩展设备
常量 : MEDIA_SHARED 值 : "shared" 解释 : 如果SDCard未挂载,并通过USB大容量存储共享 常量 : MEDIA_UNMOUNTABLE 值 : "unmountable" 解释 : 不可以挂载任何扩展设备 常量 : MEDIA_UNMOUNTED 值 : "unmounted" 解释 : 已经卸载 使用时只需先判断SDCard当前的状态然后取得SdCard的目录即可(见源代码)
Java代码
1. <SPAN style="FONT-SIZE: small"> 1 //SDcard 操作
2. public void SDCardTest() {
3. // 获取扩展SD卡设备状态
4. String sDStateString = android.os.Environment.getExternalStorageState();
5.
6. // 拥有可读可写权限
if (sDStateString.equals(android.os.Environment.MEDIA_MOUNTED)) {
try {
// 获取扩展存储设备的文件目录
7. File SDFile = android.os.Environment
8. .getExternalStorageDirectory();
// 打开文件
9. File myFile = new File(SDFile.getAbsolutePath()
10. + File.separator + "MyFile.txt");
11. // 判断是否存在,不存在则创建
12. if (!myFile.exists()) {
13. myFile.createNewFile();
14. }
15. // 写数据
16. String szOutText = "Hello, World!";
17. FileOutputStream outputStream = new FileOutputStream(myFile);
18. outputStream.write(szOutText.getBytes());
19. outputStream.close();
20. } catch (Exception e) {
21. // TODO: handle exception
}// end of try
22.}// end of if(MEDIA_MOUNTED)
23.// 拥有只读权限
24.else if (sDStateString
25. .endsWith(android.os.Environment.MEDIA_MOUNTED_READ_ONLY)) {
26. // 获取扩展存储设备的文件目录
27. File SDFile = android.os.Environment
28. .getExternalStorageDirectory();
29.// 创建一个文件
30.File myFile = new File(SDFile.getAbsolutePath()
31. + File.separator
32. + "MyFile.txt");
33.// 判断文件是否存在
34.if (myFile.exists()) {
35. try {
36. // 读数据
37. FileInputStream inputStream = new FileInputStream(myFile);
38. byte[] buffer = new byte[1024];
39. inputStream.read(buffer);
40. inputStream.close();
41. } catch (Exception e) {
42. // TODO: handle exception
43.}// end of try
}// end of if(myFile)
44.}// end of if(MEDIA_MOUNTED_READ_ONLY)
45.}// end of func</SPAN>
计算SDCard的容量大小 android.os.StatFs 一个模拟linux的df命令的一个类,获得SD卡和手机内存的使用情况 java.lang.Object android.os.StatFs 构造方法: StatFs (String path) 公用方法: 方法 : getAvailableBlocks () 返回 : int 解释 :返回文件系统上剩下的可供程序使用的块 方法 : getBlockCount () 返回 : int 解释 : 返回文件系统上总共的块 方法 : getBlockSize () 返回 : int 解释 : 返回文件系统 一个块的大小单位byte 方法 : getFreeBlocks () 返回 : int
解释 : 返回文件系统上剩余的所有块 包括预留的一般程序无法访问的 方法 : restat (String path) 返回 : void 解释 : 执行一个由该对象所引用的文件系统雷斯塔特.(Google翻译) 想计算SDCard大小和使用情况时, 只需要得到SD卡总共拥有的Block数或是剩余没用的Block数,再乘以每个Block的大小就是相应的容量大小了单位byte.(见代码)
Java代码
1. <SPAN style="FONT-SIZE: small"> 1
2. public void SDCardSizeTest() {
3. 2
4. 3 // 取得SDCard当前的状态
5. 4 String sDcString = android.os.Environment.getExternalStorageState();
6. 5
7. 6 if (sDcString.equals(android.os.Environment.MEDIA_MOUNTED)) {
8. 7
9. 8 // 取得sdcard文件路径
10. 9 File pathFile = android.os.Environment
11.10 .getExternalStorageDirectory();
12.11
13.12 android.os.StatFs statfs = new android.os.StatFs(pathFile.getPath());
14.13
15.14 // 获取SDCard上BLOCK总数
16.15 long nTotalBlocks = statfs.getBlockCount();
17.16
18.17 // 获取SDCard上每个block的SIZE
19.18 long nBlocSize = statfs.getBlockSize();
20.19
21.20 // 获取可供程序使用的Block的数量
22.21 long nAvailaBlock = statfs.getAvailableBlocks();
23.22
24.23 // 获取剩下的所有Block的数量(包括预留的一般程序无法使用的块)
25.24 long nFreeBlock = statfs.getFreeBlocks();
26.25
27.26 // 计算SDCard 总容量大小MB
28.27 long nSDTotalSize = nTotalBlocks * nBlocSize / 1024 / 1024;
29.28
30.29 // 计算 SDCard 剩余大小MB
31.30 long nSDFreeSize = nAvailaBlock * nBlocSize / 1024 / 1024;
32.31 }// end of if
33.32 }// end of func</SPAN>
Android将ButtonBar放在屏幕底部 ? 转烛空间(转载)
文章分类:移动开发
接上篇《Android将TAB选项卡放在屏幕底部》写。上篇提到ButtonBar的方式写底部button,试了试,看起来外观貌似比Tab好看,不过恐怕没有Tab管理Activity方便吧,毕竟一个Tab就是一个Activity,但是这样用Button的话,却并不如此,所以这样的涉及可能虽然好看点,但是管理起来却是相当麻烦。那么暂且把对 activity的管理放在一边,只看界面的设计吧。
要涉及这样的一个buttonbar,主要就是要用到style="@android:style/ButtonBar"这个风格。首先还是来看xml的设计,保存layout/bottombtn.xml
Java代码
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. android:orientation="vertical"
4. android:layout_width="fill_parent"
5. android:layout_height="fill_parent">
6.
7. <TabHost android:id="@+id/edit_item_tab_host"
8. android:layout_width="fill_parent"
9. android:layout_height="fill_parent">
10.<LinearLayout android:orientation="vertical"
11. android:layout_width="fill_parent"
12. android:layout_height="fill_parent"
13. android:padding="5dp">
14.<FrameLayout android:id="@android:id/tabcontent"
15. android:layout_width="fill_parent"
16. android:layout_height="wrap_content"
17. android:padding="5dp"
18. android:layout_weight="1" />
19.<TabWidget android:id="@android:id/tabs"
20. android:layout_width="fill_parent"
21. android:layout_height="wrap_content"
22. android:layout_weight="0" />
23.</LinearLayout>
24.</TabHost>
25.</LinearLayout>
然后以下就是完整的代码了:
Java代码
1. package net.wangliping.test;
2.
3. import android.app.ActivityGroup;
4. import android.content.Intent;
5. import android.os.Bundle;
6. import android.widget.TabHost;
7. import android.widget.TabHost.TabSpec;
8.
9. public class TestTab extends ActivityGroup {
10. public static TabHost tab_host;
11. @Override
12. protected void onCreate(Bundle savedInstanceState) {
13. super.onCreate(savedInstanceState);
14. setContentView(R.layout.bottomtab);
15.
16. tab_host = (TabHost) findViewById(R.id.edit_item_tab_host);
17. tab_host.setup(this.getLocalActivityManager());
18.
19. TabSpec ts1 = tab_host.newTabSpec("TAB_WEATHER");
20. ts1.setIndicator("Weather");
21. ts1.setContent(new Intent(this, Weather.class));
22. tab_host.addTab(ts1);
23.
24. TabSpec ts2 = tab_host.newTabSpec("TAB_MAIL");
25. ts2.setIndicator("Mail");
26. ts2.setContent(new Intent(this, MailSend.class));
27. tab_host.addTab(ts2);
28.
29. TabSpec ts3 = tab_host.newTabSpec("TAB_JUMP");
30. ts3.setIndicator("Jump");
31. ts3.setContent(new Intent(this, TabJump.class));
32. tab_host.addTab(ts3);
33.
34. tab_host.setCurrentTab(0);
35. }
36.}
而关于页面的跳转,就是:
Java代码
1. TestTab.tabHost.setCurrentTab(0);
如此这般,就形成了下面的这个东西,其实还没有放在上面好看。。。所以也证实了上面那个应用不是简单地放置TAB在底端了。有机会还是再看看ButtonBar了。
Android2.2 API 中文文档系列(1) —— TextView
文章分类:移动开发
正文
一、TextView的API 中文文档
1.1 结构
java .lang.Object ↳ android.view.View ↳ android.widget.TextView
直接子类:
Button, CheckedTextView, Chronometer, DigitalClock, EditText
间接子类: AutoCompleteTextView, CheckBox, CompoundButton, ExtractEditText,MultiAutoCompleteTextView, RadioButton, ToggleButton
1.2 API
属性名称
描述
android:autoLink
设置是否当文本为URL链接/email/电话号码/map时,文本显示为可点击的链接。可选值(none/web/email/phone/map/all)
android:autoText
如果设置,将自动执行输入值的拼写纠正。此处无效果,在显示输入法并输入的时候起作用。
android:bufferType
指定getText()方式取得的文本类别。选项editable 类似于StringBuilder可追加字符,
也就是说getText后可调用append方法设置文本内容。spannable 则可在给定的字符区域使用样式,参见这里1 、这里2 。
android:capitalize
设置英文字母大写类型。此处无效果,需要弹出输入法才能看得到,参见EditText此属性说明。
android:cursorVisible
设定光标为显示/隐藏,默认显示。
android:digits
设置允许输入哪些字符。如“1234567890.+-*/%\n()”
android:drawableBottom
在text的下方输出一个drawable,如图片。如果指定一个颜色的话会把text的背景设为该颜色,并且同时和background使用时覆盖后者。
android:drawableLeft
在text的左边输出一个drawable,如图片。
android:drawablePadding
设置text与drawable(图片)的间隔,与drawableLeft、drawableRight、drawableTop、drawableBottom一起使用,可设置为负数,单独使用没有效果。
android:drawableRight
在text的右边输出一个drawable,如图片。
android:drawa
在text的正上方输出一个drawable,如图片。
bleTop
android:editable
设置是否可编辑。这里无效果,参见EditView。
android:editorExtras
设置文本的额外的输入数据。在EditView再讨论。
android:ellipsize
设置当文字过长时,该控件该如何显示。有如下值设置:”start”—–省略号显示在开头;”end”——省略号显示在结尾;”middle”—-省略号显示在中间;”marquee” ——以跑马灯 的方式显示(动画横向移动 )
android:freezesText
设置保存文本的内容以及光标的位置。参见:这里 。
android:gravity
设置文本位置,如设置成“center”,文本将居中显示。
android:hint
Text为空时显示的文字提示信息,可通过textColorHint设置提示信息的颜色。此属性在EditView中使用,但是这里也可以用。
android:imeOptions
附加功能,设置右下角IME动作与编辑框相关的动作,如actionDone右下角将显示一个“完成”,而不设置默认是一个回车符号。这个在EditText中再详细说明,此处无用。
android:imeActionId
设置IME动作ID。在EditText再做说明,可以先看这篇帖子:这里 。
android:imeActionLabel
设置IME动作标签。在EditText再做说明。
android:includeFontPadding
设置文本是否包含顶部和底部额外空白,默认为true。
android:inputMethod
为文本指定输入法,需要完全限定名(完整的包名)。例如:com.google.android.inputmethod.pinyin,但是这里报错找不到。
android:inputType
设置文本的类型,用于帮助输入法显示合适的键盘类型。在EditText中再详细说明,这里无效果。
android:linksClickable
设置链接是否点击连接,即使设置了autoLink。
android:marqueeRepeatLimit
在ellipsize指定marquee的情况下,设置重复滚动的次数,当设置为marquee_forever时表示无限次。
android:ems
设置TextView的宽度为N个字符的宽度。这里测试为一个汉字字符宽度,如图:
android:maxEms
设置TextView的宽度为最长为N个字符的宽度。与ems同时使用时覆盖ems选项。
android:minEms
设置TextView的宽度为最短为N个字符的宽度。与ems同时使用时覆盖ems选项。
android:maxLength
限制显示的文本长度,超出部分不显示。
android:lines
设置文本的行数,设置两行就显示两行,即使第二行没有数据。
android:maxLines
设置文本的最大显示行数,与width或者layout_width结合使用,超出部分自动换行,超出行数将不显示。
android:minLines
设置文本的最小行数,与lines类似。
android:lineSpacingExtra
设置行间距。
android:lineSpacingMultiplier
设置行间距的倍数。如”1.2”
android:numeric
如果被设置,该TextView有一个数字输入法。此处无用,设置后唯一效果是TextView有点击效果,此属性在EditText将详细说明。
android:password
以小点”.”显示文本
android:phoneNumber
设置为电话号码的输入方式。
android:priva
设置输入法选项,此处无用,在EditText将进一步讨论。
teImeOptions
android:scrollHorizontally
设置文本超出TextView的宽度的情况下,是否出现横拉条。
android:selectAllOnFocus
如果文本是可选择的,让他获取焦点而不是将光标移动为文本的开始位置或者末尾位置。EditText中设置后无效果。
android:shadowColor
指定文本阴影的颜色,需要与shadowRadius一起使用。效果:
android:shadowDx
设置阴影横向坐标开始位置。
android:shadowDy
设置阴影纵向坐标开始位置。
android:shadowRadius
设置阴影的半径。设置为0.1就变成字体的颜色了,一般设置为3.0的效果比较好。
android:singleLine
设置单行显示。如果和layout_width一起使用,当文本不能全部显示时,后面用“„”来表示。如android:text="test_ singleLine " android:singleLine="true" android:layout_width="20dp"将只显示“t„”。如果不设置singleLine或者设置为false,文本将自动换行
android:text
设置显示文本.
android:textAppearance
设置文字外观。如“?android:attr/textAppearanceLargeInverse
”这里引用的是系统自带的一个外观,?表示系统是否有这种外观,否则使用默认的外观。可设置的值如下:textAppearanceButton/textAppearanceInverse/textAppearanceLarge /textAppearanceLargeInverse/textAppearanceMedium/textAppearanceMediumInverse/textAppearanceSmall/textAppearanceSmallInverse
android:textColor
设置文本颜色
android:textColorHighlight
被选中文字的底色,默认为蓝色
android:textColorHint
设置提示信息文字的颜色,默认为灰色。与hint一起使用。
android:textColorLink
文字链接的颜色.
android:textScaleX
设置文字之间间隔,默认为1.0f。分别设置0.5f/1.0f/1.5f/2.0f效果如下:
android:textSize
设置文字大小,推荐度量单位”sp”,如”15sp”
android:textStyle
设置字形[bold(粗体) 0, italic(斜体) 1, bolditalic(又粗又斜) 2] 可以设置一个或多个,用“|”隔开
android:typeface
设置文本字体,必须是以下常量值之一:normal 0, sans 1, serif 2, monospace(等宽字体) 3]
android:height
设置文本区域的高度,支持度量单位:px(像素)/dp/sp/in/mm(毫米)
android:maxHeight
设置文本区域的最大高度
android:minHeight
设置文本区域的最小高度
android:width
设置文本区域的宽度,支持度量单位:px(像素)/dp/sp/in/mm(毫米),与layout_width的区别看这里 。
android:maxWidth
设置文本区域的最大宽度
android:minWidth
设置文本区域的最小宽度
1.3 补充说明
1.3.1 以下几个属性以及输入法相关的在这里都没有效果,在EditText将补充说明。
android:numeric/android:digits/android:phoneNumber/android:inputMethod/android:capitalize/android:autoText
1.4 Word 格式的API文档下载
http://download.csdn.net/source/2649980
二、例子
2.1 跑马灯的效果
http://www.cnblogs.com/over140/archive/2010/08/20/1804770.html
结束
鉴于至此仍未有完整的Android API中文文档公布出来,我会一直坚持翻译到有其他组织或官方出完整的API中文文档为止。在这里感谢女朋友的支持和帮助,为我提供日中翻译(将 Android API日文版翻译成中文)和英中翻译;感谢翻译工具和搜索引擎以及其他提供部分属性翻译参考的分享者;感谢大家的支持!
Android 震动示例--心跳效果
正在开发第二个游戏,计时就要结束的时候,为了营造紧张的气氛,会利用手机自身的震动模拟心跳效果,其实这个心跳效果做起来真的非常的简单。所以直接上代码了(注意模拟器是模拟不了震动的,得真机测试哦): 程序效果:
Java代码
1. package com.ray.test;
2.
3. import android.app.Activity;
4. import android.os.Bundle;
5. import android.os.Vibrator;
6. import android.view.MotionEvent;
7.
8. public class TestViberation extends Activity {
9. Vibrator vibrator;
10. /** Called when the activity is first created. */
11. @Override
12. public void onCreate(Bundle savedInstanceState) {
13. super.onCreate(savedInstanceState);
14. setContentView(R.layout.main);
15. }
16.
17. @Override
18. protected void onStop() {
19. if(null!=vibrator){
20. vibrator.cancel();
21. }
22. super.onStop();
23. }
24.
25. @Override
26. public boolean onTouchEvent(MotionEvent event) {
27.
28. if(event.getAction() == MotionEvent.ACTION_DOWN){
29. vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
30. long[] pattern = {800, 50, 400, 30}; // OFF/ON/OFF/ON...
31. vibrator.vibrate(pattern, 2);//-1不重复,非-1为从pattern的指定下标开始重复
32. }
33. return super.onTouchEvent(event);
34. }
35.
36.
37. }
android animation
动画效果编程基础--AnimationAndroid 在Android中,分别可以在xml中定义Animation,也可以在程序代码中定义动画类型 Android的animation由四种类型组成 XML中 alpha 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面转移旋转动画效果
代码中 AlphaAnimation 渐变透明度动画效果 ScaleAnimation 渐变尺寸伸缩动画效果 TranslateAnimation 画面转换位置移动动画效果 RotateAnimation 画面转移旋转动画效果 Android动画模式 Animation主要有两种动画模式: 一种是tweened animation(渐变动画) alpha AlphaAnimation scale ScaleAnimation 一种是frame by frame(画面转换动画) translate TranslateAnimation rotate RotateAnimation 如何在XML文件中定义动画 ① 打开Eclipse,新建Android工程 ② 在res目录中新建anim文件夹 ③ 在anim目录中新建一个myanim.xml(注意文件名小写) ④ 加入XML的动画代码 <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <alpha/> <scale/> <translate/> <rotate/> </set> 每个元素表示不同的动画效果 Android动画解析--XML
<alpha> <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <alpha android:fromAlpha="0.1" android:toAlpha="1.0" android:duration="3000" /> <!-- 透明度控制动画效果 alpha 浮点型值: fromAlpha 属性为动画起始时透明度 toAlpha 属性为动画结束时透明度 说明: 0.0表示完全透明 1.0表示完全不透明 以上值取0.0-1.0之间的float数据类型的数字 长整型值: duration 属性为动画持续时间 说明: 时间以毫秒为单位 --> </set> <scale> <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <scale android:interpolator= "@android:anim/accelerate_decelerate_interpolator" android:fromXScale="0.0" android:toXScale="1.4" android:fromYScale="0.0" android:toYScale="1.4" android:pivotX="50%" android:pivotY="50%" android:fillAfter="false" android:startOffset=“700” android:duration="700" /> </set> <!-- 尺寸伸缩动画效果 scale
属性:interpolator 指定一个动画的插入器 在我试验过程中,使用android.res.anim中的资源时候发现 有三种动画插入器: accelerate_decelerate_interpolator 加速-减速 动画插入器 accelerate_interpolator 加速-动画插入器 decelerate_interpolator 减速- 动画插入器 其他的属于特定的动画效果 浮点型值: fromXScale 属性为动画起始时 X坐标上的伸缩尺寸 toXScale 属性为动画结束时 X坐标上的伸缩尺寸 fromYScale 属性为动画起始时Y坐标上的伸缩尺寸 toYScale 属性为动画结束时Y坐标上的伸缩尺寸 startOffset 属性为从上次动画停多少时间开始执行下个动画 说明: 以上四种属性值 0.0表示收缩到没有 1.0表示正常无伸缩 值小于1.0表示收缩 值大于1.0表示放大 pivotX 属性为动画相对于物件的X坐标的开始位置 pivotY 属性为动画相对于物件的Y坐标的开始位置 说明: 以上两个属性值 从0%-100%中取值 50%为物件的X或Y方向坐标上的中点位置 长整型值: duration 属性为动画持续时间 说明: 时间以毫秒为单位 布尔型值: fillAfter 属性 当设置为true ,该动画转化在动画结束后被应用 --> <translate> <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="30" android:toXDelta="-80" android:fromYDelta="30" android:toYDelta="300" android:duration="2000" /> <!-- translate 位置转移动画效果 整型值: fromXDelta 属性为动画起始时 X坐标上的位置 toXDelta 属性为动画结束时 X坐标上的位置 fromYDelta 属性为动画起始时 Y坐标上的位置 toYDelta 属性为动画结束时 Y坐标上的位置 注意: 没有指定fromXType toXType fromYType toYType 时候, 默认是以自己为相对参照物 长整型值: duration 属性为动画持续时间 说明: 时间以毫秒为单位 --> </set> <rotate> <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <rotate android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:fromDegrees="0" android:toDegrees="+350" android:pivotX="50%" android:pivotY="50%" android:duration="3000" /> <!-- rotate 旋转动画效果 属性:interpolator 指定一个动画的插入器 在我试验过程中,使用android.res.anim中的资源时候发现 有三种动画插入器: accelerate_decelerate_interpolator 加速-减速动画插入器 accelerate_interpolator 加速-动画插入器 decelerate_interpolator 减速- 动画插入器 其他的属于特定的动画效果
浮点数型值: fromDegrees 属性为动画起始时物件的角度 toDegrees 属性为动画结束时物件旋转的角度 可以大于360度 说明: 当角度为负数——表示逆时针旋转 当角度为正数——表示顺时针旋转 (负数from——to正数:顺时针旋转) (负数from——to负数:逆时针旋转) (正数from——to正数:顺时针旋转) (正数from——to负数:逆时针旋转) pivotX 属性为动画相对于物件的X坐标的开始位置 pivotY 属性为动画相对于物件的Y坐标的开始位置 说明: 以上两个属性值 从0%-100%中取值 50%为物件的X或Y方向坐标上的中点位置 长整型值: duration 属性为动画持续时间 说明: 时间以毫秒为单位 --> </set> 在编码中如何使用如何使用XML中的动画效果 在代码中使用这个方法得到Animation实例 public static Animation loadAnimation (Context context, int id) //第一个参数Context为程序的上下文 //第二个参数id为动画XML文件的引用 //例子: myAnimation= AnimationUtils.loadAnimation(this,R.anim.my_action); //使用AnimationUtils类的静态方法loadAnimation()来加载XML中的动画XML文件 如何在Java代码中定义动画 //在代码中定义 动画实例对象 private Animation myAnimation_Alpha; private Animation myAnimation_Scale; private Animation myAnimation_Translate;
private Animation myAnimation_Rotate; //根据各自的构造方法来初始化一个实例对象 myAnimation_Alpha=new AlphaAnimation(0.1f, 1.0f); myAnimation_Scale =new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); myAnimation_Translate=new TranslateAnimation(30.0f, -80.0f, 30.0f, 300.0f); myAnimation_Rotate=new RotateAnimation(0.0f, +350.0f, Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF, 0.5f); -------------------------------------------------------------------- Android动画解析 AlphaAnimation ① AlphaAnimation类对象定义 private AlphaAnimation myAnimation_Alpha; ② AlphaAnimation类对象构造 AlphaAnimation(float fromAlpha, float toAlpha) //第一个参数fromAlpha为 动画开始时候透明度 //第二个参数toAlpha为 动画结束时候透明度 myAnimation_Alpha=new AlphaAnimation(0.1f, 1.0f); //说明: // 0.0表示完全透明 // 1.0表示完全不透明 ③ 设置动画持续时间 myAnimation_Alpha.setDuration(5000); //设置时间持续时间为 5000毫秒 ScaleAnimation ①ScaleAnimation类对象定义 private AlphaAnimation myAnimation_Scale; ② ScaleAnimation类对象构造 ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) //第一个参数fromX为动画起始时 X坐标上的伸缩尺寸 //第二个参数toX为动画结束时 X坐标上的伸缩尺寸 //第三个参数fromY为动画起始时Y坐标上的伸缩尺寸 //第四个参数toY为动画结束时Y坐标上的伸缩尺寸
/*说明: 以上四种属性值 0.0表示收缩到没有 1.0表示正常无伸缩 值小于1.0表示收缩 值大于1.0表示放大 */ //第五个参数pivotXType为动画在X轴相对于物件位置类型 //第六个参数pivotXValue为动画相对于物件的X坐标的开始位置 //第七个参数pivotXType为动画在Y轴相对于物件位置类型 //第八个参数pivotYValue为动画相对于物件的Y坐标的开始位置 myAnimation_Scale =new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); ③ 设置动画持续时间 myAnimation_Scale.setDuration(700); //设置时间持续时间为 700毫秒 TranslateAnimation ① TranslateAnimation类对象定义 private AlphaAnimation myAnimation_Translate; ② TranslateAnimation类对象构造 TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta) //第一个参数fromXDelta为动画起始时 X坐标上的移动位置 //第二个参数toXDelta为动画结束时 X坐标上的移动位置 //第三个参数fromYDelta为动画起始时Y坐标上的移动位置 //第四个参数toYDelta为动画结束时Y坐标上的移动位置 ③ 设置动画持续时间 myAnimation_Translate.setDuration(2000); //设置时间持续时间为 2000毫秒 RotateAnimation ① RotateAnimation类对象定义 private AlphaAnimation myAnimation_Rotate; ② RotateAnimation类对象构造 RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) //第一个参数fromDegrees为动画起始时的旋转角度 //第二个参数toDegrees为动画旋转到的角度 //第三个参数pivotXType为动画在X轴相对于物件位置类型 //第四个参数pivotXValue为动画相对于物件的X坐标的开始位置 //第五个参数pivotXType为动画在Y轴相对于物件位置类型 //第六个参数pivotYValue为动画相对于物件的Y坐标的开始位置
myAnimation_Rotate=new RotateAnimation(0.0f, +350.0f, Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF, 0.5f) ③ 设置动画持续时间 myAnimation_Rotate.setDuration(3000); //设置时间持续时间为 3000毫秒 --------------------------------------------------------------------- 下面的小例子是利用RotateAnimation简单展示一下两种方法的用法,对于其他动画,如ScaleAnimation,AlphaAnimation,原理是一样的。 方法一:在xml中定义动画:
Xml代码
1. <?xml version="1.0" encoding="utf-8"?>
2. <set xmlns:android="http://schemas.android.com/apk/res/android">
3.
4. <rotate
5. android:interpolator="@android:anim/accelerate_decelerate_interpolator"
6. android:fromDegrees="0"
7. android:toDegrees="+360"
8. android:duration="3000" />
9.
10. <!-- rotate 旋转动画效果
11. 属性:interpolator 指定一个动画的插入器,用来控制动画的速度变化
12. fromDegrees 属性为动画起始时物件的角度
13. toDegrees 属性为动画结束时物件旋转的角度,正代表顺时针
14. duration 属性为动画持续时间,以毫秒为单位
15. -->
16. lt;/set>
使用动画的Java代码,程序的效果是点击按钮,TextView旋转一周:
Java代码
1. package com.ray.animation;
2.
3. import android.app.Activity;
4. import android.os.Bundle;
5. import android.view.View;
6. import android.view.View.OnClickListener;
7. import android.view.animation.Animation;
8. import android.view.animation.AnimationUtils;
9. import android.widget.Button;
10. import android.widget.TextView;
11.
12. public class TestAnimation extends Activity implements OnClickListener{
13. public void onCreate(Bundle savedInstanceState) {
14. super.onCreate(savedInstanceState);
15. setContentView(R.layout.main);
16. Button btn = (Button)findViewById(R.id.Button01);
17. btn.setOnClickListener(this);
18. }
19.
20. @Override
21. public void onClick(View v) {
22. Animation anim = AnimationUtils.loadAnimation(this, R.anim.my_rotate_action);
23. findViewById(R.id.TextView01).startAnimation(anim);
24. }
25. }
方法二:直接在代码中定义动画(效果跟方法一类似):
Java代码
1. package com.ray.animation;
2.
3. import android.app.Activity;
4. import android.os.Bundle;
5. import android.view.View;
6. import android.view.View.OnClickListener;
7. import android.view.animation.AccelerateDecelerateInterpolator;
8. import android.view.animation.Animation;
9. import android.view.animation.RotateAnimation;
10. import android.widget.Button;
11.
12. public class TestAnimation extends Activity implements OnClickListener{
13.
14. public void onCreate(Bundle savedInstanceState) {
15. super.onCreate(savedInstanceState);
16. setContentView(R.layout.main);
17. Button btn = (Button)findViewById(R.id.Button);
18. btn.setOnClickListener(this);
19. }
20.
21. public void onClick(View v) {
22. Animation anim = null;
23. anim = new RotateAnimation(0.0f,+360.0f);
24. anim.setInterpolator(new AccelerateDecelerateInterpolator());
25. anim.setDuration(3000);
26. findViewById(R.id.TextView01).startAnimation(anim);
27. }
28. }
29.一、Android中的通知
30. 一般手机上边都有一个状态条,显示电池电量、信号强度、未接来电、短信...。Android的屏幕上方也具有状态条。这里所说的通知,就是在这个状态条上显示通知。
31.
32. 发送通知的步骤如下:
33. 1).获取通知管理器
34. NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
35. 2).新建一个通知,指定其图标和标题
36. int icon = android.R.drawable.stat_notify_chat;
37. long when = System.currentTimeMillis();
38. //第一个参数为图标,第二个参数为标题,第三个为通知时间
39. Notification notification = new Notification(icon, null, when);
40. Intent openintent = new Intent(this, OtherActivity.class);
41. //当点击消息时就会向系统发送openintent意图
42. PendingIntent contentIntent = PendingIntent.getActivity(this, 0, openintent, 0);
43. notification.setLatestEventInfo(this, “标题”, “内容", contentIntent);
44. mNotificationManager.notify(0, notification);
45.
Android中的样式和主题
46. android中的样式和CSS样式作用相似,都是用于为界面元素定义显示风格,它是一个包含一个戒者多个view控件属性的集合。如:需要定义字体的颜色和大小。
47.
48. 1).在values目录下添加styles.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="changcheng">
<item name="android:textSize">18px</item>
<item name="android:textColor">#0000CC</item>
</style>
</resources>
49.
50. 2).在layout文件中可以通过style戒 theme属性设置样式戒主题。
三、使用HTML做为UI
51. 使用LayoutUI比较麻烦,丌能让美工参不进来,这样就为开发人员带来了麻烦。但我们可以通过HTML+JS来进行UI的设计不操作。
52.
53. 1).在assets添加Html页面
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>联系人列表</title>
<script type="text/javascript">
function show(jsondata){
var jsonobjs = eval(jsondata);
var table = document.getElementById("personTable");
for(var y=0; y<jsonobjs.length; y++){
var tr = table.insertRow(table.rows.length); //添加一行
//添加三列
var td1 = tr.insertCell(0);
var td2 = tr.insertCell(1);
td2.align = "center";
var td3 = tr.insertCell(2);
//设置列内容和属性
td1.innerHTML = jsonobjs[y].id;
td2.innerHTML = jsonobjs[y].name;
td3.innerHTML = "<a href='javascript:itcast.call(\""+ jsonobjs[y].phone +"\")'>"+ jsonobjs[y].phone+ "</a>";
}
}
</script>
</head>
<body>
<body bgcolor="#000000" text="#FFFFFF" style="margin:0 0 0 0" onload="javascript:itcast.getContacts()">
<table border="0" width="100%" id="personTable" cellspacing="0">
<tr>
<td width="15%">编号</td><td align="center">姓名</td><td width="15%">电话</td>
</tr>
</table>
</body>
</html>
54.
55. 2).在main.xlm中添加一个WebView控件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<WebView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/webView"
/>
</LinearLayout>
56.
57. 3).Activity类
package cn.itcast.html;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import cn.itcast.domain.Contact;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.webkit.WebView;
public class ContactActivity extends Activity {
private static final String TAG = "ContactActivity";
private WebView webView;
private Handler handler = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
webView = (WebView)this.findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);//设置支持javaScript
webView.getSettings().setSaveFormData(false);//丌保存表单数据
webView.getSettings().setSavePassword(false);//丌保存密码
webView.getSettings().setSupportZoom(false);//丌支持页面放大功能
//addJavascriptInterface方法中要绑定的Java对象及方法要运行在另外的线程中,丌能运行在构造他的线程中
webView.addJavascriptInterface(new MyJavaScript(), "itcast");
webView.loadUrl("file:///android_asset/index.html");
}
private final class MyJavaScript{
public void call(final String phone){
handler.post(new Runnable() {
@Override
public void run() {
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:"+ phone));
startActivity(intent);
}
});
}
/**
* 获取所有联系人
*/
public void getContacts(){
handler.post(new Runnable() {
@Override
public void run() {
//可以通过访问SQLLite数据库得到联系人
List<Contact> contacts = new ArrayList<Contact>();
contacts.add(new Contact(27, "路飞", "12345"));
contacts.add(new Contact(28, "索隆", "67890"));
String json = buildJson(contacts);
webView.loadUrl("javascript:show('"+ json +"')");
}
});
}
//生成Json格式的数据
private String buildJson(List<Contact> contacts){
try {
JSONArray array = new JSONArray();
for(Contact contact : contacts){
JSONObject item = new JSONObject();
item.put("id", contact.getId());
item.put("name", contact.getName());
item.put("phone", contact.getPhone());
array.put(item);
}
return array.toString();
} catch (Exception e) {
Log.e(TAG, e.toString());
}
return "";
}
}
}
58.
59. MyJavaScript接口实现的方法正是提供给页面中的JS代码调用的!
60. 2.将APK包放入到SDCard目录中
61. 在FileExplorer面板的右上角有一个导入手机图标,将上面生成的APK包导入到SDCard目录中。
Android 选项卡效果
首先创建Android工程命名自己的Activity为HelloTabWidget
在main.xml或者自己定义的*.xml文件中创建一个TabHost,需要两个元素TabWidget和FrameLayout 通常会把这两个元素放到LinearLayout中。FrameLayout作为改变内容content用的。 注意:TabWidget和FrameLayout 有不同的ID命名空间android:id="@android:id/idnames",这个是必须的因此TabHost才能自动找到它,Activity需要继承TabActivity。
Xml代码
1. <?xml version="1.0" encoding="utf-8"?>
2. <TabHost xmlns:android="http://schemas.android.com/apk/res/android"
3. android:id="@android:id/tabhost"
4. android:layout_width="fill_parent"
5. android:layout_height="fill_parent">
6. <LinearLayout
7. android:orientation="vertical"
8. android:layout_width="fill_parent"
9. android:layout_height="fill_parent">
10. <TabWidget
11. android:id="@android:id/tabs"
12. android:layout_width="fill_parent"
13. android:layout_height="wrap_content" />
14. <FrameLayout
15. android:id="@android:id/tabcontent"
16. android:layout_width="fill_parent"
17. android:layout_height="fill_parent">
18. <TextView
19. android:id="@+id/textview1"
20. android:layout_width="fill_parent"
21. android:layout_height="fill_parent"
22. android:text="this is a tab" />
23. <TextView
24. android:id="@+id/textview2"
25. android:layout_width="fill_parent"
26. android:layout_height="fill_parent"
27. android:text="this is another tab" />
28. <TextView
29. android:id="@+id/textview3"
30. android:layout_width="fill_parent"
31. android:layout_height="fill_parent"
32. android:text="this is a third tab" />
33. </FrameLayout>
34. </LinearLayout>
35. </TabHost>
Activity需要继承TabActivity
Java代码
1. public class HelloTabWidget extends TabActivity
Java代码
1. public void onCreate(Bundle savedInstanceState) {
2. super.onCreate(savedInstanceState);
3. setContentView(R.layout.main);
4. mTabHost = getTabHost();
5. mTabHost.addTab(mTabHost.newTabSpec("tab_test1").setIndicator("TAB 1")
6. . setContent(R.id.textview1));
7. mTabHost.addTab(mTabHost.newTabSpec("tab_test2").setIndicator("TAB 2").setContent(R.id.textview2));
8. mTabHost.addTab(mTabHost.newTabSpec("tab_test3").setIndicator("TAB 3").setContent(R.id.textview3));
9.
10. mTabHost.setCurrentTab(0);
11. }
Android BaseExpandableListAdapter 教程
文章分类:移动开发
先上图再说,实现效果如下图,选项可多少可变化。
BaseExpandableListAdapter实现
Java代码
1. import java.util.List;
2.
3. import android.content.Context;
4. import android.graphics.drawable.Drawable;
5. import android.view.LayoutInflater;
6. import android.view.View;
7. import android.view.ViewGroup;
8. import android.widget.BaseExpandableListAdapter;
9. import android.widget.CheckBox;
10. import android.widget.ImageView;
11. import android.widget.TextView;
12. import com.iwidsets.clear.manager.R;
13. import com.iwidsets.clear.manager.adapter.BrowserInfo;
14.
15. public class ClearExpandableListAdapter extends BaseExpandableListAdapter {
16.
17. class ExpandableListHolder {
18. ImageView appIcon;
19. TextView appInfo;
20. CheckBox appCheckBox;
21. }
22.
23. private Context context;
24. private LayoutInflater mChildInflater;
25. private LayoutInflater mGroupInflater;
26. private List<GroupInfo> group;
27.
28. public ClearExpandableListAdapter(Context c, List<GroupInfo> group) {
29. this.context = c;
30. mChildInflater = (LayoutInflater) context
31. .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
32. mGroupInflater = (LayoutInflater) context
33. .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
34. this.group = group;
35. }
36.
37. public Object getChild(int childPosition, int itemPosition) {
38. return group.get(childPosition).getChild(itemPosition);
39. }
40.
41. public long getChildId(int childPosition, int itemPosition) {
42.
43. return itemPosition;
44. }
45.
46. @Override
47. public int getChildrenCount(int index) {
48. return group.get(index).getChildSize();
49. }
50.
51. public Object getGroup(int index) {
52. return group.get(index);
53. }
54.
55. public int getGroupCount() {
56. return group.size();
57. }
58.
59. public long getGroupId(int index) {
60. return index;
61. }
62.
63. public View getGroupView(int position, boolean flag, View view,
64. ViewGroup parent) {
65. ExpandableListHolder holder = null;
66. if (view == null) {
67. view = mGroupInflater.inflate(
68. R.layout.browser_expandable_list_item, null);
69. holder = new ExpandableListHolder();
70. holder.appIcon = (ImageView) view.findViewById(R.id.app_icon);
71. view.setTag(holder);
72. holder.appInfo = (TextView) view.findViewById(R.id.app_info);
73. holder.appCheckBox = (CheckBox) view
74. .findViewById(R.id.app_checkbox);
75. } else {
76. holder = (ExpandableListHolder) view.getTag();
77. }
78. GroupInfo info = this.group.get(position);
79. if (info != null) {
80. holder.appInfo.setText(info.getBrowserInfo().getAppInfoId());
81. Drawable draw = this.context.getResources().getDrawable(
82. info.getBrowserInfo().getImageId());
83. holder.appIcon.setImageDrawable(draw);
84. holder.appCheckBox.setChecked(info.getBrowserInfo().isChecked());
85. }
86. return view;
87. }
88.
89. public boolean hasStableIds() {
90. return false;
91. }
92.
93. public boolean isChildSelectable(int arg0, int arg1) {
94. return false;
95. }
96.
97. @Override
98. public View getChildView(int groupPosition, int childPosition,
99. boolean isLastChild, View convertView, ViewGroup parent) {
100. ExpandableListHolder holder = null;
101. if (convertView == null) {
102. convertView = mChildInflater.inflate(
103. R.layout.browser_expandable_list_item, null);
104. holder = new ExpandableListHolder();
105. holder.appIcon = (ImageView) convertView
106. .findViewById(R.id.app_icon);
107. convertView.setTag(holder);
108. holder.appInfo = (TextView) convertView.findViewById(R.id.app_info);
109. holder.appCheckBox = (CheckBox) convertView
110. .findViewById(R.id.app_checkbox);
111. } else {
112. holder = (ExpandableListHolder) convertView.getTag();
113. }
114. BrowserInfo info = this.group.get(groupPosition)
115. .getChild(childPosition);
116. if (info != null) {
117. holder.appInfo.setText(info.getAppInfoId());
118. Drawable draw = this.context.getResources().getDrawable(
119. info.getImageId());
120. holder.appIcon.setImageDrawable(draw);
121. holder.appCheckBox.setChecked(info.isChecked());
122. }
123. return convertView;
124. }
125.
126. }
要想让child获得焦点,只在改
Java代码
1. public boolean isChildSelectable(int arg0, int arg1) {
2. return true;
3. }
browser_expandable_list_item.xml 用于显示每一个ITEM的XML
Xml代码
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. android:layout_width="fill_parent" android:layout_height="wrap_content"
4. android:orientation="horizontal" android:minHeight="40px"
5. android:layout_gravity="center_vertical">
6. <CheckBox android:id="@+id/app_checkbox" android:focusable="false"
7. android:layout_width="wrap_content" android:layout_height="wrap_content"
8. android:layout_marginLeft="35px" android:checked="true"/>
9. <ImageView android:id="@+id/app_icon" android:layout_width="wrap_content"
10. android:layout_height="wrap_content" android:layout_gravity="center_vertical" />
11.
12. <TextView android:id="@+id/app_info" android:layout_width="wrap_content"
13. android:layout_height="wrap_content" android:textColor="?android:attr/textColorPrimary"
14. android:paddingLeft="3px" android:layout_gravity="center_vertical" />
15. </LinearLayout>
browserlayout.xml 用于显示整个界面
Xml代码
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. android:layout_width="fill_parent" android:layout_height="fill_parent"
4. android:orientation="vertical">
5. <ExpandableListView android:id="@+id/appList"
6. android:layout_width="fill_parent" android:layout_height="0dip"
7. android:layout_weight="1" />
8. <LinearLayout android:layout_height="wrap_content"
9. android:layout_width="fill_parent" android:paddingLeft="4dip"
10. android:paddingRight="4dip" android:paddingBottom="1dip"
11. android:paddingTop="5dip" android:background="@android:drawable/bottom_bar"
12. android:id="@+id/app_footer">
13. <Button android:layout_weight="1" android:id="@+id/btn_export"
14. android:layout_width="0dip" android:layout_height="fill_parent"
15. android:text="@string/clear"></Button>
16. <Button android:layout_weight="1" android:id="@+id/btn_sel_all"
17. android:layout_width="0dip" android:layout_height="fill_parent"
18. android:text="select_all"></Button>
19. <Button android:layout_weight="1" android:id="@+id/btn_desel_all"
20. android:layout_width="0dip" android:layout_height="fill_parent"
21. android:text="deselect_all"></Button>
22. </LinearLayout>
23.
24. </LinearLayout>
BrowserInfo用于提供一个项的信息
Java代码
1. public class BrowserInfo {
2.
3. private int appInfoId;
4. private int imageId;
5. private boolean checked;
6.
7. public BrowserInfo(int appInfoId, int imageId, boolean checked) {
8. this.appInfoId = appInfoId;
9. this.imageId = imageId;
10. this.checked = checked;
11. }
12.
13. public boolean isChecked() {
14. return checked;
15. }
16.
17. public void setChecked(boolean checked) {
18. this.checked = checked;
19. }
20.
21. public int getAppInfoId() {
22. return appInfoId;
23. }
24.
25. public void setAppInfoId(int appInfoId) {
26. this.appInfoId = appInfoId;
27. }
28.
29. public int getImageId() {
30. return imageId;
31. }
32.
33. public void setImageId(int imageId) {
34. this.imageId = imageId;
35. }
36.
37. }
GroupInfo 用于显示一个组的信息
Java代码
1. import java.util.List;
2.
3. public class GroupInfo {
4.
5. private BrowserInfo group;
6. private List<BrowserInfo> child;
7.
8. public GroupInfo(BrowserInfo group, List<BrowserInfo> child) {
9.
10. this.group = group;
11. this.child = child;
12. }
13.
14. public void add(BrowserInfo info){
15. child.add(info);
16. }
17.
18. public void remove(BrowserInfo info){
19. child.remove(info);
20. }
21.
22. public void remove(int index){
23. child.remove(index);
24. }
25.
26. public int getChildSize(){
27. return child.size();
28. }
29.
30. public BrowserInfo getChild(int index){
31. return child.get(index);
32. }
33.
34. public BrowserInfo getBrowserInfo() {
35. return group;
36. }
37.
38. public void setBrowserInfo(BrowserInfo group) {
39. this.group = group;
40. }
41.
42. public List<BrowserInfo> getChild() {
43. return child;
44. }
45.
46. public void setChild(List<BrowserInfo> child) {
47. this.child = child;
48. }
49.
50. }
ClearBrowserActivity 最后就是把要显示的内容显示出来的。
Java代码
1. public class ClearBrowserActivity extends Activity implements ExpandableListView.OnGroupClickListener,ExpandableListView.OnChildClickListener{
2.
3. private List<GroupInfo> group;
4.
5. private ClearExpandableListAdapter listAdapter = null;
6. private ExpandableListView appList;
7.
8. public void onCreate(Bundle savedInstanceState) {
9. super.onCreate(savedInstanceState);
10. setContentView(R.layout.browserlayout);
11. appList = (ExpandableListView) findViewById(R.id.appList);
12. init();
13. BrowserInfo browsingHistoryParents = newBrowserInfo(
14. R.string.browsinghistory, R.drawable.browser_image,true);
15. List<BrowserInfo> browsingHistoryChild = new ArrayList<BrowserInfo>();
16. BrowserInfo browser = newBrowserInfo(R.string.browser,
17. R.drawable.browser_image, true);
18. browsingHistoryChild.add(browser);
19.
20. BrowserInfo operaClear = newBrowserInfo(R.string.opera_clear,
21. R.drawable.browser_image,true);
22. browsingHistoryChild.add(operaClear);
23.
24. BrowserInfo firefoxClear = newBrowserInfo(R.string.firefox_clear,
25. R.drawable.browser_image,true);
26. browsingHistoryChild.add(firefoxClear);
27.
28. BrowserInfo ucwebClear = newBrowserInfo(R.string.ucweb_clear,
29. R.drawable.browser_image,false);
30. browsingHistoryChild.add(ucwebClear);
31.
32. GroupInfo browserGroup = new GroupInfo(browsingHistoryParents,
33. browsingHistoryChild);
34. addGroup(browserGroup);
35.
36. listAdapter = new ClearExpandableListAdapter(this, group);
37. appList.setOnChildClickListener(this);
38. appList.setOnGroupClickListener(this);
39. appList.setAdapter(listAdapter);
40. }
41.
42. private void init() {
43. group = new ArrayList<GroupInfo>();
44. }
45.
46. private void addGroup(GroupInfo info) {
47. group.add(info);
48. }
49.
50. private static BrowserInfo newBrowserInfo(int infoId, int imageId,boolean checked) {
51. return new BrowserInfo(infoId, imageId,checked);
52. }
53.
54. @Override
55. public boolean onGroupClick(ExpandableListView parent, View v,
56. int groupPosition, long id) {
57. return false;
58. }
59.
60. @Override
61. public boolean onChildClick(ExpandableListView parent, View v,
62. int groupPosition, int childPosition, long id) {
63. return false;
64. }
65. }
android 3d 旋转
文章分类:Java编程
在javaeye里看到了关于3d旋转的文章,可是博主没有透入什么技术细节。由于一直想做出那种旋转效果,所以就想啊想,终于想出来了(我是个小菜鸟)。呵呵,不管怎样,希望对想做还没做出来的朋友一些帮助。
先上一个效果图:
这是你想要的吗?如果是就继续往下看吧。
其实,这个效果是用animation配合camera做出来的,相信大家在apidemo里面看过类似的。
那么先写一个继承animation的类:Rotate3d
Rotate3d代码
1. public class Rotate3d extends Animation {
2. private float mFromDegree;
3. private float mToDegree;
4. private float mCenterX;
5. private float mCenterY;
6. private float mLeft;
7. private float mTop;
8. private Camera mCamera;
9. private static final String TAG = "Rotate3d";
10.
11. public Rotate3d(float fromDegree, float toDegree, float left, float top,
12. float centerX, float centerY) {
13. this.mFromDegree = fromDegree;
14. this.mToDegree = toDegree;
15. this.mLeft = left;
16. this.mTop = top;
17. this.mCenterX = centerX;
18. this.mCenterY = centerY;
19.
20. }
21.
22. @Override
23. public void initialize(int width, int height, int parentWidth,
24. int parentHeight) {
25. super.initialize(width, height, parentWidth, parentHeight);
26. mCamera = new Camera();
27. }
28.
29. @Override
30. protected void applyTransformation(float interpolatedTime, Transformation t) {
31. final float FromDegree = mFromDegree;
32. float degrees = FromDegree + (mToDegree - mFromDegree)
33. * interpolatedTime;
34. final float centerX = mCenterX;
35. final float centerY = mCenterY;
36. final Matrix matrix = t.getMatrix();
37.
38. if (degrees <= -76.0f) {
39. degrees = -90.0f;
40. mCamera.save();
41. mCamera.rotateY(degrees);
42. mCamera.getMatrix(matrix);
43. mCamera.restore();
44. } else if(degrees >=76.0f){
45. degrees = 90.0f;
46. mCamera.save();
47. mCamera.rotateY(degrees);
48. mCamera.getMatrix(matrix);
49. mCamera.restore();
50. }else{
51. mCamera.save();
52. //这里很重要哦。
53. mCamera.translate(0, 0, centerX);
54. mCamera.rotateY(degrees);
55. mCamera.translate(0, 0, -centerX);
56. mCamera.getMatrix(matrix);
57. mCamera.restore();
58. }
59.
60. matrix.preTranslate(-centerX, -centerY);
61. matrix.postTranslate(centerX, centerY);
62. }
63. }
有了这个类一切都会变得简单的,接着只要在activity中写两个Rotate3d的对象,让两个view,分别做这两个对象的animation就好了。(原来就这么简单啊!无语)
Activity代码
1. //下面两句很关键哦,呵呵,心照不宣。
2. Rotate3d leftAnimation = new Rotate3d(-0, -90, 0, 0, mCenterX, mCenterY);
3. Rotate3d rightAnimation = new Rotate3d(-0+90, -90+90, 0.0f, 0.0f, mCenterX, mCenterY);
4.
5. leftAnimation.setFillAfter(true);
6. leftAnimation.setDuration(1000);
7. rightAnimation.setFillAfter(true);
8. rightAnimation.setDuration(1000);
9.
10. mImageView1.startAnimation(leftAnimation);
11. mImageView2.startAnimation(rightAnimation);
还要写一下mImageView1,mImageView2的xml,
Xml代码
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. android:orientation="vertical"
4. android:layout_width="fill_parent"
5. android:layout_height="wrap_content"
6. >
7.
8. <FrameLayout
9. android:layout_width="fill_parent"
10. android:layout_height="fill_parent">
11.
12. <ImageView
13. android:id="@+id/image1"
14. android:layout_gravity="center_horizontal"
15. android:layout_width="fill_parent"
16. android:layout_height="wrap_content"
17. android:src="@drawable/image1"
18. />
19. <ImageView
20. android:id="@+id/image2"
21. android:background="#ffff0000"
22. android:layout_gravity="center_horizontal"
23. android:layout_width="fill_parent"
24. android:layout_height="wrap_content"
25. android:src="@drawable/image2"
26. />
27.
28. </FrameLayout>
29. </LinearLayout>
写完收工。如果有不足之处,还请朋友们不吝指教。
Android File Explorer 展示图片
文章分类:移动开发
res/layout/row.xml
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rowtext" android:layout_width="fill_parent" android:layout_height="25px" android:textSize="23sp" />
/res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/path"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@android:id/empty"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="No Data"
/>
</LinearLayout>
/res/layout/jpgdialog.xml
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_root"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="10dip"
android:paddingRight="10dip"
>
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="11sp" />
/>
<ImageView android:id="@+id/image"
android:layout_width="150px"
android:layout_height="150px"
/>
<Button android:id="@+id/okdialogbutton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="OK"
/>
</LinearLayout>
import java.io.File; import java.io.IOException; import java.util.ArrayList;
import java.util.List; import android.app.AlertDialog; import android.app.Dialog; import android.app.ListActivity; import android.content.Context; import android.content.DialogInterface; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.ExifInterface; import android.os.Bundle; import android.view.View; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; public class AndroidExplorer extends ListActivity { static final int ID_JPGDIALOG = 0; String filename; String exifAttribute; TextView exifText; ImageView bmImage; BitmapFactory.Options bmOptions; File jpgFile; Dialog jpgDialog; private List<String> item = null; private List<String> path = null; private String root="/"; private TextView myPath; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); myPath = (TextView)findViewById(R.id.path); getDir(root); } private void getDir(String dirPath)
{ myPath.setText("Location: " + dirPath); item = new ArrayList<String>(); path = new ArrayList<String>(); File f = new File(dirPath); File[] files = f.listFiles(); if(!dirPath.equals(root)) { item.add(root); path.add(root); item.add("../"); path.add(f.getParent()); } for(int i=0; i < files.length; i++) { File file = files[i]; path.add(file.getPath()); if(file.isDirectory()) item.add(file.getName() + "/"); else item.add(file.getName()); } ArrayAdapter<String> fileList = new ArrayAdapter<String>(this, R.layout.row, item); setListAdapter(fileList); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { File file = new File(path.get(position)); if (file.isDirectory()) { if(file.canRead())
getDir(path.get(position)); else { new AlertDialog.Builder(this) .setIcon(R.drawable.icon) .setTitle("[" + file.getName() + "] folder can't be read!") .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub } }).show(); } } else { exifAttribute = null; filename = file.getName(); String ext = filename.substring(filename.lastIndexOf('.')+1, filename.length()); if(ext.equals("JPG")||ext.equals("jpg")) { try { ExifInterface exif = new ExifInterface(file.toString()); exifAttribute = getExif(exif); } catch (IOException e) { // TODO Auto-generated catch block ; } jpgFile = file; showDialog(ID_JPGDIALOG); } else{ new AlertDialog.Builder(this) .setIcon(R.drawable.icon) .setTitle("[" + filename + "]") .setMessage(exifAttribute) .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override
public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub } }).show(); } } } private String getExif(ExifInterface exif) { String myAttribute=null; myAttribute += getTagString(ExifInterface.TAG_DATETIME, exif); myAttribute += getTagString(ExifInterface.TAG_FLASH, exif); myAttribute += getTagString(ExifInterface.TAG_GPS_LATITUDE, exif); myAttribute += getTagString(ExifInterface.TAG_GPS_LATITUDE_REF, exif); myAttribute += getTagString(ExifInterface.TAG_GPS_LONGITUDE, exif); myAttribute += getTagString(ExifInterface.TAG_GPS_LONGITUDE_REF, exif); myAttribute += getTagString(ExifInterface.TAG_IMAGE_LENGTH, exif); myAttribute += getTagString(ExifInterface.TAG_IMAGE_WIDTH, exif); myAttribute += getTagString(ExifInterface.TAG_MAKE, exif); myAttribute += getTagString(ExifInterface.TAG_MODEL, exif); myAttribute += getTagString(ExifInterface.TAG_ORIENTATION, exif); myAttribute += getTagString(ExifInterface.TAG_WHITE_BALANCE, exif); return myAttribute; } private String getTagString(String tag, ExifInterface exif) { return(tag + " : " + exif.getAttribute(tag) + "\n"); } @Override protected Dialog onCreateDialog(int id) { jpgDialog = null;; switch(id){
case ID_JPGDIALOG: Context mContext = this; jpgDialog = new Dialog(mContext); jpgDialog.setContentView(R.layout.jpgdialog); exifText = (TextView) jpgDialog.findViewById(R.id.text); bmImage = (ImageView)jpgDialog.findViewById(R.id.image); bmOptions = new BitmapFactory.Options(); bmOptions.inSampleSize = 2; Button okDialogButton = (Button)jpgDialog.findViewById(R.id.okdialogbutton); okDialogButton.setOnClickListener(okDialogButtonOnClickListener); break; default: break; } return jpgDialog; } @Override protected void onPrepareDialog(int id, Dialog dialog) { // TODO Auto-generated method stub switch(id){ case ID_JPGDIALOG: dialog.setTitle("[" + filename + "]"); exifText.setText(exifAttribute); Bitmap bm = BitmapFactory.decodeFile(jpgFile.getPath(), bmOptions); bmImage.setImageBitmap(bm); break; default: break; } } private Button.OnClickListener okDialogButtonOnClickListener = new Button.OnClickListener(){ @Override public void onClick(View v) {
// TODO Auto-generated method stub jpgDialog.dismiss(); } }; }
android ShapeDrawable实例
文章分类:移动开发
今天看了一下api中的画图,遇到了一个新的类,Shader类介绍,android中提供了Shader类专门来渲染图像已经一些几何图形,shader 下面包括几个直接子类,分别是BitmapShaper,ComposeShader,LinerGradient,RadialGradient,SweepGradient.BitmapShader主要用来渲染图像,Shader类的使用,先构造Shdaer对象,然后通过Paint的setShader方法来设置渲染对象,然后再绘制使用这个Paint对象既可。
Java代码
1. import android.app.Activity;
2. import android.content.Context;
3. import android.graphics.Bitmap;
4. import android.graphics.BitmapShader;
5. import android.graphics.Canvas;
6. import android.graphics.ComposePathEffect;
7. import android.graphics.CornerPathEffect;
8. import android.graphics.DiscretePathEffect;
9. import android.graphics.LinearGradient;
10. import android.graphics.Paint;
11. import android.graphics.Path;
12. import android.graphics.PathEffect;
13. import android.graphics.RectF;
14. import android.graphics.Shader;
15. import android.graphics.SweepGradient;
16. import android.graphics.drawable.Drawable;
17. import android.graphics.drawable.ShapeDrawable;
18. import android.graphics.drawable.shapes.ArcShape;
19. import android.graphics.drawable.shapes.OvalShape;
20. import android.graphics.drawable.shapes.PathShape;
21. import android.graphics.drawable.shapes.RectShape;
22. import android.graphics.drawable.shapes.RoundRectShape;
23. import android.graphics.drawable.shapes.Shape;
24. import android.os.Bundle;
25. import android.view.View;
26.
27. public class ShapeDrawble1 extends Activity {
28. /** Called when the activity is first created. */
29.
30.
31. @Override
32. protected void onCreate(Bundle savedInstanceState) {
33. super.onCreate(savedInstanceState);
34. setContentView(new SampleView(this));
35. }
36.
37. private static class SampleView extends View {
38. private ShapeDrawable[] mDrawables;
39.
40. private static Shader makeSweep() {
41. /* SweepGradient 是继承于Shader的,它是以中心点(150,25)
42. * 按照下列四种颜色进行变化的*/
43. return new SweepGradient(0, 0,
44. new int[] { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFF0000 },
45. null);// null 表示均衡变化
46. }
47.
48. private static Shader makeLinear() {
49. //颜色按照直线线性变化的着色器
50. return new LinearGradient(100, 100, 0, 0,
51. new int[] { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF },
52. null, Shader.TileMode.MIRROR);
53. }
54.
55. private static Shader makeTiling() {
56. int[] pixels = new int[] { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0};
57. Bitmap bm = Bitmap.createBitmap(pixels, 1, 1,
58. Bitmap.Config.ARGB_8888);
59. /**
60. * BitmapShader 是一个位图着色器,这个着色器是通过
61. * 在x,y方向重复位图bm的像素来着色的
62. *
63. */
64. return new BitmapShader(bm, Shader.TileMode.REPEAT,
65. Shader.TileMode.REPEAT);
66. }
67. /**
68. * ShapeDrawable 是绘制各种几何体的类。它注入想要绘制的形状shap
69. * 类,就可以绘制出我们想要的集合体,这个类最寒心的就是draw(canvas)
70. * 和onDraw(Shape,Canvas,Paint)这个方法调用
71. *
72. */
73. private static class MyShapeDrawable extends ShapeDrawable {
74. //Paint.ANTI_ALIAS_FLAG代表这个画笔的图形是光滑的
75. private Paint mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
76.
77. public MyShapeDrawable(Shape s) {
78. super(s);
79. mStrokePaint.setStyle(Paint.Style.STROKE);
80. }
81.
82. public Paint getStrokePaint() {
83. return mStrokePaint;
84. }
85.
86. @Override protected void onDraw(Shape s, Canvas c, Paint p) {
87. //绘制填充效果的图形
88. s.draw(c, p);
89. //绘制黑边
90. s.draw(c, mStrokePaint);
91. }
92. }
93.
94. public SampleView(Context context) {
95. super(context);
96. setFocusable(true);
97. //外部圆角矩形的圆角圆半径,上面俩个角是圆
98. float[] outerR = new float[] { 12, 12, 12, 12, 0, 0, 0, 0 };
99. //内部矩形
100. RectF inset = new RectF(6, 6, 6, 6);
101. //内部圆角矩形的圆角是圆半径,左上角和右下角是圆角矩形
102. float[] innerR = new float[] { 12, 12, 0, 0, 12, 12, 0, 0 };
103. //绘制一个顶点为下列四个点的棱形
104. Path path = new Path();
105. path.moveTo(50, 0);
106. path.lineTo(0, 50);
107. path.lineTo(50, 100);
108. path.lineTo(100, 50);
109. //封闭前面点所绘制的路径
110. path.close();
111.
112. mDrawables = new ShapeDrawable[7];
113. //绘制矩形
114. mDrawables[0] = new ShapeDrawable(new RectShape());
115. //绘制椭圆
116. mDrawables[1] = new ShapeDrawable(new OvalShape());
117. //绘制上面俩个角是圆角的矩形
118. mDrawables[2] = new ShapeDrawable(new RoundRectShape(outerR, null,
119. null));
120. //绘制上面俩角是圆角,并且有一个内嵌的矩形
121. mDrawables[3] = new ShapeDrawable(new RoundRectShape(outerR, inset,
122. null));
123. ////绘制上面俩角是圆角,并且有一个内嵌的矩形且左上角和右下角是圆形矩形环
124. mDrawables[4] = new ShapeDrawable(new RoundRectShape(outerR, inset,
125. innerR));
126. //绘制指定路径的集合体
127. mDrawables[5] = new ShapeDrawable(new PathShape(path, 100, 100));
128. // 用自定的ShapDrawble绘制开始弧度45扫过弧度-270的椭圆
129. mDrawables[6] = new MyShapeDrawable(new ArcShape(45, -270));
130.
131. mDrawables[0].getPaint().setColor(0xFFFF0000);
132. mDrawables[1].getPaint().setColor(0xFF00FF00);
133. mDrawables[2].getPaint().setColor(0xFF0000FF);
134. mDrawables[3].getPaint().setShader(makeSweep());
135. mDrawables[4].getPaint().setShader(makeLinear());
136. mDrawables[5].getPaint().setShader(makeTiling());
137. mDrawables[6].getPaint().setColor(0x88FF8844);
138. //DiscretePathEffect是一个折线路径效果,分割长度是10,偏差时4
139. PathEffect pe = new DiscretePathEffect(10, 4);
140. //CornerPathEffect是将2个路径效果合并后的路径效果
141. PathEffect pe2 = new CornerPathEffect(4);
142. mDrawables[3].getPaint().setPathEffect(
143. new ComposePathEffect(pe2, pe));
144.
145. MyShapeDrawable msd = (MyShapeDrawable)mDrawables[6];
146. //设置笔画宽度等于4
147. msd.getStrokePaint().setStrokeWidth(4);
148. }
149.
150. @Override protected void onDraw(Canvas canvas) {
151.
152. int x = 10;
153. int y = 10;
154. int width = 300;
155. int height = 50;
156. //循环绘制
157. for (Drawable dr : mDrawables) {
158. dr.setBounds(x, y, x + width, y + height);
159. dr.draw(canvas);
160. y += height + 5;
161. }
162. }
163. }
164. }
Eclipse 开发 Android, TableLayout(学习4)
Hello, TableLayout
A TableLayout is a ViewGroup that will lay child View elements into rows and columns.
1. Start a new project/Activity called HelloTableLayout.
2. Open the layout file. Make it like so:
3. <?xml version="1.0" encoding="utf-8"?>
4. <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
5. android:layout_width="fill_parent"
6. android:layout_height="fill_parent"
7. android:stretchColumns="1">
8.
9. <TableRow>
10. <TextView
11. android:layout_column="1"
12. android:text="Open..."
13. android:padding="3dip" />
14. <TextView
15. android:text="Ctrl-O"
16. android:gravity="right"
17. android:padding="3dip" />
18. </TableRow>
19.
20. <TableRow>
21. <TextView
22. android:layout_column="1"
23. android:text="Save..."
24. android:padding="3dip" />
25. <TextView
26. android:text="Ctrl-S"
27. android:gravity="right"
28. android:padding="3dip" />
29. </TableRow>
30.
31. <TableRow>
32. <TextView
33. android:layout_column="1"
34. android:text="Save As..."
35. android:padding="3dip" />
36. <TextView
37. android:text="Ctrl-Shift-S"
38. android:gravity="right"
39. android:padding="3dip" />
40. </TableRow>
41.
42. <View
43. android:layout_height="2dip"
44. android:background="#FF909090" />
45.
46. <TableRow>
47. <TextView
48. android:text="X"
49. android:padding="3dip" />
50. <TextView
51. android:text="Import..."
52. android:padding="3dip" />
53. </TableRow>
54.
55. <TableRow>
56. <TextView
57. android:text="X"
58. android:padding="3dip" />
59. <TextView
60. android:text="Export..."
61. android:padding="3dip" />
62. <TextView
63. android:text="Ctrl-E"
64. android:gravity="right"
65. android:padding="3dip" />
66. </TableRow>
67.
68. <View
69. android:layout_height="2dip"
70. android:background="#FF909090" />
71.
72. <TableRow>
73. <TextView
74. android:layout_column="1"
75. android:text="Quit"
76. android:padding="3dip" />
77. </TableRow>
78.</TableLayout>
Notice how this resembles the structure of an HTML table. TableLayout is like the table element; TableRow is like a tr element; but for our cells like the html td element, we can use any kind of View. Here, we use TextView for the cells.
79. Make sure your Activity loads this layout in the onCreate() method:
80.public void onCreate(Bundle savedInstanceState) {
81. super.onCreate(savedInstanceState);
82. setContentView(R.layout.main);
83.}
R.layout.main refers to the main.xml layout file.
84. Run it.
You should see the following:
备注:TableLayout 与html中表格类似。
系出名门Android(8)
文章分类:移动开发
系出名门Android(8) - 控件(View)之TextSwitcher, Gallery, ImageSwitcher, GridView, ListView, ExpandableList
介绍 在 Android 中使用各种控件(View) TextSwitcher - 文字转换器控件(改变文字时增加一些动画效果) Gallery - 缩略图浏览器控件 ImageSwitcher - 图片转换器控件(改变图片时增加一些动画效果) GridView - 网格控件 ListView - 列表控件 ExpandableList - 支持展开/收缩功能的列表控件
Java代码
1. 1、TextSwitcher 的 Demo
2. textswitcher.xml
3.
4. 代码
5. <?xml version="1.0" encoding="utf-8"?>
6. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
7. android:orientation="vertical" android:layout_width="fill_parent"
8. android:layout_height="fill_parent">
9.
10. <Button android:id="@+id/btnChange" android:layout_width="wrap_content"
11. android:layout_height="wrap_content" android:text="改变文字" />
12.
13. <!--
14. TextSwitcher - 文字转换器控件(改变文字时增加一些动画效果)
15. -->
16. <TextSwitcher android:id="@+id/textSwitcher"
17. android:layout_width="fill_parent" android:layout_height="wrap_content" />
18.
19. </LinearLayout>
20.
21.
22. _TextSwitcher.java
23.
24. 代码
25. package com.webabcd.view;
26.
27. import java.util.Random;
28.
29. import android.app.Activity;
30. import android.os.Bundle;
31. import android.view.View;
32. import android.view.animation.Animation;
33. import android.view.animation.AnimationUtils;
34. import android.widget.Button;
35. import android.widget.TextSwitcher;
36. import android.widget.TextView;
37. import android.widget.ViewSwitcher;
38.
39. public class _TextSwitcher extends Activity implements ViewSwitcher.ViewFactory {
40.
41. @Override
42. protected void onCreate(Bundle savedInstanceState) {
43. // TODO Auto-generated method stub
44. super.onCreate(savedInstanceState);
45. this.setContentView(R.layout.textswithcer);
46.
47. setTitle("TextSwithcer");
48.
49. final TextSwitcher switcher = (TextSwitcher) findViewById(R.id.textSwitcher);
50. // 指定转换器的 ViewSwitcher.ViewFactory
51. switcher.setFactory(this);
52.
53. // 设置淡入和淡出的动画效果
54. Animation in = AnimationUtils.loadAnimation(this, android.R.anim.fade_in);
55. Animation out = AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
56. switcher.setInAnimation(in);
57. switcher.setOutAnimation(out);
58.
59. // 单击一次按钮改变一次文字
60. Button btnChange = (Button) this.findViewById(R.id.btnChange);
61. btnChange.setOnClickListener(new View.OnClickListener() {
62. @Override
63. public void onClick(View v) {
64. switcher.setText(String.valueOf(new Random().nextInt()));
65. }
66. });
67. }
68.
69. // 重写 ViewSwitcher.ViewFactory 的 makeView(),返回一个 View
70. @Override
71. public View makeView() {
72. TextView textView = new TextView(this);
73. textView.setTextSize(36);
74. return textView;
75. }
76. }
77.
78.
79.
80. 2、Gallery 的 Demo
81. gallery.xml
82.
83. 代码
84. <?xml version="1.0" encoding="utf-8"?>
85. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
86. android:orientation="vertical" android:layout_width="fill_parent"
87. android:layout_height="fill_parent">
88.
89. <!--
90. Gallery - 缩略图浏览器控件
91. spacing - 缩略图列表中各个缩略图之间的间距
92. -->
93. <Gallery android:id="@+id/gallery" android:layout_width="fill_parent"
94. android:layout_height="wrap_content" android:spacing="20px" />
95.
96. </LinearLayout>
97.
98.
99. _Gallery.java
100.
101. 代码
102. package com.webabcd.view;
103.
104. import android.app.Activity;
105. import android.content.Context;
106. import android.os.Bundle;
107. import android.view.View;
108. import android.view.ViewGroup;
109. import android.widget.AdapterView;
110. import android.widget.BaseAdapter;
111. import android.widget.Gallery;
112. import android.widget.ImageView;
113. import android.widget.Toast;
114. import android.widget.Gallery.LayoutParams;
115.
116. public class _Gallery extends Activity {
117.
118. @Override
119. protected void onCreate(Bundle savedInstanceState) {
120. // TODO Auto-generated method stub
121. super.onCreate(savedInstanceState);
122. this.setContentView(R.layout.gallery);
123.
124. setTitle("Gallery");
125.
126. Gallery gallery = (Gallery) findViewById(R.id.gallery);
127. // 为缩略图浏览器指定一个适配器
128. gallery.setAdapter(new ImageAdapter(this));
129. // 响应 在缩略图列表上选中某个缩略图后的 事件
130. gallery.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
131. @Override
132. public void onItemSelected(AdapterView<?> parent, View v,
133. int position, long id) {
134. Toast.makeText(_Gallery.this, String.valueOf(position), Toast.LENGTH_SHORT).show();
135. }
136.
137. @Override
138. public void onNothingSelected(AdapterView<?> arg0) {
139.
140. }
141. });
142. }
143.
144. // 继承 BaseAdapter 用以实现自定义的图片适配器
145. public class ImageAdapter extends BaseAdapter {
146.
147. private Context mContext;
148.
149. public ImageAdapter(Context context) {
150. mContext = context;
151. }
152.
153. public int getCount() {
154. return mThumbIds.length;
155. }
156.
157. public Object getItem(int position) {
158. return position;
159. }
160.
161. public long getItemId(int position) {
162. return position;
163. }
164.
165. public View getView(int position, View convertView, ViewGroup parent) {
166. ImageView image = new ImageView(mContext);
167.
168. image.setImageResource(mThumbIds[position]);
169. image.setAdjustViewBounds(true);
170. image.setLayoutParams(new Gallery.LayoutParams(
171. LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
172.
173. return image;
174. }
175. }
176.
177. // 需要显示的图片集合
178. private Integer[] mThumbIds = { R.drawable.icon01, R.drawable.icon02,
179. R.drawable.icon03, R.drawable.icon04, R.drawable.icon05 };
180. }
181.
182.
183.
184. 3、ImageSwitcher 的 Demo
185. imageswitcher.xml
186.
187. 代码
188. <?xml version="1.0" encoding="utf-8"?>
189. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
190. android:orientation="vertical" android:layout_width="fill_parent"
191. android:layout_height="fill_parent">
192.
193. <Gallery android:id="@+id/gallery" android:layout_width="fill_parent"
194. android:layout_height="wrap_content" android:spacing="20px" />
195.
196. <!--
197. ImageSwitcher - 图片转换器控件(改变图片时增加一些动画效果)
198. -->
199. <ImageSwitcher android:id="@+id/imageSwitcher"
200. android:layout_width="fill_parent" android:layout_height="wrap_content" />
201.
202. </LinearLayout>
203.
204.
205. _ImageSwitcher.java
206.
207. 代码
208. package com.webabcd.view;
209.
210. import android.app.Activity;
211. import android.content.Context;
212. import android.os.Bundle;
213. import android.view.View;
214. import android.view.ViewGroup;
215. import android.view.animation.AnimationUtils;
216. import android.widget.AdapterView;
217. import android.widget.BaseAdapter;
218. import android.widget.Gallery;
219. import android.widget.ImageSwitcher;
220. import android.widget.ImageView;
221. import android.widget.ViewSwitcher;
222. import android.widget.Gallery.LayoutParams;
223.
224. // 图片转换器的使用基本同文字转换器
225. // 以下是一个用 ImageSwitcher + Gallery 实现的经典的图片浏览器的 Demo
226. public class _ImageSwitcher extends Activity implements
227. ViewSwitcher.ViewFactory {
228.
229. private ImageSwitcher mSwitcher;
230.
231. @Override
232. protected void onCreate(Bundle savedInstanceState) {
233. // TODO Auto-generated method stub
234. super.onCreate(savedInstanceState);
235. this.setContentView(R.layout.imageswithcer);
236.
237. setTitle("ImageSwithcer");
238.
239. mSwitcher = (ImageSwitcher) findViewById(R.id.imageSwitcher);
240. mSwitcher.setFactory(this);
241. mSwitcher.setInAnimation(AnimationUtils.loadAnimation(this,
242. android.R.anim.fade_in));
243. mSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this,
244. android.R.anim.fade_out));
245.
246. Gallery gallery = (Gallery) findViewById(R.id.gallery);
247. gallery.setAdapter(new ImageAdapter(this));
248. gallery.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
249. @Override
250. public void onItemSelected(AdapterView<?> parent, View v,
251. int position, long id) {
252. mSwitcher.setImageResource(mImageIds[position]);
253. }
254.
255. @Override
256. public void onNothingSelected(AdapterView<?> arg0) {
257.
258. }
259. });
260. }
261.
262. public class ImageAdapter extends BaseAdapter {
263.
264. private Context mContext;
265.
266. public ImageAdapter(Context context) {
267. mContext = context;
268. }
269.
270. public int getCount() {
271. return mThumbIds.length;
272. }
273.
274. public Object getItem(int position) {
275. return position;
276. }
277.
278. public long getItemId(int position) {
279. return position;
280. }
281.
282. public View getView(int position, View convertView, ViewGroup parent) {
283. ImageView image = new ImageView(mContext);
284.
285. image.setImageResource(mThumbIds[position]);
286. image.setAdjustViewBounds(true);
287. image.setLayoutParams(new Gallery.LayoutParams(
288. LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
289.
290. return image;
291. }
292. }
293.
294. private Integer[] mThumbIds = { R.drawable.icon01, R.drawable.icon02,
295. R.drawable.icon03, R.drawable.icon04, R.drawable.icon05 };
296.
297. private Integer[] mImageIds = { R.drawable.icon01, R.drawable.icon02,
298. R.drawable.icon03, R.drawable.icon04, R.drawable.icon05 };
299.
300. @Override
301. public View makeView() {
302. ImageView image = new ImageView(this);
303. image.setMinimumHeight(200);
304. image.setMinimumWidth(200);
305. image.setScaleType(ImageView.ScaleType.FIT_CENTER);
306. image.setLayoutParams(new ImageSwitcher.LayoutParams(
307. LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
308. return image;
309. }
310. }
311.
312.
313.
314. 4、GridView 的 Demo
315. gridview.xml
316.
317. 代码
318. <?xml version="1.0" encoding="utf-8"?>
319.
320. <!--
321. GridView - 网格控件
322. numColumns="auto_fit" - 列数自适应
323. stretchMode - 缩放模式(stretchMode="columnWidth" - 缩放与列宽大小同步)
324. -->
325. <GridView xmlns:android="http://schemas.android.com/apk/res/android"
326. android:id="@+id/gridView" android:layout_width="fill_parent"
327. android:layout_height="fill_parent" android:padding="10px"
328. android:verticalSpacing="10px" android:horizontalSpacing="10px"
329. android:numColumns="auto_fit" android:columnWidth="60px"
330. android:stretchMode="columnWidth" android:gravity="center">
331. </GridView>
332.
333.
334. _GridView.java
335.
336. 代码
337. package com.webabcd.view;
338.
339. import android.app.Activity;
340. import android.content.Context;
341. import android.os.Bundle;
342. import android.view.View;
343. import android.view.ViewGroup;
344. import android.widget.BaseAdapter;
345. import android.widget.GridView;
346. import android.widget.ImageView;
347.
348. public class _GridView extends Activity {
349.
350. @Override
351. protected void onCreate(Bundle savedInstanceState) {
352. // TODO Auto-generated method stub
353. super.onCreate(savedInstanceState);
354. this.setContentView(R.layout.gridview);
355.
356. setTitle("GridView");
357.
358. GridView gridView = (GridView) findViewById(R.id.gridView);
359. // 指定网格控件的适配器为自定义的图片适配器
360. gridView.setAdapter(new ImageAdapter(this));
361. }
362.
363. // 自定义的图片适配器
364. public class ImageAdapter extends BaseAdapter {
365.
366. private Context mContext;
367.
368. public ImageAdapter(Context context) {
369. mContext = context;
370. }
371.
372. public int getCount() {
373. return mThumbIds.length;
374. }
375.
376. public Object getItem(int position) {
377. return position;
378. }
379.
380. public long getItemId(int position) {
381. return position;
382. }
383.
384. public View getView(int position, View convertView, ViewGroup parent) {
385. ImageView imageView;
386. if (convertView == null) {
387. imageView = new ImageView(mContext);
388. imageView.setLayoutParams(new GridView.LayoutParams(48, 48));
389. imageView.setAdjustViewBounds(false);
390. imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
391. imageView.setPadding(5, 5, 5, 5);
392. } else {
393. imageView = (ImageView) convertView;
394. }
395.
396. imageView.setImageResource(mThumbIds[position]);
397.
398. return imageView;
399. }
400.
401. // 网格控件所需图片数据的数据源
402. private Integer[] mThumbIds = { R.drawable.icon01, R.drawable.icon02,
403. R.drawable.icon03, R.drawable.icon04, R.drawable.icon05 };
404. }
405. }
406.
407.
408.
409. 5、ListView 的 Demo
410. main_list_adapter.xml
411.
412. 代码
413. <?xml version="1.0" encoding="utf-8"?>
414. <!--
415. 自定义列表适配器的 layout
416. -->
417. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
418. android:orientation="horizontal" android:layout_width="fill_parent"
419. android:layout_height="fill_parent">
420.
421. <TextView android:id="@+id/text" android:layout_width="wrap_content"
422. android:layout_height="wrap_content" android:textSize="16sp">
423. </TextView>
424.
425. </LinearLayout>
426.
427.
428. MainListAdapter.java
429.
430. 代码
431. package com.webabcd.view;
432.
433. import java.util.List;
434.
435. import android.content.Context;
436. import android.view.LayoutInflater;
437. import android.view.View;
438. import android.view.ViewGroup;
439. import android.widget.BaseAdapter;
440. import android.widget.TextView;
441.
442. // 继承 BaseAdapter 以实现自定义的列表适配器
443. public class MainListAdapter extends BaseAdapter {
444.
445. private LayoutInflater mInflater;
446. private List<String> mData;
447.
448. public MainListAdapter(Context context, List<String> data) {
449. mInflater = LayoutInflater.from(context);
450. mData = data;
451. }
452.
453. @Override
454. public int getCount() {
455. return mData.size();
456. }
457.
458. @Override
459. public Object getItem(int position) {
460. return mData.get(position);
461. }
462.
463. @Override
464. public long getItemId(int position) {
465. return position;
466. }
467.
468. @Override
469. public View getView(int position, View convertView, ViewGroup parent) {
470.
471. TextView text;
472.
473. if (convertView == null) {
474. // 指定一个 layout 作为自定义列表适配器的 layout
475. convertView = mInflater.inflate(R.layout.main_list_adapter, null);
476. text = (TextView) convertView.findViewById(R.id.text);
477. convertView.setTag(text);
478. } else {
479. text = (TextView) convertView.getTag();
480. }
481.
482. String mItem = mData.get(position);
483. text.setText(mItem);
484.
485. return convertView;
486. }
487. }
488.
489. Main.java
490.
491. 代码
492. package com.webabcd.view;
493.
494. import java.util.ArrayList;
495. import java.util.List;
496.
497. import android.app.ListActivity;
498. import android.content.Intent;
499. import android.os.Bundle;
500. import android.view.View;
501. import android.widget.ListView;
502.
503. // 此处要继承 ListActivity ,用以实现 ListView 的功能
504. public class Main extends ListActivity {
505.
506. private List<String> mData;
507.
508. /** Called when the activity is first created. */
509. @Override
510. public void onCreate(Bundle savedInstanceState) {
511. super.onCreate(savedInstanceState);
512.
513. setTheme(android.R.style.Theme_Light);
514. setContentView(R.layout.main);
515. mData = getData();
516.
517. // 使用自定义的列表适配器来展现数据
518. MainListAdapter adapter = new MainListAdapter(this, mData);
519.
520. // 如需使用系统内置的列表适配器,则可以使用类似如下的方法
521. // ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1, mData);
522.
523. this.setListAdapter(adapter);
524. }
525.
526. // ListView 的数据源
527. private List<String> getData() {
528. List<String> items = new ArrayList<String>();
529.
530. items.add("TextView");
531. items.add("Button");
532. items.add("ImageButton");
533. items.add("ImageView");
534. items.add("CheckBox");
535. items.add("RadioButton");
536. items.add("AnalogClock");
537. items.add("DigitalClock");
538. items.add("DatePicker");
539. items.add("TimePicker");
540. items.add("ToggleButton");
541. items.add("EditText");
542. items.add("ProgressBar");
543. items.add("SeekBar");
544. items.add("AutoCompleteTextView");
545. items.add("MultiAutoCompleteTextView");
546. items.add("ZoomControls");
547. items.add("Include");
548. items.add("VideoView");
549. items.add("WebView");
550. items.add("RatingBar");
551. items.add("Tab");
552. items.add("Spinner");
553. items.add("Chronometer");
554. items.add("ScrollView");
555. items.add("TextSwitcher");
556. items.add("ListView");
557. items.add("Gallery");
558. items.add("ImageSwitcher");
559. items.add("GridView");
560. items.add("ExpandableList");
561.
562. return items;
563. }
564.
565. // ListView 中某项被选中后的逻辑
566. @Override
567. protected void onListItemClick(ListView l, View v, int position, long id) {
568. Intent intent = new Intent();
569. intent.setClassName(this, "com.webabcd.view._" + mData.get(position));
570.
571. startActivityForResult(intent, 0);
572. }
573. }
574.
575.
576. 6、ExpandableList 的 Demo
577. _ExpandableList.java
578.
579. 代码
580. package com.webabcd.view;
581.
582. import android.app.ExpandableListActivity;
583. import android.os.Bundle;
584. import android.view.ContextMenu;
585. import android.view.Gravity;
586. import android.view.MenuItem;
587. import android.view.View;
588. import android.view.ViewGroup;
589. import android.view.ContextMenu.ContextMenuInfo;
590. import android.widget.AbsListView;
591. import android.widget.BaseExpandableListAdapter;
592. import android.widget.ExpandableListAdapter;
593. import android.widget.ExpandableListView;
594. import android.widget.TextView;
595. import android.widget.Toast;
596. import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
597.
598. // ExpandableList - 可展开/收缩列表
599. // 继承 ExpandableListActivity 以实现列表的可展开/收缩的功能
600. public class _ExpandableList extends ExpandableListActivity {
601.
602. private ExpandableListAdapter mAdapter;
603.
604. @Override
605. protected void onCreate(Bundle savedInstanceState) {
606. // TODO Auto-generated method stub
607. super.onCreate(savedInstanceState);
608.
609. setTitle("ExpandableList");
610.
611. mAdapter = new MyExpandableListAdapter();
612. setListAdapter(mAdapter);
613. registerForContextMenu(this.getExpandableListView());
614. }
615.
616. // 为列表的每一项创建上下文菜单(即长按后呼出的菜单)
617. @Override
618. public void onCreateContextMenu(ContextMenu menu, View v,
619. ContextMenuInfo menuInfo) {
620. menu.setHeaderTitle("ContextMenu");
621. menu.add(0, 0, 0, "ContextMenu");
622. }
623.
624. // 单击上下文菜单后的逻辑
625. @Override
626. public boolean onContextItemSelected(MenuItem item) {
627. ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) item.getMenuInfo();
628. String title = ((TextView) info.targetView).getText().toString();
629.
630. int type = ExpandableListView.getPackedPositionType(info.packedPosition);
631. if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
632. int groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition);
633. int childPos = ExpandableListView.getPackedPositionChild(info.packedPosition);
634.
635. Toast.makeText(this, title + " - Group Index: " + groupPos + " Child Index: " + childPos, Toast.LENGTH_SHORT).show();
636.
637. return true;
638. } else if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
639. int groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition);
640. Toast.makeText(this, title + " - Group Index: " + groupPos, Toast.LENGTH_SHORT).show();
641.
642. return true;
643. }
644.
645. return false;
646. }
647.
648. public class MyExpandableListAdapter extends BaseExpandableListAdapter {
649.
650. // 父列表数据
651. private String[] groups =
652. {
653. "group1",
654. "group2",
655. "group3",
656. "group4"
657. };
658. // 子列表数据
659. private String[][] children =
660. {
661. { "child1" },
662. { "child1", "child2" },
663. { "child1", "child2", "child3" },
664. { "child1", "child2", "child3", "child4" }
665. };
666.
667. @Override
668. public Object getChild(int groupPosition, int childPosition) {
669. return children[groupPosition][childPosition];
670. }
671.
672. @Override
673. public long getChildId(int groupPosition, int childPosition) {
674. return childPosition;
675. }
676.
677. @Override
678. public int getChildrenCount(int groupPosition) {
679. return children[groupPosition].length;
680. }
681.
682. // 取子列表中的某一项的 View
683. @Override
684. public View getChildView(int groupPosition, int childPosition,
685. boolean isLastChild, View convertView, ViewGroup parent) {
686. TextView textView = getGenericView();
687. textView.setText(getChild(groupPosition, childPosition).toString());
688. return textView;
689. }
690.
691. @Override
692. public Object getGroup(int groupPosition) {
693. return groups[groupPosition];
694. }
695.
696. @Override
697. public int getGroupCount() {
698. return groups.length;
699. }
700.
701. @Override
702. public long getGroupId(int groupPosition) {
703. return groupPosition;
704. }
705.
706. // 取父列表中的某一项的 View
707. @Override
708. public View getGroupView(int groupPosition, boolean i***panded,
709. View convertView, ViewGroup parent) {
710. TextView textView = getGenericView();
711. textView.setText(getGroup(groupPosition).toString());
712. return textView;
713. }
714.
715. @Override
716. public boolean hasStableIds() {
717. return true;
718. }
719.
720. @Override
721. public boolean isChildSelectable(int groupPosition, int childPosition) {
722. return true;
723. }
724.
725. // 获取某一项的 View 的逻辑
726. private TextView getGenericView() {
727. AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
728. ViewGroup.LayoutParams.FILL_PARENT, 48);
729. TextView textView = new TextView(_ExpandableList.this);
730. textView.setLayoutParams(lp);
731. textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
732. textView.setPadding(32, 0, 0, 0);
733. return textView;
734. }
735. }
736. }
Android SurfaceView小解
文章分类:移动开发
注:来自东方尚智沈大海博客 在android中开发游戏,一般来说,或想写一个复杂一点的游戏,是必须用到SurfaceView来开发的。经过这一阵子对android的学习,我找到了自已在android中游戏开发的误区,不要老想着用Layout和view去实现,不要将某个游戏中的对象做成一个组件来处理。应该尽量想着在Canvas(画布)中画出游戏戏中的背景、人物、动画等...SurfaceView提供直接访问一个可画图的界面,可以控制在界面顶部的子视图层。SurfaceView是提供给需要直接画像素而不是使用窗体部件的应用使用的。Android图形系统中一个重要的概念和线索是surface。View及其子类(如TextView, Button)要画在surface上。每个surface创建一个Canvas对象(但属性时常改变),用来管理view在surface上的绘图操作,如画点画线。还要注意的是,使用它的时候,一般都是出现在最顶层的:The view hierarchy will take care of correctly compositing with the Surface any siblings of the SurfaceView that would normally appear on top of it. 使用的SurfaceView的时候,一般情况下还要对其进行创建,销毁,改变时的情况进行监视,这就要用到SurfaceHolder.Callback. 在用SurfaceView进行游戏开发过程中,用到SurfaceHolder来处理它的Canvas上画的效果和动画是必不可少的。用于控制表面,大小,像素等。 Abstract interface to someone holding a display surface. Allows you to control the surface size and format, edit the pixels in the surface, and monitor changes to the surface. This interface is typically available through the SurfaceView class. 其中特别要注意以下的几个函数: abstract void addCallback(SurfaceHolder.Callback callback); // 给SurfaceView当前的持有者一个回调对象。 abstract Canvas lockCanvas(); // 锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。 abstract Canvas lockCanvas(Rect dirty); // 锁定画布的某个区域进行画图等..因为画完图后,会调用下面的unlockCanvasAndPost来
改变显示内容。 // 相对部分内存要求比较高的游戏来说,可以不用重画dirty外的其它区域的像素,可以提高速度。 abstract void unlockCanvasAndPost(Canvas canvas); // 结束锁定画图,并提交改变。 实例:用线程画一个蓝色的长方形。
Java代码
1. import android.app.Activity;
2. import android.content.Context;
3. import android.graphics.Canvas;
4. import android.graphics.Color;
5. import android.graphics.Paint;
6. import android.graphics.RectF;
7. import android.os.Bundle;
8. import android.view.SurfaceHolder;
9. import android.view.SurfaceView;
10.
11. public class Test extends Activity {
12.
13. public void onCreate(Bundle savedInstanceState) {
14. super.onCreate(savedInstanceState);
15. setContentView(new MyView(this));
16. }
17.
18. //内部类
19. class MyView extends SurfaceView implements SurfaceHolder.Callback{
20.
21. SurfaceHolder holder;
22. public MyView(Context context) {
23. super(context);
24. holder = this.getHolder();//获取holder
25. holder.addCallback(this);
26. //setFocusable(true);
27. }
28.
29. @Override
30. public void surfaceChanged(SurfaceHolder holder, int format, int width,
31. int height) {
32.
33. }
34.
35. @Override
36. public void surfaceCreated(SurfaceHolder holder) {
37. new Thread(new MyThread()).start();
38. }
39.
40. @Override
41. public void surfaceDestroyed(SurfaceHolder holder) {}
42.
43. //内部类的内部类
44. class MyThread implements Runnable{
45.
46. @Override
47. public void run() {
48. Canvas canvas = holder.lockCanvas(null);//获取画布
49. Paint mPaint = new Paint();
50. mPaint.setColor(Color.BLUE);
51.
52. canvas.drawRect(new RectF(40,60,80,80), mPaint);
53. holder.unlockCanvasAndPost(canvas);//解锁画布,提交画好的图像
54. }
55.
56. }
57.
58. }
59. }
访问SurfaceView的底层图形是通过SurfaceHolder接口来实现的,通过getHolder()方法可以得到这个SurfaceHolder对象。你应该实现surfaceCreated(SurfaceHolder)和surfaceDestroyed(SurfaceHolder)方法来知道在这个Surface在窗口的显示和隐藏过程中是什么时候创建和销毁的。SurfaceView可以在多线程中被访问。注意:一个SurfaceView只在SurfaceHolder.Callback.surfaceCreated() 和SurfaceHolder.Callback.surfaceDestroyed()调用之间是可用的,其他时间是得不到它的Canvas对象的(null)。 我的访问过程: 创建一个SurfaceView的子类,实现SurfaceHolder.Callback接口。 得到这个SurfaceView的SurfaceHolder对象holder。 holder.addCallback(callback),也就是实现SurfaceHolder.Callback接口的类对象。 在SurfaceHolder.Callback.surfaceCreated()调用过后holder.lockCanvas()对象就可以得到SurfaceView对象对应的Canvas对象canvas了。 用canvas对象画图。 画图结束后调用holder.unlockCanvasAndPost()就把图画在窗口中了。 SurfaceView可以多线程访问,在多线程中画图。
Java代码
1. import android.content.Context;
2. import android.graphics.Canvas;
3. import android.graphics.Color;
4. import android.graphics.Paint;
5. import android.util.Log;
6. import android.view.SurfaceHolder;
7. import android.view.SurfaceView;
8.
9. public class MySurfaceView extends SurfaceView implements
10. SurfaceHolder.Callback {
11.
12.
13. private Context mContext;
14. private SurfaceHolder mHolder;
15.
16. public TouchScreenAdjusterSurfaceView(Context context,) {
17. super(context);
18.
19. mContext = context;
20.
21. mHolder = TouchScreenAdjusterSurfaceView.this.getHolder();
22. mHolder.addCallback(TouchScreenAdjusterSurfaceView.this);
23.
24. this.setFocusableInTouchMode(true); // to make sure that we can get
25. // touch events and key events,and
26. // "setFocusable()" to make sure we
27. // can get key events
28. }
29.
30. @Override
31. public void surfaceChanged(SurfaceHolder holder, int format, int width,
32. int height) {
33. // TODO Auto-generated method stub
34.
35. }
36.
37. @Override
38. public void surfaceCreated(SurfaceHolder holder) {
39. //now you can get the Canvas and draw something here
40. }
41.
42. @Override
43. public void surfaceDestroyed(SurfaceHolder holder) {
44. // TODO Auto-generated method stub
45.
46. }
47.
48.
49. public void drawMyShape(PointPostion ps) {
50.
51. mCanvas = mHolder.lockCanvas();
52.
53. // draw anything you like
54.
55. mHolder.unlockCanvasAndPost(mCanvas);
56. }
57.
58. }
android琐碎笔记六
文章分类:移动开发
1.得到屏幕的screen dimensions Display display = getWindowManager().getDefaultDisplay(); int width = display.getWidth();int height = display.getHeight(); 2. 播放 gif图片在android @Override protected void onDraw(Canvas canvas) { canvas.drawColor(0xFFCCCCCC); Paint p = new Paint(); p.setAntiAlias(true); canvas.drawBitmap(mBitmap4, 210, 170, null); mDrawable.draw(canvas); long now = android.os.SystemClock.uptimeMillis(); if (mMovieStart == 0) { // first time mMovieStart = now; } if (mMovie != null) { int dur = mMovie.duration(); if (dur == 0) { dur = 1000; } int relTime = (int)((now - mMovieStart) % dur); mMovie.setTime(relTime); mMovie.draw(canvas, getWidth() - mMovie.width(), getHeight() - mMovie.height()); invalidate(); } }
@Override protected void onDraw(Canvas canvas) { if(movie != null) { long now = android.os.SystemClock.uptimeMillis(); int dur = Math.max(movie.duration(), 1); // is it really animated? int pos = (int)(now % dur); movie.setTime(pos); movie.draw(canvas, x, y); invalidate(); }} 4. 打开sd卡中的sqllite File dbfile = new File("/sdcard/mydb.sqlite" ); SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbfile, null); 5.得到手机的IMEI ((TelephonyManager) getSystemService=(Context.TELEPHONY_SERVICE)).getDeviceId(); 6. 不让程序 生成一个appliation 去掉 <category android:name="android.intent.category.LAUNCHER" /> 当然你的让你的程序 被引导启动 7.使用appliation 的id 可以获得不同appliation的数据: android:sharedUserId="string" 在主xml中添加上面一句话,然后签名也要一样 两个app的id也要设置成一样 如都是string 那么这两个程序就可以相互访问彼此的数据,也可以在同一个process中了 8.判断相机设备存在不 private android.hardware.Camera mCameraDevice; try { mCameraDevice = android.hardware.Camera.open();} catch (RuntimeException e) { Log.e(TAG, "fail to connect Camera", e); 9使listView 透明 android:background="#00000000" android:cacheColorHint="#00000000" 或者 android:background="@android:color/transparent" •The background android screen image should be visible. 屏幕的背景图像可以看见 manifest file 添加attribute 到 activity. android:theme="@android:style/Theme.Dialog"
Android通过selector改变界面状态
文章分类:移动开发
先上图,看看效果:
初始效果 按下后效果
在res/drawable文件夹新增一个文件,此文件设置了图片的触发状态,你可以设置state_pressed,state_checked,state_pressed,state_selected,state_focused,state_enabled等几个状态:
Java代码
1. <selector xmlns:android="http://schemas.android.com/apk/res/android">
2.
3. <item android:state_pressed="true" android:drawable="@drawable/arrow_pressed" />
4. <item android:drawable="@drawable/arrow_normal" />
5. <item android:state_checked="true" android:drawable="@drawable/arrow_pressed" />
6. </selector>
实现如下,注意其中的android:src="@drawable/imageselector"
Xml代码
1. <ImageView android:layout_width="wrap_content"
2. android:layout_height="@android:dimen/app_icon_size"
3. android:layout_alignParentRight="true" android:scaleType="fitCenter"
4. android:layout_gravity="center" android:src="@drawable/imageselector"
5. android:clickable="true" android:focusable="true" android:id="@+id/blacklistImageView"
6. android:layout_marginRight="10dip" />
如果当触发的控件不是ImageView,而是别的控件,可在代码中用
Java代码
1. blacklistImageView.setPressed(true);
Java代码
1. blacklistImageView.setChecked(true);
Android 经典小技巧总结
一、这是一篇关于如何将自定义的 homescreen 设定为Android的默认主页,而不需要用户选择的讨论贴,原文如下:
Another additional info: If you want that your homescreen is always the default and that the system doesn't ask to choose between different home screens simply put it that way: XML:
<intent-filter priority="1">
<action name="android.intent.action.MAIN"></action>
<category name="android.intent.category.HOME"></category>
<category name="android.intent.category.DEFAULT"></category>
<category name="android.intent.category.MONKEY"></category>
</intent-filter>
The difference to the XML above is android:priority="1". It seems that the default home screen has priority 0 and therefore setting the priority
of your home screen to 1 is sufficient to force the usage of your home screen
android shape渐近线效果
文章分类:综合技术
http://wang-peng1.javaeye.com/blog/523869 android画图-----shape的使用 在GradientDrawable1试图中终于把shape学会了,以前总是似懂非懂, 现在终于把里面的东西搞清楚了,同时也挺佩服谷歌的用心,故意设 置一些陷阱吧,不认真对待还真以为没有啥效果呢。 setContentView(R.layout.shape_drawable_1) shape_drawable_1 代码如下: <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content"> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content"> <ImageView android:layout_width="fill_parent" android:layout_height="50dip" android:src="@drawable/shape_1" /> <ImageView android:layout_width="fill_parent" android:layout_height="50dip" android:src="@drawable/line" /> <ImageView android:layout_width="fill_parent" android:layout_height="50dip" android:src="@drawable/shape_2" /> <ImageView android:layout_width="fill_parent" android:layout_height="wrap_content" android:src="@drawable/line" />
<ImageView android:layout_width="fill_parent" android:layout_height="50dip" android:src="@drawable/shape_3" /> <ImageView android:layout_width="fill_parent" android:layout_height="20dip" android:src="@drawable/line" /> <ImageView android:layout_width="fill_parent" android:layout_height="50dip" android:src="@drawable/shape_4" /> <ImageView android:layout_width="fill_parent" android:layout_height="wrap_content" android:src="@drawable/line" /> <ImageView android:layout_width="fill_parent" android:layout_height="50dip" android:src="@drawable/shape_5" /> </LinearLayout> </ScrollView> shape_5的代码: <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <gradient android:startColor="#FFFF0000" android:endColor="#80FF00FF" android:angle="270"/> <padding android:left="50dp" android:top="20dp" android:right="7dp" android:bottom="7dp" /> <corners android:radius="8dp" /> </shape> gradient 产生颜色渐变 android:angle 从哪个角度开始变 貌似只有90的整数倍可以 android:shape="rectangle" 默认的也是长方形 <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="#ff4100ff"/>
<stroke android:width="2dp" android:color="#ee31ff5e" android:dashWidth="3dp" android:dashGap="2dp" /> <padding android:left="7dp" android:top="7dp" android:right="7dp" android:bottom="7dp" /> <corners android:radius="6dp" /> </shape> #ff4100ff蓝色#ff4100ff绿色 <solid android:color="#ff4100ff"/>实心的 填充里面 <stroke 描边 采用那样的方式将外形轮廓线画出来 android:dashWidth="3dp" android:dashGap="2dp" 默认值为0 android:width="2dp" android:color="#FF00ff00"笔的粗细, android:dashWidth="5dp" android:dashGap="5dp" 实现- - -这样的效果,dashWidth指的是一条小横线的宽度 dashGap 指的是 小横线与小横线的间距。 width="2dp" 不能太宽
分析android动画模块
关键字: android 动画
主要思路
Tween 动画通过对 View 的内容完成一系列的图形变换 (包括平移、缩放、旋转、改变透明度)来实现动画效果。
具体来讲,预先定义一组指令,这些指令指定了图形变换的类型、触发时间、持续时间。这些指令可以是以 XML 文件方式定义,也可以是以源代码方式定义。程序沿着时间线执行这些指令就可以实现动画效果。
动画的进度使用 Interpolator 控制,android 提供了几个 Interpolator 子类,实现了不同的速度曲线,如LinearInterpolator 实现了匀速效果、 Accelerateinterpolator 实现了加速效果、DecelerateInterpolator 实现了减速效果等。还可以定义自己的 Interpolator 子类,实现抛物线、自由落体等物理效果。
动画的运行模式有两种:
 独占模式,即程序主线程进入一个循环,根据动画指令不断刷新屏幕,直到动画结束;
 中断模式,即有单独一个线程对时间计数,每隔一定的时间向主线程发通知,主线程接到通知后更新屏幕;
图形变换通过仿射矩阵实现。图形变换是图形学中的基本知识。简单来说就是,每种变换都是一次矩阵运算。在 Android 中,Canvas 类中包含当前矩阵,当调用 Canvas.drawBitmap
(bmp, x, y, Paint) 绘制时,android 会先把 bmp 做一次矩阵运算,然后将运算的结果显示在 Canvas 上。这样,编程人员只需不断修改 Canvas 的矩阵并刷新屏幕,View 里的对象就会不停的做图形变换,动画就形成了。
在 android 中提供了 Animation 、 Interpolator、Transformation 等类具体实现 Tween 动画,下面逐一分析。
Animation 类及其子类
Animation 类及其子类是动画的核心模块,它实现了各种动画效果,如平移、缩 放、旋转、改变透明度等。
Tween 动画的每一桢都根据 Interpolator 对 view 的内容做一次图形变换,因此 Animation 的核心工作是做变换(transformation)。
Aniamtion 是基类,他记录了动画的通用属性和方法。主要的属性包括动画持续时间、重复次数、interpolator 等。动画里最重要的方法是 getTransformation (currentTime, outTransformation),该方法根据当前间 (currentTime) 和 interpolator,计算当前的变换,在 outTransformation 中返回。
TranslateAnimation、RotateAnimation、AlphaAnimation 等是 Animation 的 子类,分别实现了平移、旋转、改变 Alpha 值等动画。
每个动画都重载了父类的 applyTransformation 方法,这个方法会被父类的 getTransformation 方法调用。另外每个动画还有个 initialize 方法,完成初始化工作。
不同的动画具有不同的属性,如 RotateAnimation 的属性是起始角度、终止角度和旋转点坐标, TranslateAnimation 的属性是起始位置和终止位置。AlphaAnimation 的属性是起始 alpha 值和终止 alpha 值。
Animation 类及其子类的类图如下所示:
Interpolator 类及其子类
Interpolator 定义了动画的变化速度,可以实现匀速、正加速、负加速、无规则变加速等;
Interpolator 是基类,封装了所有 Interpolator 的共同方法,它只有一个方法,即 getInterpolation (float input),该方法 maps a point on the timeline to a multiplier to be applied to the transformations of an animation.
LinearInerpolator、AccelerateInterpolator, DecelerateInterpolator, AccelerateDecelerateInterpolator,CycleInterpolator 是 Interpolator 的子类,分别实现了匀速、加速、减速、变速、循环等效果。
对于 LinearInterpolator ,变化率是个常数,即 f (x) = x.
Java代码
1. public float getInterpolation(float input) {
2. return input;
3. }
对于 AccelerateInterpolator,开始变化很慢,然后逐渐变快,即 f(x) = x*x 或者 f(x) = pow(x, 2*mFactor).
Java代码
1. public float getInterpolation(float input) {
2. if (mFactor == 1.0f) {
3. return (float)(input * input);
4. } else {
5. return (float)Math.pow(input, 2 * mFactor);
6. }
7. }
对于 AccelerateDecelerateInterpolator,变化率开始和结束都很慢,但中间 很快,即 f(x) = (cos ((x+1)*PI) / 2.0f) + 0.5f.
Java代码
1. public float getInterpolation(float input) {
2. return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
3. }
Interpolator 类及其子类的类图如下所示:
Transformation 类
Transformation 记录了仿射矩阵 Matrix,动画每触发一次,会对原来的矩阵做一次运算, View 的 Bitmap 与这个矩阵相乘就可实现相应的操作(旋转、平移、缩放等)。
Transformation 类封装了矩阵和 alpha 值,它有两个重要的成员,一是 mMatrix,二是 mAlpha。
Transformation 类图如下所示:
如何在 View 中实现动画
从逻辑上讲,实现动画需要如下几步:
1. view 创建动画对象,设置动画属性,调用 invalidate 刷新屏幕,启动动画;
2. invalidate 方法触发了 onDraw 函数;
3. 在 onDraw 函数中:
o 调用动画的 getTransformation 方法,得到当前时间点的矩阵
o 将该矩阵设置成 Canvas 的当前矩阵
o 调用 canvas 的 drawBitmap 方法,绘制屏幕。
o 判断 getTransformation 的返回值,若为真,调用 invalidate 方法,刷新屏幕进入下一桢;若为假,说明动画完成。
整个流程可用一个序列图表示:
使用样例
下面的代码是一个 view,系统创建 view 时会调用 onCreate 方法,该方法定义了一个 TranslateAniamtion,指定了移动起点和终点,动画持续时间为 1s,最后调用 startAnimation 将该动画保存在 View 的成员 mCurrentAnianmtion 中并启动动画。
注意,在 View 中需要定义成员变量 mCurrentAnimation 和 mTransformation ,分别记录当前的动画和变换。另外需要定义成员函数 startAnimation 启动动画。
Java代码
1. class MyView extends View {
2.
3. Animation mCurrentAnimation = null;
4.
5. Transformation mTransformation = new Transformation;
6.
7.
8.
9. private void setAnimation(Animation animation) {
10. mCurrentAnimation = animation;
11. if (animation != null) {
12. animation.reset();
13. }
14. }
15.
16.
17.
18. public void startAnimation(Animation animation) {
19. animation.setStartTime(animation.START_ON_FIRST_FRAME);
20. setAnimation(animation);
21. invalidate();
22. }
23.
24.
25. onDraw (Canvas canvas) {
26.
27. long curTime = SystemClock.uptimeMillis ();
28.
29. if (mCurrentAniamtion == null){
30.
31. canvas.drawBitmap (b, x, y, mPaint);
32.
33. }
34.
35. else {
36.
37. if (!mCurrentAnimation.isInitialized()) //initialize animation
38.
39. mCurrentAnimation.initialize (w, h, pw, ph);
40.
41. boolean more = mCurrentAnimation.getTransformation (curTime, mTransformation);
42.
43. if(more) {
44.
45. Matrix m = canvas.getMatrix();
46.
47. canvas.setMatrix (mTransformation.getMatrix());
48.
49. canvas.drawBitmap (b, x, y, mPaint);
50.
51. canvas.setMatrix (m);
52.
53. this.invalidate ();
54.
55. }
56.
57. else {
58.
59. mCurrentAnimation = null;
60.
61. this.invalidate ();
62.
63. }
64.
65. }
66.
67.
68.
69. }
70.
71.
72. void onCreate (){
73.
74. Animation anim = new TranslateAnimation (10, 20, 0, 0);
75.
76. anim.setDuration (1000); // 1s
77.
78. anim.setInterpolator (new AcceleratInterpolator(3.0f));
79.
80. startAniamtion (anim);
81.
82. }
83. }
Android Animation Frame动画
文章分类:Java编程
1.java代码实现:
Java代码
1. package com.Aina.Android;
2.
3. import android.content.Context;
4. import android.graphics.Canvas;
5. import android.graphics.drawable.AnimationDrawable;
6. import android.graphics.drawable.Drawable;
7. import android.view.KeyEvent;
8. import android.view.View;
9. import android.widget.ImageView;
10.
11. /**
12. * com.Aina.Android Pro_AnimationFrame
13. *
14. * @author Aina.huang E-mail: 674023920@qq.com
15. * @version 创建时间:2010 Jun 18, 2010 1:56:18 PM 类说明
16. */
17. public class GameView extends View {
18.
19. private AnimationDrawable mAnimationDrawable = null;
20. private Context mContext = null;
21. private Drawable mDrawable = null;
22.
23. public GameView(Context context) {
24. super(context);
25. this.mContext = context;
26.
27. mAnimationDrawable = new AnimationDrawable();
28. for (int i = 1; i <= 15; i++) {
29. int id = this.getResources().getIdentifier("a" + i, "drawable",
30. mContext.getPackageName());
31. mDrawable = this.getResources().getDrawable(id);
32. mAnimationDrawable.addFrame(mDrawable, 100);// 为动画添加一帧.时间为毫秒
33. }
34. mAnimationDrawable.setOneShot(false);// 设置播放模式是否循环,false循环,true不循环.
35.
36. // ImageView iv = new ImageView(mContext);
37. // iv.setBackgroundResource(R.anim.frame);
38. // mAnimationDrawable = (AnimationDrawable) iv.getBackground();
39. this.setBackgroundDrawable(mAnimationDrawable);// 显示动画.
40.
41. }
42.
43. @Override
44. protected void onDraw(Canvas canvas) {
45. super.onDraw(canvas);
46. }
47. public boolean onKeyDown(int keyCode, KeyEvent event) {
48. if(keyCode==KeyEvent.KEYCODE_1){
49. mAnimationDrawable.start();//启动动画.
50. }
51. return super.onKeyDown(keyCode, event);
52. }
53. }
Java代码
1. package com.Aina.Android;
2.
3. import android.app.Activity;
4. import android.os.Bundle;
5. import android.view.KeyEvent;
6.
7. public class Test_Frame extends Activity {
8. /** Called when the activity is first created. */
9. private GameView gv = null;
10. @Override
11. public void onCreate(Bundle savedInstanceState) {
12. super.onCreate(savedInstanceState);
13. gv = new GameView(this);
14. setContentView(gv);
15. }
16. @Override
17. public boolean onKeyDown(int keyCode, KeyEvent event) {
18. return gv.onKeyDown(keyCode, event);
19. }
20.
21. }
2.xml布局文件实现:
Java代码
1. <?xml version="1.0" encoding="utf-8"?>
2. <animation-list
3. xmlns:android="http://schemas.android.com/apk/res/android"
4. android:oneshot="false">
5. <item android:drawable="@drawable/a1" android:duration="100" />
6. <item android:drawable="@drawable/a2" android:duration="100" />
7. <item android:drawable="@drawable/a3" android:duration="100" />
8. <item android:drawable="@drawable/a4" android:duration="100" />
9. <item android:drawable="@drawable/a5" android:duration="100" />
10. <item android:drawable="@drawable/a6" android:duration="100" />
11. <item android:drawable="@drawable/a7" android:duration="100" />
12. <item android:drawable="@drawable/a8" android:duration="100" />
13. <item android:drawable="@drawable/a9" android:duration="100" />
14. <item android:drawable="@drawable/a10" android:duration="100" />
15. <item android:drawable="@drawable/a11" android:duration="100" />
16. <item android:drawable="@drawable/a12" android:duration="100" />
17. <item android:drawable="@drawable/a13" android:duration="100" />
18. <item android:drawable="@drawable/a14" android:duration="100" />
19. <item android:drawable="@drawable/a15" android:duration="100" />
20. </animation-list>
Java代码
1. package com.Aina.Android;
2.
3. import android.content.Context;
4. import android.graphics.Canvas;
5. import android.graphics.drawable.AnimationDrawable;
6. import android.graphics.drawable.Drawable;
7. import android.view.KeyEvent;
8. import android.view.View;
9. import android.widget.ImageView;
10.
11. /**
12. * com.Aina.Android Pro_AnimationFrame
13. *
14. * @author Aina.huang E-mail: 674023920@qq.com
15. * @version 创建时间:2010 Jun 18, 2010 1:56:18 PM 类说明
16. */
17. public class GameView extends View {
18.
19. private AnimationDrawable mAnimationDrawable = null;
20. private Context mContext = null;
21. private Drawable mDrawable = null;
22.
23. public GameView(Context context) {
24. super(context);
25. this.mContext = context;
26. /*
27. mAnimationDrawable = new AnimationDrawable();
28. for (int i = 1; i <= 15; i++) {
29. int id = this.getResources().getIdentifier("a" + i, "drawable",
30. mContext.getPackageName());
31. mDrawable = this.getResources().getDrawable(id);
32. mAnimationDrawable.addFrame(mDrawable, 100);// 为动画添加一帧.时间为毫秒
33. }
34. mAnimationDrawable.setOneShot(false);// 设置播放模式是否循环,false循环,true不循环.
35. */
36. ImageView iv = new ImageView(mContext);
37. iv.setBackgroundResource(R.anim.frame);
38. mAnimationDrawable = (AnimationDrawable) iv.getBackground();
39. this.setBackgroundDrawable(mAnimationDrawable);// 显示动画.
40.
41. }
42.
43. @Override
44. protected void onDraw(Canvas canvas) {
45. super.onDraw(canvas);
46. }
47. public boolean onKeyDown(int keyCode, KeyEvent event) {
48. if(keyCode==KeyEvent.KEYCODE_1){
49. mAnimationDrawable.start();//启动动画.
50. }
51. return super.onKeyDown(keyCode, event);
52. }
53. }
Android ImageSwithcher的使用
文章分类:Java编程
图片切换ImageSwitcher的使用:
Java代码
1. package com.Aina.Android;
2. import android.app.Activity;
3. import android.os.Bundle;
4. import android.util.Log;
5. import android.view.View;
6. import android.view.View.OnClickListener;
7. import android.widget.Button;
8. import android.widget.ImageSwitcher;
9. import android.widget.ImageView;
10. import android.widget.LinearLayout;
11. import android.widget.ViewSwitcher.ViewFactory;
12.
13. public class Test_ImageSwitcher extends Activity implements OnClickListener,ViewFactory{
14. /** Called when the activity is first created. */
15. //所有要显示的图片资源索引
16. private static final Integer[] imagelist = {
17. R.drawable.img1,
18. R.drawable.img2,
19. R.drawable.img3,
20. R.drawable.img4,
21. R.drawable.img5,
22. R.drawable.img6,
23. R.drawable.img7,
24. R.drawable.img8
25. };
26. private ImageSwitcher imageswitcher;
27. private static int index = 0;
28. //设置各组件ID
29. private static final int Button_NEXT = 0x123456;
30. private static final int Button_BACK = 0x123457;
31. private static final int ImageSwitcher = 0x123458;
32. @Override
33. public void onCreate(Bundle savedInstanceState) {
34. super.onCreate(savedInstanceState);
35. //创建一个线性布局
36. LinearLayout layout = new LinearLayout(this);
37. layout.setOrientation(LinearLayout.HORIZONTAL);//水平布局
38. imageswitcher = new ImageSwitcher(this);
39. LinearLayout.LayoutParams p2 = new LinearLayout.LayoutParams(120,120);
40. layout.addView(imageswitcher,p2);
41. imageswitcher.setId(ImageSwitcher);//设置ID
42. imageswitcher.setFactory(this);//设置此对象的数据源
43. imageswitcher.setImageResource(imagelist[index]);
44. setContentView(layout);
45.
46. //创建下一张按钮
47. Button next = new Button(this);
48. next.setId(Button_NEXT);
49. next.setText("下一张");
50. next.setOnClickListener(this);
51. LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(100,100);
52. layout.addView(next, p);
53. //创建上一张按钮
54. Button back = new Button(this);
55. back.setId(Button_BACK);
56. back.setText("上一张");
57. back.setOnClickListener(this);
58. layout.addView(back, p);
59. }
60. @Override
61. public void onClick(View v) {
62. if(v.getId()==Button_BACK){
63. index--;
64. if(index<0){
65. index = imagelist.length-1;
66. }
67. imageswitcher.setImageResource(imagelist[index]);
68. }else if(v.getId()==Button_NEXT){
69. index++;
70. if(index>=imagelist.length){
71. index = 0;
72. }
73. imageswitcher.setImageResource(imagelist[index]);
74. }
75. }
76. @Override
77. public View makeView() {
78. Log.i("TAG", "makeView()");
79. return new ImageView(this);
80. }
81. }
android图形图像
文章分类:移动开发
一、 android.graphics.Matrix 有关图形的变换、缩放等相关操作常用的方法有: void reset() // 重置一个matrix对象。 void set(Matrix src) //复制一个源矩阵,和本类的构造方法 Matrix(Matrix src) 一样 boolean isIdentity() //返回这个矩阵是否定义(已经有意义) void setRotate(float degrees) //指定一个角度以0,0为坐标进行旋转 void setRotate(float degrees, float px, float py) //指定一个角度以px,py为坐标进行旋转 void setScale(float sx, float sy) // 缩放 void setScale(float sx, float sy, float px, float py) //以坐标px,py进行缩放 void setTranslate(float dx, float dy) //平移 void setSkew (float kx, float ky, float px, float py) //以坐标px,py进行倾斜 void setSkew (float kx, float ky) //倾斜 二、android.graphics.NinePatch NinePatch是Android平台特有的一种非矢量图形自然拉伸处理方法,可以帮助常规的图形在拉伸时不会缩放,实例中Android开发网提示大家对于Toast的显示就是该原理,同时SDK中提供了一个工具名为Draw 9-Patch,有关该工具的使用方法可以参考我们经发布的 Draw 9-Patch使用方法介绍一文。由于该类提供了高质量支持透明的缩放方式,所以图形格式为PNG,文件命名方式为.9.png 的后缀比如android123.9.png。 三、android.graphics.Paint Paint类我们可以理解为画笔、画刷的属性定义,本类常用的方法如下: void reset() //重置 void setARGB(int a, int r, int g, int b) 或 void setColor(int color) 均为设置Paint对象的颜色 void setAntiAlias(boolean aa) //是否抗锯齿,需要配合void setFlags (Paint.ANTI_ALIAS_FLAG) 来帮助消除锯齿使其边缘更平滑。 Shader setShader(Shader shader) //设置阴影,Shader类是一个矩阵对象,如果为NULL将清除阴影。
void setStyle(Paint.Style style) //设置样式,一般为 FILL 填充,或者STROKE凹陷效果。 void setTextSize(float textSize) //设置字体大小 void setTextAlign(Paint.Align align) //文本对齐方式 Typeface setTypeface(Typeface typeface) //设置字体,通过Typeface可以加载Android内部的字体,一般为宋体对于中文,部分ROM可以自己添加比如雅黑等等 void setUnderlineText(boolean underlineText) //是否设置下划线,需要撇和void setFlags (Paint.UNDERLINE_TEXT_FLAG) 方法。 四、android.graphics.Rect Rect我们可以理解为矩形区域,类似的还有Point一个点,Rect类除了表示一个矩形区域位置描述外,android123提示主要可以帮助我们计算图形之间是否碰撞(包含)关系,对于Android游戏开发比较有用,其主要的成员contains包含了三种重载方法,来判断包含关系 boolean contains(int left, int top, int right, int bottom) boolean contains(int x, int y) boolean contains(Rect r) 五、android.graphics.Region Region在Android平台中表示一个区域和Rect不同的是,它表示的是一个不规则的样子,可以是椭圆、多边形等等,而Rect仅仅是矩形。同样Region的boolean contains(int x, int y) 成员可以判断一个点是否在该区域内 六、android.graphics.Typeface Typeface类是帮助描述一个字体对象,在TextView中通过使用setTypeface方法来制定一个输出文本的字体,其直接构造调用成员create方法可以直接指定一个字体名称和样式,比如 static Typeface create(Typeface family, int style) static Typeface create(String familyName, int style) 同时使用isBold和isItalic方法可以判断出是否包含粗体或斜体的字型。 final boolean isBold() final boolean isItalic() 该类的创建方法还有从apk的资源或从一个具体的文件路径,其具体方法为 static Typeface createFromAsset(AssetManager mgr, String path) static Typeface createFromFile(File path) static Typeface createFromFile(String path)
Android ImageSwitcher和Gallery 综合使用
文章分类:移动开发
一个简易的相册
功能描述: 点击按钮进入下一屏,在屏幕上面展示一个大图,在屏幕的下面是一组可以滚动的图片,点击滚动的图片可以显示在上面的控件中。
效果图如下:
开发环境:eclipse3.4.2 AndroidSDK2.0 ADT0.9.7
代码:
1.MainActivity 单击按钮时,跳转到 ImageShowActivity
Java代码
1. package com.small.photos;
2.
3. import com.small.photos.R;
4. import android.widget.*;
5. import android.app.Activity;
6. import android.content.Intent;
7. import android.os.Bundle;
8. import android.view.View;
9. import android.view.View.OnClickListener;
10.
11. public class MainActivity extends Activity {
12.
13. OnClickListener listener0 = null;
14. Button button0;
15.
16. @Override
17. public void onCreate(Bundle savedInstanceState) {
18. super.onCreate(savedInstanceState);
19. setContentView(R.layout.main);
20.
21. // 单击按钮跳转到ImageShowActivity
22. listener0 = new OnClickListener() {
23. public void onClick(View v) {
24. Intent intent = new Intent(MainActivity.this,
25. ImageShowActivity.class);
26. startActivity(intent);
27. }
28. };
29.
30. button0 = (Button) findViewById(R.id.image_show_button);
31. button0.setOnClickListener(listener0);
32. }
33.
34. }
2. main.xml 定义入口按钮
Java代码
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. android:orientation="vertical"
4. android:layout_width="fill_parent"
5. android:layout_height="fill_parent"
6. >
7. <Button android:id="@+id/image_show_button"
8. android:text="ImageSwitcher Gallery"
9. android:layout_width="wrap_content"
10. android:layout_height="wrap_content">
11. </Button>
12. </LinearLayout>
3.image_show.xml
ImageSwitcher是用来图片显示那块区域的控件 Gallery 是来控制底下那个图标列表索引用的
Java代码
1. <?xml version="1.0" encoding="utf-8"?>
2. <RelativeLayout
3. xmlns:android="http://schemas.android.com/apk/res/android"
4. android:layout_width="fill_parent"
5. android:layout_height="fill_parent">
6.
7. <ImageSwitcher android:id="@+id/ImageSwitcher01"
8. android:layout_height="fill_parent"
9. android:layout_width="fill_parent"
10. android:layout_alignParentTop="true"
11. android:layout_alignParentLeft="true">
12. </ImageSwitcher>
13.
14.
15. <Gallery
16. android:id="@+id/gallery"
17. android:background="#55000000"
18. android:layout_width="fill_parent"
19. android:layout_height="60dp"
20. android:layout_alignParentBottom="true"
21. android:layout_alignParentLeft="true"
22. android:gravity="center_vertical"
23. android:spacing="16dp" />
24.
25. </RelativeLayout>
4.ImageShowActivity
R.drawable.sample_thumb_0 为图片的标识
图片放在res/drawable/目录下 图片名称为sample_thumb_0.gif
Java代码
1. package com.small.photos;
2.
3. import android.app.Activity;
4. import android.content.Context;
5. import android.os.Bundle;
6. import android.view.View;
7. import android.view.ViewGroup;
8. import android.view.Window;
9. import android.view.animation.AnimationUtils;
10. import android.widget.AdapterView;
11. import android.widget.BaseAdapter;
12. import android.widget.Gallery;
13. import android.widget.ImageSwitcher;
14. import android.widget.ImageView;
15. import android.widget.AdapterView.OnItemSelectedListener;
16. import android.widget.RelativeLayout.LayoutParams;
17. import android.widget.ViewSwitcher.ViewFactory;
18.
19. public class ImageShowActivity extends Activity implements ViewFactory,
20. OnItemSelectedListener {
21. /** Called when the activity is first created. */
22. ImageSwitcher mSwitcher;
23. private Integer[] mThumbIds = { R.drawable.sample_thumb_0,
24. R.drawable.sample_thumb_1, R.drawable.sample_0, R.drawable.sample_1 };
25.
26. private Integer[] mImageIds = { R.drawable.sample_thumb_0,
27. R.drawable.sample_thumb_1, R.drawable.sample_0, R.drawable.sample_1 };
28.
29. @Override
30. public void onCreate(Bundle savedInstanceState) {
31. super.onCreate(savedInstanceState);
32. requestWindowFeature(Window.FEATURE_NO_TITLE);
33.
34. setContentView(R.layout.image_show);
35. setTitle("ImageShowActivity");
36.
37. mSwitcher = (ImageSwitcher) findViewById(R.id.ImageSwitcher01);
38. // 系统的anim中的fade_in.xml
39. mSwitcher.setFactory(this);
40. mSwitcher.setInAnimation(AnimationUtils.loadAnimation(this,
41. android.R.anim.fade_in));
42. mSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this,
43. android.R.anim.fade_out));
44.
45. Gallery g = (Gallery) findViewById(R.id.gallery);
46. // 为缩略图浏览器指定一个适配器
47. g.setAdapter(new ImageAdapter(this));
48. // 响应 在缩略图列表上选中某个缩略图后的 事件
49. g.setOnItemSelectedListener(this);
50.
51. }
52.
53. @SuppressWarnings("unchecked")
54. public void onItemSelected(AdapterView parent, View v, int position, long id) {
55. mSwitcher.setImageResource(mImageIds[position]);
56. }
57.
58. @SuppressWarnings("unchecked")
59. public void onNothingSelected(AdapterView parent) {
60. }
61.
62. @Override
63. public View makeView() {
64. ImageView i = new ImageView(this);
65. i.setBackgroundColor(0xFF000000);
66. i.setScaleType(ImageView.ScaleType.FIT_CENTER);
67. i.setLayoutParams(new ImageSwitcher.LayoutParams(
68. LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
69. return i;
70. }
71.
72. public class ImageAdapter extends BaseAdapter {
73. private Context mContext;
74.
75. public ImageAdapter(Context c) {
76. mContext = c;
77. }
78.
79. public int getCount() {
80. return mThumbIds.length;
81. }
82.
83. public Object getItem(int position) {
84. return position;
85. }
86.
87. public long getItemId(int position) {
88. return position;
89. }
90.
91. //getView方法动态生成一个ImageView,然后利用setLayoutParams、setImageResource、
92. //setBackgroundResource分别设定图片大小、图片源文件和图片背景。当图片被显示到当前
93. //屏幕的时候,这个函数就会被自动回调来提供要显示的ImageView
94. public View getView(int position, View convertView, ViewGroup parent) {
95. ImageView i = new ImageView(mContext);
96.
97. i.setImageResource(mThumbIds[position]);
98. i.setAdjustViewBounds(true);
99. i.setLayoutParams(new Gallery.LayoutParams(
100. LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
101. i.setBackgroundResource(R.drawable.picture_frame);
102. return i;
103. }
104.
105. }
106.
107. }
5.AndroidManifest.xml 标识MainActivity为一个程序的开始
Java代码
1. <?xml version="1.0" encoding="utf-8"?>
2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3. package="com.small.photos"
4. android:versionCode="1"
5. android:versionName="1.0">
6. <application android:label="@string/app_name">
7. <activity android:name=".ImageShowActivity"
8. android:label="@string/app_name">
9.
10. </activity>
11.
12. <activity android:name="MainActivity"><intent-filter><action android:name="android.intent.action.MAIN"></action>
13. <category android:name="android.intent.category.LAUNCHER"></category>
14. </intent-filter>
15. </activity>
16. </application>
17.
18.
19. </manifest>
基本上就是这些了,然后启动吧!
opengl es 雾
文章分类:移动开发
雾效果在某种场合很重要,想象你正在游戏中穿过城市的边缘,显然你并没有渲染场景中很远距的物体,因为代价很大。当然你不愿意突然出现的场景或物体。雾可以解决这个问题。 雾同样可以使场景更加逼真,例如一个山谷中的场景,往往会云气缭绕。 这一章依据第17章的代码。 程序代码: 雾可以指定一个颜色,我们创建一个灰色的颜色。 float fogColor[] = { 0.5f, 0.5f, 0.5f, 1.0f }; 雾又三种模式,下面列表给出: 模式 描述 GL_EXP 雾的最简单的一种模式. 物体并没有真正的存在雾中,仅仅是一种阴霾的效果。 GL_EXP2 比第一种模式高级. 比第一种逼真些,但远近距离效果不够真实。 GL_LINEAR 最逼真的一种模式. 模拟现实中的场景。 由上可以看出,GL_LINEAR是最好的一种效果,但并不意味着你要使用它。显然越好的效果,性能的损失就越大,根据你的需要选择哪种模式。 创建一个数组,保存雾的所有模式,用于即使切换。fogType指明当前使用的哪种模式。 float fogTypes[] = { GL_EXP, GL_EXP2, GL_LINEAR }; int fogType = 0;
设置雾的效果,需要使用glFogf或glFogfv函数。glFogf函数有两个参数,第一个是指定要修改的雾的属性标志,第二个是修改的值。 下表描述了雾的各种属性。 标记 浮点值 描述 GL_FOG_MODE GL_EXP, GL_EXP2 or GL_LINEAR 雾的效果模式. GL_FOG_DENSITY > 0.0f (default 1.0f) 雾的密度,值越大密度越高。 GL_FOG_START Any float (default 0.0f) 指定雾的近面距离,在此距离内不渲染. GL_FOG_END Any float (default 1.0f) 指定雾的远面距离,超过此距离不渲染. 了解了属性参数,下面设置雾的属性,初始化雾的模式为GL_EXP. bool init() { . . glFogf(GL_FOG_MODE, GL_EXP); //指定雾的颜色,灰色 glFogfv(GL_FOG_COLOR, fogColor); //雾的密度 glFogf(GL_FOG_DENSITY, 0.35f); //系统如何计算雾气,这里设置不关心 glHint(GL_FOG_HINT, GL_DONT_CARE); glFogf(GL_FOG_START, 1.0f); glFogf(GL_FOG_END, 5.0f); glEnable(GL_FOG); . . } void display() { . . glTranslatef(0.0f, 0.0f, -5.0f);
. . } menu函数中动态改变雾的模式。 case 3 : ++fogType %= 3; glFogf(GL_FOG_MODE, fogTypes[fogType]); break; 至此,雾已经加入到你的场景了,观察效果吧。
Opengl归纳
文章分类:移动开发
1.雾
Java代码
1. // fog opengles
2.
3. gl.glFogfv(GL10.GL_FOG_COLOR, fogColorBfr);
4. gl.glFogf(GL10.GL_FOG_DENSITY, 0.35f);
5. gl.glHint(GL10.GL_FOG_HINT, GL10.GL_DONT_CARE);
6. gl.glFogf(GL10.GL_FOG_START, 2.0f);
7. gl.glFogf(GL10.GL_FOG_END, 6.0f);
8. gl.glEnable(GL10.GL_FOG);
Java代码
1. glClearColor(0.5f,0.5f,0.5f,1.0f); // 设置背景的颜色为雾气的颜色
2. glFogi(GL_FOG_MODE, fogMode[fogfilter]); // 设置雾气的模式
3. glFogfv(GL_FOG_COLOR, fogColor); // 设置雾的颜色
4. glFogf(GL_FOG_DENSITY, 0.35f); // 设置雾的密度
5. glHint(GL_FOG_HINT, GL_DONT_CARE); // 设置系统如何计算雾气
6. glFogf(GL_FOG_START, 1.0f); // 雾气的开始位置
7. glFogf(GL_FOG_END, 5.0f); // 雾气的结束位置
8. glEnable(GL_FOG); // 使用雾气
2.混合 Blend
Java代码
1. gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
2. gl.glEnable(GL10.GL_BLEND);
3.纹理
Java代码
1. // create textures
2. gl.glEnable(GL10.GL_TEXTURE_2D);
3. texturesBuffer = IntBuffer.allocate(3);
4. gl.glGenTextures(3, texturesBuffer);
5.
6. // load bitmap
7. Bitmap texture = Utils.getTextureFromBitmapResource(context, R.drawable.glass);
8.
9. // setup texture 0
10. gl.glBindTexture(GL10.GL_TEXTURE_2D, texturesBuffer.get(0));
11. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);
12. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
13. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
14. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
15. GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, texture, 0);
16.
17. // setup texture 1
18. gl.glBindTexture(GL10.GL_TEXTURE_2D, texturesBuffer.get(1));
19. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
20. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
21. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
22. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
23. GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, texture, 0);
24.
25. // setup texture 2
26. gl.glBindTexture(GL10.GL_TEXTURE_2D, texturesBuffer.get(2));
27. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
28. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR_MIPMAP_NEAREST);
29. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
30. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
31. Utils.generateMipmapsForBoundTexture(texture);
32.
33. // free bitmap
34. texture.recycle();
定向光
文章分类:移动开发
这一节我们使用定向光,涉及漫射光的高级应用和镜面光源。 我们将展示镜面光的显示效果,使用红色的小球和照在小球上的光源。 程序代码: 第一步依然是定义属性值,这里我们要加上镜面光的属性值定义。 float lightAmbient[] = { 0.2f, 0.0f, 0.0f, 1.0f }; float lightDiffuse[] = { 0.5f, 0.0f, 0.0f, 1.0f }; float lightSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; 同样,定义材质对镜面光的反射值
float matAmbient[] = { 1.0f, 1.0f, 1.0f, 1.0f }; float matDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; float matSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; 因为是定向光,所以我们需要知道光的位置和方向,下面代码就是定义位置和方向, float lightPosition[] = { 2.0f, 2.0f, 3.0f, 0.0f }; float lightDirection[] = { -2.0f, -2.0f, -3.0f }; 下面启用第一个光源 void init() { glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); 设置材质属性 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matAmbient); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matSpecular); 另一个可以用glMaterialf 设置的属性是GL_SHININESS,它的值在0到128之间,它表明镜面光的焦距度,值越大镜面光焦距越多。 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.0f); 下一步设置光属性 glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient); glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular); 设置光源的位置和方向,使用glLightfv 函数,它的第二个参数可以指明设置的是位置还是方向。 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, lightDirection); 另一个有用的标记是GL_SPOT_CUTOFF,它指定光锥体的大小,想象一个火把远离你时所产生的火光锥体,1.2将产生2.4度大的光锥体,如果设置为180度,则发射的光会照到各个角落。 glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 1.2f); 我们要讨论的下一个标记是GL_SPOT_EXPONENT,它控制圆锥体内光强分布的指
数因子,值在0到128之间,值越大,锥体轴线部分的光越强。 glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 20.0f); glLightf 函数还有三个标记可以设置,是用来控制衰减方式的,分别是:GL_CONSTANT_ATTENUATION(1), GL_LINEAR_ATTENUATION(0),GL_QUADRATIC_ATTENUATION。即常数衰减,线性衰减和二次衰减。括号中的值是它的默认值。 衰减指的是光的强度逐渐减弱,就像你离火光越来越远一样。设置这些属性会导致程序大幅减慢。 display 函数余下部分不变。 glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepthf(1.0f); glEnable(GL_CULL_FACE); glShadeModel(GL_SMOOTH); } 我们简单的使用glutSolidSphere / ugSolidSpheref 来创建求面体,这个球面体由水平24栈和垂直24片组成,这样可以更多的体现光照细节。 也许你奇怪我们为什么没有指定球面的法线,令人高兴的是UG / GLUT|ES库中创建的形状物体,法线是自动生成的,均由库自动计算,这大大简化了我们的任务。 void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAtf( 0.0f, 0.0f, 4.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); glRotatef(xrot, 1.0f, 0.0f, 0.0f); glRotatef(yrot, 0.0f, 1.0f, 0.0f); ugSolidSpheref(1.0f, 24, 24);
glFlush(); glutSwapBuffers(); } 运行程序,会呈现一个红色的球,注意镜面光源在球的右上方,那么现在你可以把定向光加入自己的程序了。
opengl es 灯光
文章分类:移动开发
这一章将在你的程序中加入灯光,使场景看起来和真实场景一样。 灯光 opengl中灯光分为好几种,都可以加入到你的场景中。 Ambiend Light 环境光 环境光没有确切的来源方向,当环境光照射到物体时,光被反射到各个方向。 Diffuse Light 漫射光 漫射光不同于环境光,它来自某个方向,但和环境光一样,照射到物体时,会被反射到各个方向。 Specular Light 镜面光 镜面光和漫射光一样是有方向的,但它反射方向是一定的,而不像漫射光一样反射到各个方向。所以当镜面光照射到物体时,你会看到物体表面被照射的亮点。 Emissive Light 发射光 它来自于某一物体,该物体散发出大量的光,但不会被任何物体面反射。 为了更好的理解这几种光,我从网络上摘抄了一段定义: * 环境光——经过多次反射而来的光称为环境光,无法确定其最初的方向,但当特定的光源关闭后,它们将消失.
* 全局环境光——它们并非来自特定的光源,这些光经过了多次散射,已经无法确定其光源位于何处. * 散射光——来自同一方向,照射到物体表面后,将沿各个方向均匀反射,因此,无论从哪个方向观察,表面的亮度都相同. * 镜面反射光——来自特定方向,也被反射到特定方向.镜面反射度与之相关. * 材质发射光——用于模拟发光物体.在OpenGL光照模型中,表面的发射光增加了物体的亮度,它不受光源的影响,另外,发射光不会给整个场景中增加光线. 材质 你不光可以设置光的属性,而且还可以指定不同的面对光照作出的反应,这就要指定材质属性。 这就指定了一个面对光源反射多少。 法线 法线是一个向量垂直于(90度)某一特定面,就称这个向量是某个面的法线。法线可以用于光的计算。如果你想让画出的物体对光源产生影响,那么必须指定物体每个面的法线。下面将会说明。 另一个需要注意的一点是,法线要单位化,我们不会深入数学计算,这不是我们这章的目的。如果需要会在将来某章中讲解。简明的说,一个向量的长度等于各个向量分量的平方和的平方根,再把每个向量的分量除以这个值。现在不需要过多担心这个。 程序代码: 下面定义两个颜色数组,一个用于环境光,一个用于漫射光,它们是光源的颜色值。 float lightAmbient[] = { 0.2f, 0.3f, 0.6f, 1.0f }; float lightDiffuse[] = { 0.2f, 0.3f, 0.6f, 1.0f }; 下面创建一个材质属性数组,分别用于环境光和漫射光。 用材质属性值乘以光源值得出面的反射颜色值,下面的值将会导致面反射的光失去接收光的百分之四十。每个值表示特定颜色被反射的数量。 float matAmbient[] = { 0.6f, 0.6f, 0.6f, 1.0f }; float matDiffuse[] = { 0.6f, 0.6f, 0.6f, 1.0f }; void init() { 首先先启用光源,这样光才会在场景中起作用。 glEnable(GL_LIGHTING);
opengl最多允许8个光源,要使用某个光源,需要使用glEnable打开它,光源的编号是GL_LIGHTX,X的值是0---7。 指定材质属性,可以使用glMaterialfv和glMaterialf ,glMaterialfv接受向量数组,而glMaterialf只接受一个向量。第一个参数指定那个面被更新,在opengl es中只可以使用GL_FRONT_AND_BACK,其他参数不起作用。之所以存在这个参数,是因为opengl可以设置多个参数。 第二个参数指定光源的类型,GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_EMISSION 和 GL_AMBIENT_AND_DIFFUSE. 最后一个参数指定一个数组或单个值,取决于你使用的哪个函数。 下一行设置面的材质属性: glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matAmbient); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiffuse); 灯光的设置和材质的设置相同,使用glLightfv或glLightf函数: glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient); glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse); init函数没有发生改变: glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepthf(1.0f); glVertexPointer(3, GL_FLOAT, 0, box); glEnableClientState(GL_VERTEX_ARRAY); glEnable(GL_CULL_FACE); glShadeModel(GL_SMOOTH); } display函数的开头部分没有发生改变: void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAtf( 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glRotatef(xrot, 1.0f, 0.0f, 0.0f); glRotatef(yrot, 0.0f, 1.0f, 0.0f); 前面我们讨论了法线,法线是垂直于面的,所以前平面的法线是(0, 0, 1),后平面的法线是(0, 0, -1),两个法线的长度为1,所以不用再单位化。 法线由glNormal3f 函数指定,并在渲染时调用。这个函数由3个float类型的数据组成单位化的向量。 // FRONT AND BACK glColor4f(1.0f, 0.0f, 0.0f, 1.0f); glNormal3f(0.0f, 0.0f, 1.0f); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glNormal3f(0.0f, 0.0f, -1.0f); glDrawArrays(GL_TRIANGLE_STRIP, 4, 4); 其他页面设置也同上, // LEFT AND RIGHT glColor4f(0.0f, 1.0f, 0.0f, 1.0f); glNormal3f(-1.0f, 0.0f, 0.0f); glDrawArrays(GL_TRIANGLE_STRIP, 8, 4); glNormal3f(1.0f, 0.0f, 0.0f); glDrawArrays(GL_TRIANGLE_STRIP, 12, 4); // TOP AND BOTTOM glColor4f(0.0f, 0.0f, 1.0f, 1.0f); glNormal3f(0.0f, 1.0f, 0.0f); glDrawArrays(GL_TRIANGLE_STRIP, 16, 4); glNormal3f(0.0f, -1.0f, 0.0f); glDrawArrays(GL_TRIANGLE_STRIP, 20, 4); glFlush(); glutSwapBuffers(); } 最后菜单增加一项彩色材质,这项选择打开或关闭色彩跟踪。色彩跟踪根据当前面的色彩反色不同色的光。 case 2 : if (glIsEnabled(GL_COLOR_MATERIAL)) glDisable(GL_COLOR_MATERIAL); else glEnable(GL_COLOR_MATERIAL); break;
下面两张图是程序的运行结果,分别是普通灯光和色彩追踪的效果。 普通灯光 色彩跟踪
opengl es 色彩混合
文章分类:移动开发
色彩混合对于效果有很大作用,通过它,可以实现物体透明,例如玻璃、水、窗户等等。 alpha是混合的基础,前面说过,色彩是由RGBA表示的,A就代表alpha,我们可以简单理解为透明度。A值为0代表完全透明,1代表不透明,指定A的值0到1之间可以调整色彩的透明度。 当使用混合时,始终要记住两个不同的颜色,一个是源色彩(用来参加运算),一个是目标色彩(已经存在于缓冲区)。混合就是进行两个色彩的运算。 程序代码: 这章使用正交视图 glOrthof(0.0f, 3.0f, 0.0f, 3.0f, -1.0f, 1.0f);
然后重叠几个矩形放在屏幕上,顶点数组下面给出: GLfloat rectangle[] = { -1.0f, -0.25f, 1.0f, -0.25f, -1.0f, 0.25f, 1.0f, 0.25f }; 下面将显示色彩的不同混合方式,下面的变量用来控制混合方式。 int currBlend = 4; init函数首先选择清除缓冲区的颜色,并且不使用深度值。 void init() { glClearColor(0.25f, 0.25f, 0.25f, 1.0f); 然后启用混合功能,传递GL_BLEND参数给glEnable函数。 glEnable(GL_BLEND); glBlendFunc函数用于指定颜色如何混合,有两个参数,它们指定颜色运算方式,有下面几种方式: GL_ZERO GL_ONE GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_DST_COLOR GL_ONE_MINUS_DST_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA GL_DST_ALPHA GL_ONE_MINUS_DST_ALPHA 第一个参数也可以指定为GL_SRC_ALPHA_SATURATE。 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 下面的数组用于切换不同的混合操作。 GLenum blendSrc[] = {
GL_ONE, GL_ONE, GL_ONE, GL_SRC_ALPHA, GL_SRC_ALPHA }; GLenum blendDst[] = { GL_ZERO, GL_ONE, GL_ONE_MINUS_DST_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA }; display函数放置4个矩形在屏幕上 void display() { glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); glVertexPointer(2, GL_FLOAT, 0, rectangle); glEnableClientState(GL_VERTEX_ARRAY); glPushMatrix(); glTranslatef(1.5f, 2.0f, 0.0f); glColor4f(1.0f, 0.0f, 0.0f, 0.5f); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glPopMatrix(); glPushMatrix(); glTranslatef(0.7f, 1.5f, 0.0f); glRotatef(90.0f, 0.0f ,0.0f, 1.0f); glColor4f(0.0f, 1.0f, 0.0f, 0.5f); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glPopMatrix(); glPushMatrix(); glTranslatef(1.7f, 1.5f, 0.0f); glRotatef(90.0f, 0.0f ,0.0f, 1.0f); glColor4f(0.0f, 0.0f, 1.0f, 0.25f); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glPopMatrix(); glPushMatrix(); glTranslatef(1.5f, 1.0f, 0.0f); glColor4f(1.0f, 1.0f, 0.0f, 0.75f); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glPopMatrix(); glFlush(); glutSwapBuffers(); } menu函数中选择不同的混合处理。 case 2 : ++currBlend %= 5; glBlendFunc(blendSrc[currBlend], blendDst[currBlend]); glutPostRedisplay(); break; 运行程序,你可以使用'b'键改变混合方式。 默认混合方式为( GL_ONE, GL_ZERO ),这种方式意味着目标色不起作用,仅仅用源色覆盖目标色,效果如下:
第二种方式为( GL_ONE, GL_ONE ),
第三种方式为(GL_ONE, GL_ONE_MINUS_DST_ALPHA)
第四种方式为(GL_SRC_ALPHA, GL_ONE)
(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
opengl es 灯光 | Opengl-ES 方法
Android 图片倒影
文章分类:移动开发
public static Bitmap createReflectedImage(Bitmap originalImage) { // The gap we want between the reflection and the original image final int reflectionGap = 4; int width = originalImage.getWidth(); int height = originalImage.getHeight(); // This will not scale but will flip on the Y axis Matrix matrix = new Matrix(); matrix.preScale(1, -1); // Create a Bitmap with the flip matrix applied to it. // We only want the bottom half of the image Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height / 2, width, height / 2, matrix, false); // Create a new bitmap with same width but taller to fit reflection Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height / 2), Config.ARGB_8888); // Create a new Canvas with the bitmap that's big enough for // the image plus gap plus reflection Canvas canvas = new Canvas(bitmapWithReflection); // Draw in the original image
canvas.drawBitmap(originalImage, 0, 0, null); // Draw in the gap Paint defaultPaint = new Paint(); canvas.drawRect(0, height, width, height + reflectionGap, defaultPaint); // Draw in the reflection canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null); // Create a shader that is a linear gradient that covers the reflection Paint paint = new Paint(); LinearGradient shader = new LinearGradient(0, originalImage.getHeight(), 0, bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP); // Set the paint to use this shader (linear gradient) paint.setShader(shader); // Set the Transfer mode to be porter duff and destination in paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN)); // Draw a rectangle using the paint with our linear gradient canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + reflectionGap, paint); return bitmapWithReflection;
}
画面
文章分类:移动开发
Android系统开机动画包括两部分: 开机显示的 ANDROID 文字; ANDROID发光动画。 这篇文章说的开机动画是第一种,下面开始正文!
1. 制作当前屏幕像素的图片(模拟器默认为320*480) 使用PS制作一张320*480的图片,保存时选“保存为 Web 所用格式”,然后在弹开的窗口上,“预设”项选择“PNG-24”,保存为android_logo.png 注:好像只支持png-24,其他格式生成的rle文件显示不正常,有兴趣大家可以再验证一下。
2. 将图片转换为raw格式 使用linux下的ImageMagick自带的convert命令,进行raw格式转换,命令为:
convert -depth 8 android_logo.png rgb:android_logo.raw 注:ubuntu 10.04 默认已经安装ImgageMagick工具,如果当前系统没有安装,可以执行下面的命令安装: sudo apt-get install imagemagick
3. 将raw格式转化为rle文件 需要用到android编译后的rgb2565工具,在android/out/host/linux-x86/bin目录下(android为当前源码所在目录),转换命令如下: rgb2565 -rle < android_logo.raw > initlogo.rle 到目前为止,启动需要显示的图像已经做好了,就是initlogo.rle,注意文件名必须是这个,如果想改文件名,需要修改android/system/core/init/init.h中的宏: #define INIT_IMAGE_FILE "/initlogo.rle" ============================================================================================
下面需要将initlogo.rle加入的android文件系统中 4. 找到ramdisk.img文件(android/out/target/product/generic/ramdisk.img),将文件名改为ramdisk.img.gz,然后使用下面的命令解压: gunzip ramdisk.img.gz 解压后得到ramdisk.img,可能有人要问,怎么文件名又改回去了?其实不然,使用file ramdisk.img查看一下就知道了: 解压前:ramdisk.img: gzip compressed data, from Unix 解压后:ramdisk.img: ASCII cpio archive (SVR4 with no CRC) 跑题了,还是说正事儿。
5. 使用cpio提取文件: 新建一个temp目录: mkdir temp cd temp cpio -i -F ../ramdisk.img
6. 导出文件列表: cpio -i -t -F ../ramdisk.img > list 注:list是一个文本文件,里面存储了ramdisk.img的文件结构,我们需要在这个文件中加入initlogo.rle这一行,修改后的文件如下: data default.prop dev init init.goldfish.rc init.rc initlogo.rle proc
sbin sbin/adbd sys system
7. 生成ramdisk.img cpio -o -H newc -O ramdisk.img < list 注:根据list文件的描述,生成ramdisk.img文件
8. 用ramdisk.img覆盖sdk目录下的ramdisk.img(android-sdk-windows/platforms/android-2.1/images/ramdisk.img),最好先备份一下。
9. 启动模拟器,就可以看到我们自己做的的开机界面了。 ///////////////////////// 开机图片设置 的下载地址为:http://docs.google.com/leaf?id=0 ... TIzOGQ5OWQ3&amp;hl=en
init 文件下载地址 http://docs.google.com/leaf?id=0 ... 2RiYjZjNjM2&amp;hl=en
split_bootimg.pl 下载地址:http://android-dls.com/files/linux/split_bootimg.zip
T卡文件下载地址:http://docs.google.com/leaf?id=0 ... GVjYzVhMjg4&amp;hl=en
开机图片设置 软件原理: 根据android 系统 开机LOGO和开机动画的存放路径:/initlogo.rle 和 /data/local/bootanimation.zip 在init.rc 中 建立两个链接: /initlogo.rle ->/data/data/com.android.e139.gallery/initlogo.rle 和 /data/local/bootanimation.zip ->/data/data/com.android.e139.gallery/bootanimation.zip 来完成开机LOGO和开机动画的动态设定
安装要求:
1.本apk文件只能安装在android 2.1 或 2.0的操作系统 中 2.必须修改android 根目录下面的两个文件:init.rc 和 init 功能才能实现设置开机LOGO和开机动画的功能
修改init.rc 和 init 的方法:
1.修改 init.rc 和init文件需要修改手机中的 boot.img 导出方法: cat /dev/mtd/mtd2 > /sdcard/root.img
然后
adb pull /sdcard/root.img ./
这样就把root.img拷贝到本地目录下了。
boot.img的组成结构是
+—————–+ | boot header | 1 page +—————–+ | kernel | n pages +—————–+ | ramdisk | m pages +—————–+ | second stage | o pages +—————–+
那我们要做的就是把这几个部分分别分离出来
我们现在先进行镜像分离。用命令
./split_bootimg.pl boot.img
成功执行后,可以得到两个文件,一个是boot.img-kernel,另一个是boot.img-ramdisk.gz。我们这里以修改ramdisk为例,所以将其解包
mkdir ramdisk
cd ramdisk
gzip -dc ../boot.img-ramdisk.gz | cpio -i
cd ..
2.进入ramdisk 修改init.rc 在init.rc 中增加:
on logo-init
mkdir /data 0775 system system
# We chown/chmod /data again so because mount is run as root + defaults mount yaffs2 mtd@userdata /data nosuid nodev chown system system /data #for other user can read this dir chmod 0775 /data
symlink /data/data/com.android.e139.gallery/initlogo.rle /initlogo.rle
on early-boot # copy file symlink /data/data/com.android.e139.gallery/bootanimation.zip /data/local/bootanimation.zip chmod 0666 /data/local/bootanimation.zip
再将已经下载的init文件覆盖到目录下面的init文件 3.生成新img 回到ramdisk 的上一级目录后执行: mkbootfs ./ramdisk | gzip > ramdisk-new.gz mkbootimg --cmdline 'no_console_suspend=1 console=null' --kernel boot.img-kernel --ramdisk ramdisk-new.gz -o boot-new.img 就会重新生成 boot-new.img 3.刷入新img
生成了新的img后,我们如何在系统上应用我们的新boot.img呢?首先,把img文件放到sdcard上去
adb push ./boot_new.img /sdcard
然后执行这两个操作
cat /dev/zero > /dev/mtd/mtd2 flash_image boot /sdcard/mynewimage.img
执行第一个操作时,可能会提示你
write: No space left on device
这个信息没关系,不用管它。两个命令都执行后,最后adb shell reboot即可。如果重启顺利,那么恭喜你,你刷成功了.
安装步骤: 1.按上面的步骤修改手机中的init.rc 和init文件
2.把下载的T卡文件放到T卡中 3.安装 开机图片设置.apk文件
修改boot.img的方法参考:http://www.kunli.info/2009/09/14/how-to-modify-ramdisk-android/ 和 http://android-dls.com/wiki/index.php?title=HOWTO:_Unpack,_Edit,_and_Re-Pack_Boot_Images
3D桌面效果动画类
文章分类:移动开发
Java代码
1. public class CubeAnimation extends Animation implements
2. Animation.AnimationListener {
3. public static final int FACE_LEFT = 0;
4. public static final int FACE_RIGHT = 1;
5. private int mInd;
6. private float mFromDegrees;
7. private float mToDegrees;
8. private float mCenterX;
9. private float mCenterY;
10. private int mHorizonType = 1;
11. private float mHorizonValue = 0.5F;
12. private Camera mCamera;
13. private View mView;
14.
15. public CubeAnimation(int ind) {
16. this.mInd = ind;
17. this.mFromDegrees = 0.0F;
18. this.mToDegrees = 90.0F;
19. }
20.
21. public CubeAnimation(Context context, AttributeSet attrs) {
22. super(context, attrs);
23. TypedArray a = context.obtainStyledAttributes(attrs,
24. R.styleable.CubeAnimation);
25.
26. this.mFromDegrees = 0.0F;
27. this.mToDegrees = 90.0F;
28.
29. Description d = Description.parseValue(a.peekValue(0));
30. this.mHorizonType = d.type;
31. this.mHorizonValue = d.value;
32.
33. this.mInd = a.getInt(1, 0);
34.
35. boolean t = a.getBoolean(2, true);
36. if (!(t)) {
37. this.mInd = (1 - this.mInd);
38. this.mToDegrees = 0.0F;
39. this.mFromDegrees = 90.0F;
40. }
41. a.recycle();
42. }
43.
44. public void onAnimationStart(Animation anim) {
45. this.mView.setVisibility(View.VISIBLE);
46. }
47.
48. public void onAnimationEnd(Animation anim) {
49. this.mView.setVisibility((this.mInd == 0) ? 0 : 8);
50. this.mInd = (1 - this.mInd);
51. }
52.
53. public void onAnimationRepeat(Animation anim) {
54. }
55.
56. public static void startCubeAnimation(Context context, int id, View view1,
57. View view2) {
58. XmlPullParser parser;
59. try {
60. parser = context.getResources().getAnimation(id);
61. AttributeSet attrs = Xml.asAttributeSet(parser);
62.
63. int type = parser.getEventType();
64. int depth = parser.getDepth();
65. while (true) {
66. while (true) {
67. if ((((type = parser.next()) == 3) && (parser.getDepth() <= depth))
68. || (type == 1))
69. break label172;
70. if (type == 2)
71. break;
72. }
73.
74. String name = parser.getName();
75.
76. if (name.equals("cube")) {
77. CubeAnimation anim1 = new CubeAnimation(context, attrs);
78. anim1.mInd = 1;
79. anim1.mView = view1;
80. anim1.setAnimationListener(anim1);
81. CubeAnimation anim2 = new CubeAnimation(context, attrs);
82. anim2.mInd = 0;
83. anim2.mView = view2;
84. anim2.setAnimationListener(anim2);
85. view1.startAnimation(anim1);
86. label172: view2.startAnimation(anim2);
87. }
88. }
89. } catch (Resources.NotFoundException ex) {
90. Log.e("CubeAnimation", "NotFoundException");
91. } catch (XmlPullParserException ex) {
92. Log.e("CubeAnimation", "XmlPullParserException");
93. } catch (IOException ex) {
94. Log.e("CubeAnimation", "IOException");
95. }
96. }
97.
98. public void initialize(int width, int height, int parentWidth,
99. int parentHeight) {
100. super.initialize(width, height, parentWidth, parentHeight);
101. this.mCenterX = resolveSize(1, 0.5F, width, parentWidth);
102. this.mCenterY = resolveSize(1, 0.5F, height, parentHeight);
103. if (this.mHorizonType == 0) {
104. this.mHorizonValue /= height;
105. }
106.
107. this.mCamera = new Camera();
108. }
109.
110. protected void applyTransformation(float interpolatedTime, Transformation t) {
111. float fromDegrees = this.mFromDegrees;
112. float degrees = fromDegrees + (this.mToDegrees - fromDegrees)
113. * interpolatedTime;
114.
115. float centerX = this.mCenterX;
116. float centerY = this.mCenterY;
117. Camera camera = this.mCamera;
118.
119. Matrix matrix = t.getMatrix();
120.
121. camera.save();
122.
123. float b = 0.0F;
124. float e = -this.mHorizonValue;
125.
126. if (this.mInd == 0) {
127. degrees += 90.0F;
128. }
129.
130. camera.rotateY(degrees);
131.
132. camera.getMatrix(matrix);
133. camera.restore();
134.
135. if (this.mInd == 0) {
136. matrix.preScale(-1.0F, 1.0F, centerX, 0.0F);
137. }
138.
139. float tranX = 320.0F * interpolatedTime;
140.
141. float tranY = -centerY * e + b;
142. matrix.preTranslate(0.0F, centerY * e);
143. matrix.postTranslate(tranX, tranY);
144. }
145.
146. protected static class Description {
147. public int type;
148. public float value;
149.
150. static Description parseValue(TypedValue value) {
151. Description d = new Description();
152. if (value == null) {
153. d.type = 0;
154. d.value = 0.0F;
155. } else {
156. if (value.type == 6) {
157. d.type = (((value.data & 0xF) == 1) ? 2 : 1);
158.
159. d.value = TypedValue.complexToFloat(value.data);
160. return d;
161. }
162. if (value.type == 4) {
163. d.type = 0;
164. d.value = value.getFloat();
165. return d;
166. }
167. if ((value.type >= 16) && (value.type <= 31)) {
168. d.type = 0;
169. d.value = value.data;
170. return d;
171. }
172. }
173.
174. d.type = 0;
175. d.value = 0.0F;
176.
177. return d;
178. }
179. }
180. }
31
菱形3D实例
文章分类:移动开发
下面是具体的实现方法: 首先需要建两个array,第一array是用来告诉opengl这个图形有哪些顶点: 画一个三维的坐标轴,然后把你要画的点都算出来,然后放在这个array里。
Java代码
1. float l=1.5f;
2. float[] vertex={
3.
4. 0.0f,l,0.0f,
5.
6. l,0.0f,0.0f,
7.
8. 0.0f,0.0f,l,
9.
10. -l,0.0f,0.0f,
11.
12. 0.0f,0.0f,-l,
13.
14. 0.0f,-l,0.0f
15.
16. };
第二个array是告诉opengl 你要怎样组织这些点: 这里我要画三角形,所以每三个点是一组。
Java代码
1. byte[] edge=
2. {
3. 0,1,2,
4. 1,2,5,
5.
6. 0,2,3,
7. 5,2,3,
8.
9. 0,3,4,
10. 5,3,4,
11.
12. 0,4,1,
13. 5,4,1
14.
15. };
这里的数字,是第一个array的index。 下面你要建立两个Buffer它们是用来存放这两个array的。
Java代码
1. ByteBuffer bb = ByteBuffer.allocateDirect(vertex.length*4);
2. bb.order(ByteOrder.nativeOrder());
3. fbv=bb.asFloatBuffer();
4. fbv.put(vertex);
5. fbv.position(0);
6.
7. ffe=ByteBuffer.allocateDirect(edge.length);
8. ffe.put(edge);
9. ffe.position(0);
这样一个三维的菱形就画好了。
下面你要写一个方法能让它自己把自己画出来!
Java代码
1. public void draw(GL10 gl)
2. {
3. gl.glFrontFace(GL10.GL_CW);
4. gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fbv);
5. gl.glDrawElements(GL10.GL_TRIANGLES, 24, GL10.GL_UNSIGNED_BYTE, ffe);
6.
7. }
先说第一个glFrontFace,物体都有一个正面一个反面,这里告诉opengl显示这个物体按顺时针方向(CW=> clockwise) gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fbv);这个方法是把本程序所用的点都传递个opengl。opengl需要知道什么哪?首先是 这个点是几维的(opengl 支持2,3,4 维),这里是3所以是三维的,第二个参数告诉opengl,这个点是用什么样类型的变量来储存的,这里是float类型。第三个是步长(stride),这个我还没弄明白,不过我看的例子都为0. 最后把你建立好的三维坐标点都传给opengl gl.glDrawElements。 这个方法是告诉opengl如果要画这个图形,应该怎么画。第一个参数,告诉opengl 用画三角形(这样opengl就以三个点为一组),然后告诉opengl你要用到多少个点(注意这个点是在第二个array里的点数)。 第三个是告诉opengl这些点(其实是三维坐标点的reference)的类型。这里是unsigned byte。最后把你排列点的array 放进去! 第二个大的步骤是创建一个让这个三维坐标运行的环境(Renderer)。 这是一个interface类 首先,在onDrawFrame里,我们告诉本程序这个三维图形的行为: 在做任何事情之前,我们要清空所有以前内存里的东西,这个内存包括:Color 和Depth gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT); 然后告诉opengl你要用那个MatrixMode 这个就比较难解释了。 如果写程序 只要记住 GL_MODELVIEW 是管理图形的 缩放,移动,和转动就行了.(如果那个朋友想理解的更深一点,可以联系我,我可以把我的笔记发过去或者参考 http://glasnost.itcarlow.ie/~powerk/GeneralGraphicsNotes/projection/projection_viewing.html )。 gl.glTranslatef(0, 0, -3.0f); 这个方法告诉opengl把图形沿z轴迁移3个unit。这三个值分别是x,y,z轴。 gl.glRotatef(angle,0, 1, 0); 这个方法告诉我们以y为轴。 转angle个度数。注意这里的1和0是告诉沿着那个轴转,别的值应该没有意义。 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 还记得上边说的opengl分client side和service side吗。 这个是告诉opengl如果client side
调用draw什么的时候,这个vertex array是可用的。opengl有很多这样的可选项,所以需要告诉opengl,因为我们已经设置了vertex array(我们的第一个array),所以告诉opengl 它是可用的(如果不告诉,opengl会忽略)! trian.draw(gl); 这个方法是把图形画出来。 angle++; 为了达到动态的效果,我们让每一个frame 的angle,比上一个多一度。 当显示空间大小发生变化的时候,我们应该告诉opengl一下信息:
Java代码
1. public void onSurfaceChanged(GL10 gl, int width, int height)
2. {
3. gl.glViewport(0, 0, width, height);
4. gl.glMatrixMode(GL10.GL_PROJECTION);
5. gl.glLoadIdentity();
6. float ratio = (float)width/height;
7. gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
8.
9. }
首先是opengl可用的空间 : gl.glViewport(0, 0, width, height); 想象一下用这四个点画出来的四边形,就是opengl所能用的空间。 gl.glMatrixMode(GL10.GL_PROJECTION); 这个matrix是如何把三维坐标转换为二维坐标并把它放在显示器上。 gl.glLoadIdentity 是告诉opengl初始化这个matrix。 gl.glFrustumf 要把三维的东西用二维显示出来,需要知道几个东西,第一是这个显示平面有多大,你可以看多近和多远。这里的头四个参数,建立了一个四边形,告诉opengl把图形显示在这个范围了。后两个参数告诉opengl这里显示平面里可以显示三维空间里最近和最远的位置。 当这个三维图形建立的是时候,我们可以告诉opengl一些基本参数。这里把能省略的都省略了(其实什么都没有也可以运行!)
Java代码
1. public void onSurfaceCreated(GL10 gl, EGLConfig arg1)
2. {
3. gl.glEnable(GL10.GL_DEPTH_TEST);
4. gl.glClearColor(0,0, 0, 0);
5. }
gl.glEnable(GL10.GL_DEPTH_TEST); 告诉opengl要检查depth,为什么哪。在三维空间里一个物体A在另一个物体B后面,那么这个A被B挡住里,所以你是看不见的。我们要告诉opengl,我们不想看见被挡住的东西。这个GL_DEPTH_TEST 就是这个功能。 gl.glClearColor(0,0, 0, 0); 设置这个背景颜色为黑色,应为我们没有给我们的三维图形设置颜色(为了简单),它的初始化颜色是白色。 以下是源代码:
Java代码
1. package Beta.ThreeD;
2.
3. import java.nio.ByteBuffer;
4. import java.nio.ByteOrder;
5. import java.nio.FloatBuffer;
6.
7. import javax.microedition.khronos.opengles.GL10;
8.
9. public class TriangleShape
10. {
11.
12. private final float l=1.5f;
13.
14. private FloatBuffer fbv;
15.
16. private ByteBuffer ffe;
17.
18. public TriangleShape()
19.
20. {
21.
22. float[] vertex={
23.
24. 0.0f,l,0.0f,
25.
26. l,0.0f,0.0f,
27.
28. 0.0f,0.0f,l,
29.
30. -l,0.0f,0.0f,
31.
32. 0.0f,0.0f,-l,
33.
34. 0.0f,-l,0.0f
35.
36. };
37.
38.
39. byte[] edge=
40.
41. {
42.
43. 0,1,2,
44.
45. 1,2,5,
46.
47.
48.
49. 0,2,3,
50.
51. 5,2,3,
52.
53.
54.
55. 0,3,4,
56.
57. 5,3,4,
58.
59.
60.
61. 0,4,1,
62.
63. 5,4,1
64.
65. };
66.
67. ByteBuffer bb = ByteBuffer.allocateDirect(vertex.length*4);
68.
69. bb.order(ByteOrder.nativeOrder());
70.
71. fbv=bb.asFloatBuffer();
72.
73. fbv.put(vertex);
74.
75. fbv.position(0);
76.
77.
78.
79.
80. ffe=ByteBuffer.allocateDirect(edge.length);
81.
82. ffe.put(edge);
83.
84. ffe.position(0);
85.
86. }
87.
88. public void draw(GL10 gl)
89.
90. {
91.
92. gl.glFrontFace(GL10.GL_CW);
93.
94. gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fbv);
95.
96. gl.glDrawElements(GL10.GL_TRIANGLES, 24, GL10.GL_UNSIGNED_BYTE, ffe);
97.
98. }
99. }
100.
101.
102. package Beta.ThreeD;
103.
104. import javax.microedition.khronos.egl.EGLConfig;
105. import javax.microedition.khronos.opengles.GL10;
106.
107. import android.opengl.GLSurfaceView.Renderer;
108.
109. public class MySimpleRendered implements Renderer
110. {
111.
112. private int angle=50;
113.
114. private TriangleShape trian;
115.
116. public MySimpleRendered()
117.
118. {
119.
120. trian = new TriangleShape();
121.
122. }
123.
124. @Override
125.
126. public void onDrawFrame(GL10 gl)
127.
128. {
129.
130. // TODO Auto-generated method stub
131.
132. gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
133.
134. gl.glMatrixMode(GL10.GL_MODELVIEW);
135.
136. gl.glLoadIdentity();
137.
138. gl.glTranslatef(0, 0, -3.0f);
139.
140. gl.glRotatef(angle,0, 1, 0);
141.
142. gl.glRotatef(angle, 1, 0, 0);
143.
144. gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
145.
146. trian.draw(gl);
147.
148. angle++;
149.
150. }
151.
152.
153. @Override
154.
155. public void onSurfaceChanged(GL10 gl, int width, int height)
156.
157. {
158.
159. // TODO Auto-generated method stub
160.
161. gl.glViewport(0, 0, width, height);
162.
163. gl.glMatrixMode(GL10.GL_PROJECTION);
164.
165. gl.glLoadIdentity();
166.
167. float ratio = (float)width/height;
168.
169. gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
170.
171.
172.
173. }
174.
175.
176. @Override
177.
178. public void onSurfaceCreated(GL10 gl, EGLConfig arg1)
179.
180. {
181.
182. gl.glEnable(GL10.GL_DEPTH_TEST);
183.
184. gl.glClearColor(0,0, 0, 0);
185.
186. }
187.
188. }
189. package Beta.ThreeD;
190.
191. import android.app.Activity;
192. import android.os.Bundle;
193. import android.opengl.GLSurfaceView;
194. public class Triangle extends Activity {
195. /** Called when the activity is first created. */
196.
197. private GLSurfaceView my_view;
198. @Override
199. public void onCreate(Bundle savedInstanceState) {
200. super.onCreate(savedInstanceState);
201. setContentView(R.layout.main);
202. my_view = new GLSurfaceView(this);
203. my_view.setRenderer(new MySimpleRendered());
204. this.setContentView(my_view);
205. }
206. public void onResume()
207. {
208.
209. super.onResume();
210.
211. my_view.onResume();
212. }
213. public void onPause()
214. {
215.
216. super.onPause();
217.
218. my_view.onPause();
219. }
220. }
镜像倒影特效Gallery
文章分类:移动开发
效果展示
本文档将介绍在android上如何实现一个倒影效果的Gallery。
为了达到上图所示的效果,
首先,是需要有一个自定义的gallery,实现了对Gallery的继承,通过重写getChildStaticTransformation方法来控制,每个子view有不同的缩放比例,形成阶梯状的展示。这个gallery是在坤庭的代码基础上实现的,我这里就不再重复介绍。
接下来,gallery中的每个view,都是一个自定义的MirrorView,由它来实现了画原图及画倒影。新的算法解决了性能问题,下面就重点说一下这部分内容:
镜像特效最近还蛮流行的,尤其在HTC 的Sense 介面上,常常都可以见到。大家可以看到,加了个镜像特效后,那感觉就很立体,感觉上好像是这些图片摆立在一个玻璃桌面上。
在Android 上要帮图片加上镜像特效,会不会很麻烦?一点也不麻烦,只要几行代码,就可以搞定。
因此,在开始看答案之前,我会建议你要先有Photoshop 的使用经验。想想,如果用Photoshop 要帮图片加上镜像特效,要如何做?我想一般不外乎是先复制个图片,并将其垂直翻转,接着再对这翻转的图片,加个由灰到黑的渐层mask 即可。
好了,让我们来看一下答案。底下就是帮图片加上镜像特效的程式范例。
Java代码
1. public class MirrorView extends View {
2.
3. Paint m_paint;
4.
5. int m_nShadowH;
6.
7. Drawable m_dw;
8.
9. Bitmap m_bitmap;
10.
11. Matrix mMatrix;
12.
13. int shadowHeight;
14.
15. public MirrorView(Context context, Bitmap bitmap) {
16.
17. super (context);
18.
19. m_bitmap = bitmap;
20.
21. _Init();
22.
23. }
24.
25. private void _Init() {
26.
27. //m_dw = new BitmapDrawable(BitmapFactory.decodeResource(getResources(), R.drawable.icon));
28.
29. m_dw = new BitmapDrawable(m_bitmap);
30.
31. m_dw.setBounds(0,0,m_dw.getIntrinsicWidth(),m_dw.getIntrinsicHeight());
32.
33. m_nShadowH = m_dw.getIntrinsicHeight()/1;
34.
35. m_paint = new Paint(Paint.ANTI_ALIAS_FLAG );
36.
37. LinearGradient lg = new LinearGradient(0, 0, 0, m_nShadowH, 0xB0FFFFFF, 0×00000000, Shader.TileMode.CLAMP );
38.
39. m_paint.setShader(lg);
40.
41. m_paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY ));
42.
43. mMatrix = new Matrix();
44.
45. }
46.
47. @Override
48.
49. public void onDraw(Canvas canvas) {
50.
51. super .onDraw(canvas);
52.
53. int nX = 0;
54.
55. int nY = 0;
56.
57. _DrawNormalImg(canvas, nX, nY);
58.
59. _DrawMirror(canvas, nX, nY);
60.
61. }
62.
63. private void _DrawNormalImg(Canvas canvas, int nX, int nY) {
64.
65. canvas.save(Canvas.MATRIX_SAVE_FLAG );
66.
67. canvas.translate(nX, nY);
68.
69. m_dw.draw(canvas);
70.
71. canvas.restore();
72.
73. }
74.
75. private void _DrawMirror(Canvas canvas, int nX, int nY) {
76.
77. int nW = m_dw.getIntrinsicWidth();
78.
79. int nH = m_dw.getIntrinsicHeight();
80.
81. shadowHeight=nH/2;
82.
83. float [] src={0, nH, nW, nH, nW,nH – m_nShadowH, 0, nH – m_nShadowH};
84.
85. float [] dst={ 0, nH, nW, nH,nW, shadowHeight, 0, shadowHeight };
86.
87. canvas.save();
88.
89. mMatrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1);
90.
91. canvas.concat(mMatrix);
92.
93. //draw mirror image
94.
95. canvas.save(Canvas.MATRIX_SAVE_FLAG );
96.
97. canvas.scale(1.0f, -1.0f);
98.
99. canvas.translate(nX, -(nY + nH * 2));
100.
101. canvas.clipRect(0, nH, nW, nH – m_nShadowH);
102.
103. m_dw.draw(canvas);
104.
105. canvas.restore();
106.
107. //draw mask
108.
109. canvas.save();
110.
111. canvas.translate(nX, nY + nH);
112.
113. canvas.drawRect(0, 0, nW, m_nShadowH, m_paint);
114.
115. canvas.restore();
116.
117. canvas.restore();
118.
119. }
120.
121. }
_DrawMirror() 方法是关键。用Photoshop 要如何做出镜像特效?第一步是先画出垂直翻转的图片。
Android 绘图座标体系预设的原点在左上角,X 轴往右是越来越大的正值,而Y 轴往下,则是越来越大的正值。要画出垂直翻转的图片,其实也就是要垂直翻转整个绘图座标体系。在 Android 中,要如何做?答案就是 canvas.scale(1.0f, -1.0f)。很简单吧,没想到给scale() 函式一个负值,就可以翻转相对应的轴。
在Photoshop 中,做镜像特效的第二步是要对这翻转的图片,加个由灰到黑的渐层mask。
在Android 中,要画渐层色,那就一定得用LinearGradient 这个类别。至于要对背景图加上个mask,就请参考一下Paint 的setXfermode() 函式。 _Init() 这个函式,就是负责生成一个由灰到黑渐层mask 的m_paint 物件。
这个控件我测试过,200张图片加入adapter,在大数据量情况下性能也没有问题。
Gallery3D各个界面可见范围计算方法
文章分类:移动开发
computeVisibleRange算法分析: 第1步,计算出left,right,bottom,top 第2步,计算出numSlots,并除于2赋值给index 第3步,由index得position,判断position是否在第1步计算出的范围内,是的话,就把第2步计算得出的中间的index赋值给 firstVisibleSlotIndex,lastVisibleSlotIndex,否则,根据滑动窗口算法改变index直到求组所需index 第4步,在while循环中,用第3步得到的firstVisibleSlotIndex求出position,进行和第2步相反的判断,即 position若不在可视范围内,则将相应的index给firstVisibleSlotIndex,否则减 firstVisibleSlotIndex,直到找到最小的可视范围内的index作为firstVisibleSlotIndex。 第5步,在while循环中,用第3步得到的lastVisibleSlotIndex求出position,进行和第2步相反的判断,即 position若不在可视范围内,则将相应的index给lastVisibleSlotIndex,否则增 lastVisibleSlotIndex,直到找到可视范围内的最大的index作为lastVisibleSlotIndex。 第6步,进行firstVisibleSlotIndex,lastVisibleSlotIndex的越界判断。 outBufferedVisibleRange对应的是可见的。outBufferedVisibleRange对应的是0~文件夹的最大数。 computeVisibleItems算法分析: 第1步 由slot计算出position,set,当前set不为空且slot在有效范围,创建bestItems,计算sortedIntersection 第2步 计算这个slotindex中的图片数目,取这个文件中的前12张图片加到bestItems. 第3步 取bestItems里的图片对应的displayList中的displayItem,并赋值给displayItems数组,同时保存 position,及j,j是bestItems数组中一项,范围是0~12。 第四步 对于每一个文件夹,要在displayItems里有对应的12项,当文件夹内图片不足12时,余下的用null填充。 当绘制缩略图界面时,有些不同 在第1步中,slotindex不再表示文件夹,这时表示具体某一张图片了,所以由slot得到的set里始终只有1项,且会调 ArrayUtils.computeSortedIntersection(visibleItems, items, MAX_ITEMS_PER_SLOT, bestItems, sTempHash);给bestItems赋值,这样第2步就在bestItems加项动作不执行。
Gallery3D中画图时调用glTranslate函数参数赋值过程
文章分类:移动开发
GridDrawManager::drawDisplayItem(RenderView view, GL11 gl, DisplayItem displayItem, Texture texture, int pass,Texture previousTexture, float mixRatio) 函数有下面几句:
Java代码
1. Vector3f animatedPosition = displayItem.mAnimatedPosition;
2. float translateXf = animatedPosition.x * camera.mOneByScale;
3. float translateYf = animatedPosition.y * camera.mOneByScale;
4. float translateZf = -animatedPosition.z;
调用过程: ->computeVisibleItems(),displayItems[baseIndex + j] = displayItem;Vector3f position =
pool.create(); GridCameraManager.getSlotPositionForSlotIndex(i, camera, layout, deltaAnchorPosition, position);//give position value displayList.setPositionAndStackIndex(displayItem, position, j, true);//raletive position to item ->GridLayer, mDrawManager = new GridDrawManager(context, mCamera, mDrawables, sDisplayList, sDisplayItems, sDisplaySlots); ->GridDrawManager(), mDisplayItems = displayItems; ->drawFocusItems ,DisplayItem[] displayItems = mDisplayItems; ->animatedPosition = displayItem.mAnimatedPosition; ->drawDisplayItem, amAnimatedPosition ->DisplayItem::commit() amAnimatedPosition.set(mTargetPosition); -> DisplayItem::set(Vector3f position, int stackIndex, boolean performTransition) mTargetPosition.z =
Java代码
1. public void getPositionForSlotIndex(int slotIndex, int itemWidth, int itemHeight, Vector3f outPosition) {
2. outPosition.x = (slotIndex / mNumRows) * (itemWidth + mSpacingX);
3. outPosition.y = (slotIndex % mNumRows) * (itemHeight + mSpacingY);
4. int maxY = (mNumRows - 1) * (itemHeight + mSpacingY);
5. outPosition.y -= (maxY >> 1);
6. outPosition.z = 0;
7. Log.d("outPosition","slotIndex="+slotIndex+",mNumRows="+mNumRows+",outPosition=("+outPosition.x+","+outPosition.y+","+outPosition.z+")");
8. }
在gallery3d中矩阵是从上到下、从左到右排列的,在主界面时最多有3行,mNumRows=3,在缩略图界面最多4行mNumRows=4,在查看界面只有一行mNumRows=1 上面函数是计算所绘制项位置的,slotIndex / mNumRows得到的是当前处于多少列,slotIndex % mNumRows得到的是处于多少行。 int maxY = (mNumRows - 1) * (itemHeight + mSpacingY); outPosition.y -= (maxY >> 1);是为了在y方向对称,想成屏幕中间是分界线,以上的项y为负,线以下的y为正。 deltaAnchorPosition的赋值过程:
Java代码
1. int currentlyVisibleSlotIndex = getAnchorSlotIndex(ANCHOR_CENTER);->anchorItem = displayItem.mItemRef;-> newSlotIndex = i;->if (currentAnchorSlotIndex != Shared.INVALID && newAnchorSlotIndex != Shared.INVALID) {
2. layout.getPositionForSlotIndex(newAnchorSlotIndex, itemWidth, itemHeight, deltaAnchorPosition);
3. oldLayout.getPositionForSlotIndex(currentAnchorSlotIndex, itemWidth, itemHeight, currentSlotPosition);
4. currentSlotPosition.subtract(sDeltaAnchorPosition);
5. deltaAnchorPosition.subtract(currentSlotPosition);
6. deltaAnchorPosition.y = 0;
7. deltaAnchorPosition.z = 0;
8. }
MediaFeed::run() onFeedChanged(, onLayout(newSlotIndex, currentlyVisibleSlotIndex, null); onLayout, sDeltaAnchorPositionUncommited.set(deltaAnchorPosition); computeVisibleRange(),sDeltaAnchorPosition.set(sDeltaAnchorPositionUncommited); deltaAnchorPosition.set(sDeltaAnchorPosition); deltaAnchorPosition
Gallery3D笔记
文章分类:移动开发
布局及特效 gallery3d 的精华 一、布局 gallery3d的界面生成和普通的应用程序不一样。普通程序一般一个界面就是一个activity,布局用xml或代码都可以实现,界面切换是activity的切换方式;而gallery3d没有用android的UI系统,而是用opengl画出来的,即界面是在同一个 activity的,如主界面,缩略图界面,单张图片查看界面,标记界面等都属于同一个activity。那么这界面布局不同的界面是如何组合到一起的呢?分析代码,可以把它看成一个状态机: 1、标记模式 public static final int MODE_SELECT = 1;(HudLayer) 包含了主界面标记模式,缩略界面矩阵游览时标记模式、缩略图界面分类游览时标记模式3个界面 2、普通模式 public static final int MODE_NORMAL = 0;(HudLayer) 包含了
Java代码
1. public static final int STATE_MEDIA_SETS = 0;主界面
2. public static final int STATE_GRID_VIEW = 1;缩略图矩阵浏览
3. public static final int STATE_FULL_SCREEN = 2;查看界面
4. public static final int STATE_TIMELINE = 3;缩略图界面分类浏览
有了以上状态分类后,在渲染的时候就能根据些界面的组成来定哪些控件譔隐藏,哪些要显示了。 下面是基本控件:
Java代码
1. com.cooliris.media.GridLayer
2. com.cooliris.media.BackgroundLayer
3. com.cooliris.media.HudLayer
4. com.cooliris.media.ImageButton
5. com.cooliris.media.TimeBar
6. com.cooliris.media.MenuBar
7. com.cooliris.media.PopupMenu
8. com.cooliris.media.PathBarLayer
在渲染时,每一帧所有界面上的元素都画了,由于根据上面的状态只把特定窗口的特定元素显示出来,其它窗口中的隐藏,所以不会乱。 Layer是上面控件的基类,上面控件的类也就有了下面两个方法来隐藏不譔显示的界面元素。
Java代码
1. public boolean isHidden() {
2. return mHidden;
3. }
4.
5. public void setHidden(boolean hidden) {
6. if (mHidden != hidden) {
7. mHidden = hidden;
8. onHiddenChanged();
9. }
10. }
下面是根据上面分类来画不同元素所用的标识:
Java代码
1. public static final int PASS_THUMBNAIL_CONTENT = 0;
2. public static final int PASS_FOCUS_CONTENT = 1;
3. public static final int PASS_FRAME = 2;
4. public static final int PASS_PLACEHOLDER = 3;
5. public static final int PASS_FRAME_PLACEHOLDER = 4;
6. public static final int PASS_TEXT_LABEL = 5;
7. public static final int PASS_SELECTION_LABEL = 6;
8. public static final int PASS_VIDEO_LABEL = 7;
9. public static final int PASS_LOCATION_LABEL = 8;
10. public static final int PASS_MEDIASET_SOURCE_LABEL = 9;
Java代码
1. drawDisplayItem(view, gl, displayItem, texture, PASS_THUMBNAIL_CONTENT, placeholder,displayItem.mAnimatedPlaceholderFade); 画缩略图的,注掉此句,前两屏只显示框,第三屏OK
2. drawDisplayItem(view, gl, displayItem, texture, PASS_FOCUS_CONTENT, null, 0.0f);画单张图片的,注掉,第三屏黑屏
3. drawDisplayItem(view, gl, itemDrawn, textureToUse, PASS_FRAME, previousTexture, ratio);画边框的,注掉,前两屏明显没有边框,巨齿明显
4. drawDisplayItem(view, gl, displayItem, textureString, PASS_TEXT_LABEL, null, 0);画文本标签的
5. drawDisplayItem(view, gl, displayItem, textureToUse, PASS_SELECTION_LABEL, null, 0);画选中标记的
6. drawDisplayItem(view, gl, displayItem, videoTexture, PASS_VIDEO_LABEL, null, 0);画视频标记的
7. drawDisplayItem(view, gl, displayItem, locationTexture, PASS_LOCATION_LABEL, null, 0);画位置标记的
8. drawDisplayItem(view, gl, displayItem, locationTexture, PASS_MEDIASET_SOURCE_LABEL,transparentTexture, 0.85f);画源来源图标的(相机或一般文件夹)
二、特效 举如何显示一张图片为例,在图片完全显示出来经过这样一个过程,附近的图片渐小渐出,当前图片渐大渐入,当前图片逐渐变大直到全屏。实现这个特效,要进行很多帧的渲染。就是说并不是只调一次onDrawFrame函数就可以了,要调用多次。可以把这个特效的实现想成一个状态变化的过程,在每一个状态,纹理的显示大小和位置都不同,这也符合动画的基本原理。放大、缩小我们只要改变顶点数据就可以做到,gallery3d也是这样做的,下面是主要代码: 我们知道调用onDrawFrame来渲染,最后调到下面的drawFocusItems函数,
Java代码
1. GridQuad quad = GridDrawables.sFullscreenGrid[vboIndex];
2. float u = texture.getNormalizedWidth();
3. float v = texture.getNormalizedHeight();
4. float imageWidth = texture.getWidth();
5. float imageHeight = texture.getHeight();
6. boolean portrait = ((theta / 90) % 2 == 1);
7. if (portrait) {
8. viewAspect = 1.0f / viewAspect;
9. }
10. quad.resizeQuad(viewAspect, u, v, imageWidth, imageHeight);//改变用来贴图片的长方形的大小
11. quad.bindArrays(gl);//绑定新数据,为渲染做准备。
而位置的改变有两种方式,一种是直接以顶点数据中改变,另一种是计算出在3维3个方向的偏移量,再调用gltranslate来做,从代码可以看出采用的是第二种方式来做的,比第一种方式更方便一些。代码:
Java代码
1. gl.glTranslatef(-translateXf, -translateYf, -translateZf);
而这里的3个偏移量的计算是和camera相关的,相关文件为GridCamera.java,GridCameraManager.java,过程很复杂,理清楚后再细化吧。 cache管理 下面是cache文件
Java代码
1. /sdcard/Android/data/com.cooliris.media/cache/local-album-cache
2. d---rwxr-x system sdcard_rw 2010-05-21 09:56 local-album-cache
3. d---rwxr-x system sdcard_rw 2010-05-21 09:56 local-meta-cache
4. ----rwxr-x system sdcard_rw 299877 2010-05-28 07:36 local-album-cachechunk_0
5. d---rwxr-x system sdcard_rw 2010-05-21 09:56 geocoder-cache
6. ----rwxr-x system sdcard_rw 284 2010-05-28 07:36 local-album-cacheindex
7. d---rwxr-x system sdcard_rw 2010-05-21 09:56 local-image-thumbs
8. d---rwxr-x system sdcard_rw 2010-05-21 09:56 local-video-thumbs
9. d---rwxr-x system sdcard_rw 2010-05-21 09:56 picasa-thumbs
10. ----rwxr-x system sdcard_rw 80 2010-05-28 07:36 local-meta-cachechunk_0
11. ----rwxr-x system sdcard_rw 164 2010-05-28 07:36 local-meta-cacheindex
12. d---rwxr-x system sdcard_rw 2010-05-21 09:56 hires-image-cache
13. ----rwxr-x system sdcard_rw 627629 2010-05-28 07:37 local-image-thumbschunk_0
14. ----rwxr-x system sdcard_rw 3914 2010-05-21 09:56 local-image-thumbsindex
15. ----rwxr-x system sdcard_rw 53343 2010-05-28 07:34 hires-image-cache-4982941342287215583_1024.cache
16. ----rwxr-x system sdcard_rw 237692 2010-05-28 07:33 hires-image-cache3684568484369117627_1024.cache
17. ----rwxr-x system sdcard_rw 133182 2010-05-28 07:34 hires-image-cache607542544081226432_1024.cache
18. ----rwxr-x system sdcard_rw 83223 2010-05-28 07:34 hires-image-cache4275479623210216146_1024.cache
19. ----rwxr-x system sdcard_rw 292837 2010-05-28 07:34 hires-image-cache-646316556936433937_1024.cache
20. ----rwxr-x system sdcard_rw 191377 2010-05-28 07:35 hires-image-cache2631364604509958174_1024.cache
21. ----rwxr-x system sdcard_rw 366905 2010-05-28 07:35 hires-image-cache-3280562009766080884_1024.cache
22. ----rwxr-x system sdcard_rw 323671 2010-05-28 07:35 hires-image-cache5752471827533329222_1024.cache
创建cache的关键代码
Java代码
1. LocalDataSource
2. public static final DiskCache sThumbnailCache = new DiskCache("local-image-thumbs");----------------------local-image-thumbs local-image-thumbschunk_0 local-image-thumbsindex
3. public static final DiskCache sThumbnailCacheVideo = new DiskCache("local-video-thumbs");--------------------local-video-thumbs
4. public static final DiskCache sAlbumCache = new DiskCache("local-album-cache");----------------------local-album-cache local-album-cacheindex
5. public static final DiskCache sMetaAlbumCache = new DiskCache("local-meta-cache");------------------local-meta-cache local-meta-cacheindex
6. getChunkFile --------------local-meta-cachechunk_0 local-album-cachechunk_0
7.
8. ReverseGeocoder:: private static final DiskCache sGeoCache = new DiskCache("geocoder-cache"); -------------------------geocoder-cache
9. PicasaDataSource:: public static final DiskCache sThumbnailCache = new DiskCache("picasa-thumbs");-----------------------------picasa-thumbs
10. UriTexture::writeToCache --------------------------hires-image-cache-xxx_1024.cache
布局补充: 在画一个界面是,是分类化的,比如第一个界面是显示所有有图片的文件夹,在代码里叫专辑.有这些元素要创建: 文本标签 显示专辑名和专辑内图片或视频数 路径条 显示路径名 按纽 拍照按纽,放大/缩小
菜单栏 全选,取消全选,分享,删除,更多等 图片边框 用于显示图片的矩形 在渲染时一次把一类元素画完,再画另一类.如主界面顺序为: 路径条->按纽->文本标签->图片边框->图片. 具体代码见drawBlendedComponents函数
1.CacheService.java 中写缓存: sAlbumCache.put(ALBUM_CACHE_LOCALE_INDEX, sDummyData, 0);
第一个是 key ,这里是正常数据,当然还有别的 key , key 分别是 -1,-2,-3,-4,-5 。
2.DiskCache.java 中,执行上面的写的过程,这里先得明白他的 cache 怎么装的:
它是由很多称之为“片”的文件组成的,形成一个 List 形式: private final
LongSparseArray<RandomAccessFile> mChunkFiles = new LongSparseArray<RandomAccessFile>();
即 mChuckFiles 就是整个 cache ,里面包括很多 chunk( 即片 ) ,每一个 chunk 大小为 1MB.
当要写入某一个 chunk 里面的时候,先要找到他在 mChuckFiles 里面的索引值即 chunkIndex, 由
mChunkFiles.get(chunkIndex); 来获取这个文件, chunkIndex 怎么来的呢?
private LongSparseArray<Record> mIndexMap;
Record record = mIndexMap.get(key); 这里的 key 就是上面用 put 方法传过来的
ALBUM_CACHE_LOCALE_INDEX 的值(就是 -5 )
int chunkIndex = record.chunk;
这么一步步来的。
当然了,第一次都是空的,也就是 get 不到东西 mChunkFiles.get(chunkIndex); 和 Record record =
mIndexMap.get(key); 都 get 不到,那么第一次就先把东西放进去, mIndexMap.put(key, new Record
(chunkIndex, record.offset, data.length, record.sizeOnDisk, timestamp)); (记录 key 值)以及 final
String chunkFilePath = mCacheDirectoryPath + CHUNK_FILE_PREFIX + chunk; chunkFile = new
RandomAccessFile(chunkFilePath, "rw");mChunkFiles.put(chunk, chunkFile); (三句代码来新建一个
chunkfile 并放到 cache 列表里面)
注意: Record 是内部类,只是一个数据集合类而已,相当于文件描述信息。每个 cache (即 chunk )对应一个。
private final LongSparseArray<RandomAccessFile> mChunkFiles = new LongSparseArray<RandomAccessFile>(); 中 mChunkFiles 最大装 13 个,每个 chunk 是 1M, 所以全部 Cache 是 13M.
Gallery3d 代码分析之渲染流程
文章分类:移动开发
RenderView gallery3d 的渲染从 RenderView 开始。RenderView 从 GLSurfaceView 继承而来,采用了通知型绘制模式,即通过调用 requestRender 通知 RenderView 重绘屏幕。 RenderView 将所有需要绘制的对象都保存一个 Lists中,Lists 包含了5个ArrayList,其定义如下所示:
Java代码
1. public final ArrayList<Layer> updateList = new ArrayList<Layer>();
2. public final ArrayList<Layer> opaqueList = new ArrayList<Layer>();
3. public final ArrayList<Layer> blendedList = new ArrayList<Layer>();
4. public final ArrayList<Layer> hitTestList = new ArrayList<Layer>();
5. public final ArrayList<Layer> systemList = new ArrayList<Layer>();
RenderView 的 onDrawFrame 接口完成每一帧的绘制操作,绘制时遍历 lists 里每个 list 的每一个成员并调用其 renderXXX 函数。主要代码如下所示:
Java代码
1. ...
2. final Lists lists = sLists;
3.
4. final ArrayList<Layer> updateList = lists.updateList;
5. boolean isDirty = false;
6. for (int i = 0, size = updateList.size(); i != size; ++i) {
7. boolean retVal = updateList.get(i).update(this, mFrameInterval);
8. isDirty |= retVal;
9. }
10. if (isDirty) {
11. requestRender();
12. }
13.
14. // Clear the depth buffer.
15. gl.glClear(GL11.GL_DEPTH_BUFFER_BIT);
16. gl.glEnable(GL11.GL_SCISSOR_TEST);
17. gl.glScissor(0, 0, getWidth(), getHeight());
18.
19. // Run the opaque pass.
20. gl.glDisable(GL11.GL_BLEND);
21. final ArrayList<Layer> opaqueList = lists.opaqueList;
22. for (int i = opaqueList.size() - 1; i >= 0; --i) {
23. final Layer layer = opaqueList.get(i);
24. if (!layer.mHidden) {
25. layer.renderOpaque(this, gl);
26. }
27. }
28.
29. // Run the blended pass.
30. gl.glEnable(GL11.GL_BLEND);
31. final ArrayList<Layer> blendedList = lists.blendedList;
32. for (int i = 0, size = blendedList.size(); i != size; ++i) {
33. final Layer layer = blendedList.get(i);
34. if (!layer.mHidden) {
35. layer.renderBlended(this, gl);
36. }
37. }
38. gl.glDisable(GL11.GL_BLEND);
lists 的各个 list 里包含的各个 layer 如下所示:
Java代码
1. lists
2. |------------------|-----------------|-----------------|---------------|
3. updateList opaqueList blendedList systemList hitTestList
4. | | | | |
5. GridLayer GridLayer GridLayer GridLayer GridLayer
6. BackgroudLayer BackgroudLayer BackgroudLayer
7. HudLayer HudLayer HudLayer HudLayer
8. TimeBar TimeBar TimeBar
9. PathBar PathBar PathBar
10. XXXButton XXXButton XXXButton
11. XXXMenu XXXMenu XXXMenu
Layer 类提供了 update(...), renderOpaque (...), renderBlended (...) 接口,从上面 RenderView 的 onDrawFrame 绘制代码可以看到,这些接口被调用。
Java代码
1. public abstract class Layer {
2. ... ...
3.
4. public abstract void generate(RenderView view, RenderView.Lists lists);
5.
6. public boolean update(RenderView view, float frameInterval) {
7. return false;
8. }
9.
10. public void renderOpaque(RenderView view, GL11 gl) {
11. }
12.
13. public void renderBlended(RenderView view, GL11 gl) {
14. }
15. ... ...
16.
17. }
GridLayer GridLayer 中有个 GridDrawManager,专门负责绘制。 下面是 GridDrawManager 的构造函数,从其参数里可以看出些门道。
Java代码
1. mDrawManager = new GridDrawManager(context, mCamera, mDrawables, sDisplayList, sDisplayItems, sDisplaySlots);
Gallery 3D 代码分析之 GLSurfaceView
文章分类:移动开发
简介 SDK 中的 android.opengl.GLSurfaceView 类提供如下功能:
 在 OpenGL ES 和 View 系统之间建立联系;
 使得 OpenGL ES 可以工作在 Activity 生命周期中;
 可选择合适的 frame buffer 像素格式;
 创建并管理一个单独的渲染线程,可以实现平滑的动画;
 提供 debugging 工具和 API。
一个简单的 GLSurfaceView 应用
Java代码
1. package com.example.android.apis.graphics;
2.
3. import javax.microedition.khronos.egl.EGLConfig;
4. import javax.microedition.khronos.opengles.GL10;
5.
6. import android.app.Activity;
7. import android.opengl.GLSurfaceView;
8. import android.os.Bundle;
9.
10. public class ClearActivity extends Activity {
11. @Override
12. protected void onCreate(Bundle savedInstanceState) {
13. super.onCreate(savedInstanceState);
14. mGLView = new GLSurfaceView(this);
15. mGLView.setRenderer(new ClearRenderer());
16. setContentView(mGLView);
17. }
18.
19. @Override
20. protected void onPause() {
21. super.onPause();
22. mGLView.onPause();
23. }
24.
25. @Override
26. protected void onResume() {
27. super.onResume();
28. mGLView.onResume();
29. }
30.
31. private GLSurfaceView mGLView;
32. }
33.
34. class ClearRenderer implements GLSurfaceView.Renderer {
35. public void onSurfaceCreated(GL10 gl, EGLConfig config) {
36. // Do nothing special.
37. }
38.
39. public void onSurfaceChanged(GL10 gl, int w, int h) {
40. gl.glViewport(0, 0, w, h);
41. }
42.
43. public void onDrawFrame(GL10 gl) {
44. gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
45. }
46. }
这个程序功能很简单,每帧绘制时将屏幕设置成黑色。但它是一个完整的工作在 Activity 生命周期中的 OpenGL 程序。当 activity 暂停时,它暂停渲染;当 activity 继续时,它继续渲染。可以将这个程序用作非交互式的 demo 程序。可以在 ClearRenderer.onDrawFrame() 接口中增加 OpenGL 调用做很多的绘制。 GLSurfaceView.Render 接口有三个方法: * onSurfaceCreated():该方法在渲染开始前调用,OpenGL ES 的绘制上下文被重建时也会被调用。当 activity 暂停时绘制上下文会丢失,当 activity 继续时,绘制上下文会被重建。另外,创建长期存在的 OpenGL 资源(如 texture)往往也在这里进行。 * onSurfaceChanged():当 surface 的尺寸发生改变时该方法被调用。往往在这里设置 viewport。若你的 camera 是固定的,也可以在这里设置 camera。 * onDrawFrame():每帧都通过该方法进行绘制。绘制时通常先调用 glClear 函数来清空 framebuffer,然后在调用 OpenGL ES 的起它的接口进行绘制。 输入如何处理 若是开发一个交互型的应用(如游戏),通常需要子类化 GLSurfaceView,由此可以获取输入事件。下面有个例子:
Java代码
1. package com.google.android.ClearTest;
2.
3. import javax.microedition.khronos.egl.EGLConfig;
4. import javax.microedition.khronos.opengles.GL10;
5.
6. import android.app.Activity;
7. import android.content.Context;
8. import android.opengl.GLSurfaceView;
9. import android.os.Bundle;
10. import android.view.MotionEvent;
11.
12. public class ClearActivity extends Activity {
13. @Override
14. protected void onCreate(Bundle savedInstanceState) {
15. super.onCreate(savedInstanceState);
16. mGLView = new ClearGLSurfaceView(this);
17. setContentView(mGLView);
18. }
19.
20. @Override
21. protected void onPause() {
22. super.onPause();
23. mGLView.onPause();
24. }
25.
26. @Override
27. protected void onResume() {
28. super.onResume();
29. mGLView.onResume();
30. }
31.
32. private GLSurfaceView mGLView;
33. }
34.
35. class ClearGLSurfaceView extends GLSurfaceView {
36. public ClearGLSurfaceView(Context context) {
37. super(context);
38. mRenderer = new ClearRenderer();
39. setRenderer(mRenderer);
40. }
41.
42. public boolean onTouchEvent(final MotionEvent event) {
43. queueEvent(new Runnable(){
44. public void run() {
45. mRenderer.setColor(event.getX() / getWidth(),
46. event.getY() / getHeight(), 1.0f);
47. }});
48. return true;
49. }
50.
51. ClearRenderer mRenderer;
52. }
53.
54. class ClearRenderer implements GLSurfaceView.Renderer {
55. public void onSurfaceCreated(GL10 gl, EGLConfig config) {
56. // Do nothing special.
57. }
58.
59. public void onSurfaceChanged(GL10 gl, int w, int h) {
60. gl.glViewport(0, 0, w, h);
61. }
62.
63. public void onDrawFrame(GL10 gl) {
64. gl.glClearColor(mRed, mGreen, mBlue, 1.0f);
65. gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
66. }
67.
68. public void setColor(float r, float g, float b) {
69. mRed = r;
70. mGreen = g;
71. mBlue = b;
72. }
73.
74. private float mRed;
75. private float mGreen;
76. private float mBlue;
77. }
其他的 GLSurfaceView 例子 在 Android SDK 的 API Demo例子程序中还有很多例子:
 GLSurfaceView
 Kube
 Translucent GLSurfaceView:透明背景
 Textured Triangle:纹理贴图
 Sprite Text:在 texture 上写文本并显示在 3D 场景中
 Touch Rotate:旋转 3D 对象
选择一个 Surface GLSurfaceView 提供了接口可选择 surface 的类型。默认情况下, GLSurfaceView 会使用一个 16 位 RGB frame buffer,带 16 位深度。你也可以根据自己的需要进行选择,比如在 Translucent GLSurfaceView 例子里,需要一个 Alpha 通道来实现透明。GLSurfaceView 提供了 setEGLSurfaceChooser()方法来选择 surface。 选择一个 RGB (565)的16位 framebuffer,接口如下:
Java代码
1. setEGLConfigChooser(boolean needDepth)
若要定制 red, green, blue, alpha 和 depth,则用如下接口:
Java代码
1. setEGLConfigChooser(int redSize, int greenSize,int blueSize, int alphaSize,int depthSize, int stencilSize)
使用自己实现的 EGLConfigChooser,用如下的接口:
Java代码
1. setEGLConfigChooser(EGLConfigChooser configChooser)
持续型渲染模式 & 通知型渲染模式 大多数 3D 应用,如游戏、模拟等都是持续型渲染的动画,还有些 3D 应用是反应式的(reactive),它们往往先被动等待,当用户有了动作再做出反应。对于这种应用,持续渲染屏幕是浪费时间。若开发反应式的应用,可以调用下面的方法
Java代码
1. GLSurfaceView.setRenderMode(RENDERMODE_WHEN_DIRTY);
停止持续渲染。当调用
Java代码
1. GLSurfaceView.requestRender()
时,程序再渲染屏幕。 调试 GLSurfaceView.setDebugFlags() 方法可以激活 log 或者错误检测,它们可以帮助调试 OpenGL ES 调用。具体使用时,在 GLSurfaceView 的构造函数中,调用 setRender() 之前调用 GLSurfaceView.setDebugFlags()就可以了。下面是个例子:
Java代码
1. public ClearGLSurfaceView(Context context) {
2. super(context);
3. // Turn on error-checking and logging
4. setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS);
5. mRenderer = new ClearRenderer();
6. setRenderer(mRenderer);
7. }

论坛徽章:
0
2 [报告]
发表于 2012-04-03 11:04 |只看该作者
我日,乱七八糟一大坨,你写给自己看的吧
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP