Android界面特殊全汇总
(一)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, fl
oat 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 和 SimpleCur
sorAdapter
其中以 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 管理,这样 C
ursor 的生命周期和 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"},
15 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 的每一节对应 ListVi
ew 的每一行。HashMap 的每个键值数据映射到布局文件中对应 id 的组件上。因为系统没
有对应的布局文件可用,我们可以自己定义一个布局 vlist.xml。下面做适配,new 一个 S
impleAdapter 参数一次是: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
12
2
holder.img.setBackgroundResource((Integer)mData.get(position).ge
t("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 在开始绘制的时候,系统首先调用 getC
ount()函数,根据他的返回值得到 listView 的长度(这也是为什么在开始的第一张图特
别的标出列表长度),然后根据这个长度,调用 getView()逐一绘制每一行。如果你的 g
etCount()返回值是 0 的话,列表将不显示同样 return 1,就只显示一行。
系统显示列表时,首先实例化一个适配器(这里将实例化自定义的适配器)。当手动完
成适配时,必须手动映射数据,这需要重写 getView()方法。系统在绘制列表的每一行
的时候将调用此方法。getView()有三个参数,position 表示将显示的是第几行,covert
View 是从布局文件中 inflate 来的布局。我们用 LayoutInflater 的方法将定义好的 vlist
2.xml 文件提取成 View 实例用来显示。然后将 xml 文件中的各个组件实例化(简单的 fi
ndViewById()方法)。这样便可以将数据对应到各个组件上了。但是按钮为了响应点击事
件,需要为它添加点击监听器,这样就能捕获点击事件。至此一个自定义的 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-resour
ces.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/androi
d”
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.sho
w)).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().ge
tDrawable(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.ge
tHeight());
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_defaul
t< /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_en
abled="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="t
rue"
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 s
etters
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 associat
e 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 DrawableContainerSt
ate {
68.private int[][] mStateSets;
69.
70.StateListState(StateListState orig, StateListDrawable owner, R
esources 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 #getDrawa
bleState()}
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 remov
ed, 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 backgr
ound, 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() == VISIB
LE, 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
信息:
l #RGB
l #ARGB
l #RRGGBB
l #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(s
tr);
9. style.setSpan(new ForegroundColorSpan(Color.RED),3,8,Spann
able.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.getExternalSto
rageState();
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.Environme
nt.getExternalStorageState();
6. 5
7. 6 if (sDcString.equals(android.os.Environme
nt.MEDIA_MOUNTED)) {
8. 7
9. 8 // 取得 sdcard 文件路径
10. 9 File pathFile = android.os.Envi
ronment
11.10 .getExternalStorage
Directory();
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.getBl
ockCount();
17.16
18.17 // 获取 SDCard 上每个 block 的
SIZE
19.18 long nBlocSize = statfs.getBlock
Size();
20.19
21.20 // 获取可供程序使用的 Block 的数
量
22.21 long nAvailaBlock = statfs.getAv
ailableBlocks();
23.22
24.23 // 获取剩下的所有 Block 的数量(包括
预留的一般程序无法使用的块)
25.24 long nFreeBlock = statfs.getFree
Blocks();
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/a
ndroid"
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_WEATH
ER");
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.clas
s));
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:autoL
ink
设置是否当文本为 URL 链接/email/电话号码/map 时,文本
显示为可点击的链接。可选值(none/web/email/phone/map/all)
android:autoT
ext
如果设置,将自动执行输入值的拼写纠正。此处无效果,在
显示输入法并输入的时候起作用。
android:buffe
rType
指定 getText()方式取得的文本类别。选项 editable 类似
于 StringBuilder 可追加字符,
也就是说 getText 后可调用 append 方法设置文本内容。
spannable 则可在给定的字符区域使用样式,参见这里 1 、这里
2 。
android:capit
alize
设置英文字母大写类型。此处无效果,需要弹出输入法才能
看得到,参见 EditText 此属性说明。
android:curso
rVisible
设定光标为显示/隐藏,默认显示。
android:digit
s
设置允许输入哪些字符。如“1234567890.+-*/%\n()”
android:drawa
bleBottom
在 text 的下方输出一个 drawable,如图片。如果指定一个
颜色的话会把 text 的背景设为该颜色,并且同时和 background
使用时覆盖后者。
android:drawa
bleLeft
在 text 的左边输出一个 drawable,如图片。
android:drawa
blePadding
设置 text 与 drawable(图片)的间隔,与 drawableLeft、
drawableRight、drawableTop、drawableBottom 一起使用,可设
置为负数,单独使用没有效果。
android:drawa
bleRight
在 text 的右边输出一个 drawable,如图片。
android:drawa
在 text 的正上方输出一个 drawable,如图片。
bleTop
android:edita
ble
设置是否可编辑。这里无效果,参见 EditView。
android:edito
rExtras
设置文本的额外的输入数据。在 EditView 再讨论。
android:ellip
size
设置当文字过长时,该控件该如何显示。有如下值设
置:”start”—–省略号显示在开头;”end”——省略号显示
在结尾;”middle”—-省略号显示在中间;”marquee” ——
以跑马灯 的方式显示(动画横向移动 )
android:freez
esText
设置保存文本的内容以及光标的位置。参见:这里 。
android:gravi
ty
设置文本位置,如设置成“center”,文本将居中显示。
android:hint
Text 为空时显示的文字提示信息,可通过 textColorHint
设置提示信息的颜色。此属性在 EditView 中使用,但是这里也
可以用。
android:imeOp
tions
附加功能,设置右下角 IME 动作与编辑框相关的动作,如
actionDone 右下角将显示一个“完成”,而不设置默认是一个回
车符号。这个在 EditText 中再详细说明,此处无用。
android:imeAc
tionId
设置 IME 动作 ID。在 EditText 再做说明,可以先看这篇帖
子:这里 。
android:imeAc
tionLabel
设置 IME 动作标签。在 EditText 再做说明。
android:inclu
deFontPadding
设置文本是否包含顶部和底部额外空白,默认为 true。
android:input
Method
为文本指定输入法,需要完全限定名(完整的包名)。例如:
com.google.android.inputmethod.pinyin,但是这里报错找不
到。
android:input
Type
设置文本的类型,用于帮助输入法显示合适的键盘类型。在
EditText 中再详细说明,这里无效果。
android:links
Clickable
设置链接是否点击连接,即使设置了 autoLink。
android:marqu
eeRepeatLimit
在ellipsize指定marquee的情况下,设置重复滚动的次数,
当设置为 marquee_forever 时表示无限次。
android:ems
设置 TextView 的宽度为 N 个字符的宽度。这里测试为一个
汉字字符宽度,如图:
android:maxEm
s
设置 TextView 的宽度为最长为 N 个字符的宽度。与 ems 同
时使用时覆盖 ems 选项。
android:minEm
s
设置 TextView 的宽度为最短为 N 个字符的宽度。与 ems 同
时使用时覆盖 ems 选项。
android:maxLe
ngth
限制显示的文本长度,超出部分不显示。
android:lines
设置文本的行数,设置两行就显示两行,即使第二行没有数
据。
android:maxLi
nes
设置文本的最大显示行数,与 width 或者 layout_width 结
合使用,超出部分自动换行,超出行数将不显示。
android:minLi
nes
设置文本的最小行数,与 lines 类似。
android:lineS
pacingExtra
设置行间距。
android:lineS
pacingMultipl
ier
设置行间距的倍数。如”1.2”
android:numer
ic
如果被设置,该 TextView 有一个数字输入法。此处无用,
设置后唯一效果是 TextView 有点击效果,此属性在 EditText 将
详细说明。
android:passw
ord
以小点”.”显示文本
android:phone
Number
设置为电话号码的输入方式。
android:priva
设置输入法选项,此处无用,在 EditText 将进一步讨论。
teImeOptions
android:scrol
lHorizontally
设置文本超出 TextView 的宽度的情况下,是否出现横拉条。
android:selec
tAllOnFocus
如果文本是可选择的,让他获取焦点而不是将光标移动为文
本的开始位置或者末尾位置。EditText 中设置后无效果。
android:shado
wColor
指定文本阴影的颜色,需要与 shadowRadius 一起使用。效
果:
android:shado
wDx
设置阴影横向坐标开始位置。
android:shado
wDy
设置阴影纵向坐标开始位置。
android:shado
wRadius
设置阴影的半径。设置为 0.1 就变成字体的颜色了,一般设
置为 3.0 的效果比较好。
android:singl
eLine
设置单行显示。如果和 layout_width 一起使用,当文本不
能全部显示时,后面用“„”来表示。如 android:text="test_
singleLine " android:singleLine="true"
android:layout_width="20dp"将只显示“t„”。如果不设置
singleLine 或者设置为 false,文本将自动换行
android:text
设置显示文本.
android:textA
ppearance
设置文字外观。如
“?android:attr/textAppearanceLargeInverse
”这里引用的是系统自带的一个外观,?表示系统是否有这
种外观,否则使用默认的外观。可设置的值如下:
textAppearanceButton/textAppearanceInverse/textAppearan
ceLarge
/textAppearanceLargeInverse/textAppearanceMedium/textAp
pearanceMediumInverse/textAppearanceSmall/textAppearanc
eSmallInverse
android:textC
olor
设置文本颜色
android:textC
olorHighlight
被选中文字的底色,默认为蓝色
android:textC
olorHint
设置提示信息文字的颜色,默认为灰色。与 hint 一起使用。
android:textC
olorLink
文字链接的颜色.
android:textS
caleX
设置文字之间间隔,默认为 1.0f。分别设置
0.5f/1.0f/1.5f/2.0f 效果如下:
android:textS
ize
设置文字大小,推荐度量单位”sp”,如”15sp”
android:textS
tyle
设置字形[bold(粗体) 0, italic(斜体) 1, bolditalic(又
粗又斜) 2] 可以设置一个或多个,用“|”隔开
android:typef
ace
设置文本字体,必须是以下常量值之一:normal 0, sans 1,
serif 2, monospace(等宽字体) 3]
android:heigh
t
设置文本区域的高度,支持度量单位:px(像
素)/dp/sp/in/mm(毫米)
android:maxHe
ight
设置文本区域的最大高度
android:minHe
ight
设置文本区域的最小高度
android:width
设置文本区域的宽度,支持度量单位:px(像
素)/dp/sp/in/mm(毫米),与 layout_width 的区别看这里 。
android:maxWi
dth
设置文本区域的最大宽度
android:minWi
dth
设置文本区域的最小宽度
1.3 补充说明
1.3.1 以下几个属性以及输入法相关的在这里都没有效果,在 EditText
将补充说明。
android:numeric/android:digits/android:phoneNumber/android:inputMetho
d/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").setConte
nt(R.id.textview2));
8. mTabHost.addTab(mTabHost.newTabSpec("tab_test3").setIndicator("TAB 3").setConte
nt(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/textColorPrim
ary"
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.OnGr
oupClickListener,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, mCent
erY);
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.sim
ple_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.getMen
uInfo();
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).sho
w();
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 isExpanded,
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/blacklistImageVi
ew"
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, mTransformatio
n);
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,ViewFactor
y{
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.glas
s);
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, GL1
0.GL_NEAREST);
12. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL1
0.GL_NEAREST);
13. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.G
L_CLAMP_TO_EDGE);
14. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.G
L_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, GL1
0.GL_LINEAR);
20. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL1
0.GL_LINEAR);
21. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.G
L_CLAMP_TO_EDGE);
22. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.G
L_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, GL1
0.GL_LINEAR);
28. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL1
0.GL_LINEAR_MIPMAP_NEAREST);
29. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.G
L_CLAMP_TO_EDGE);
30. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.G
L_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&hl=en
init 文件下载地址 http://docs.google.com/leaf?id=0 ...
2RiYjZjNjM2&hl=en
split_bootimg.pl 下载地址:
http://android-dls.com/files/linux/split_bootimg.zip
T 卡文件下载地址:http://docs.google.com/leaf?id=0 ...
GVjYzVhMjg4&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.draw
able.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+",outPosit
ion=("+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 = dis
playItem.mItemRef;-> newSlotIndex = i;->if (currentAnchorSlotIndex != Shared.INVALID &
& newAnchorSlotIndex != Shared.INVALID) {
2. layout.getPositionForSlotIndex(newAnchorSlotIndex, itemWidth, itemHeight, de
ltaAnchorPosition);
3. oldLayout.getPositionForSlotIndex(currentAnchorSlotIndex, itemWidth, itemHei
ght, 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, placeholde
r,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-4982941342
287215583_1024.cache
16. ----rwxr-x system sdcard_rw 237692 2010-05-28 07:33 hires-image-cache36845684843
69117627_1024.cache
17. ----rwxr-x system sdcard_rw 133182 2010-05-28 07:34 hires-image-cache60754254408
1226432_1024.cache
18. ----rwxr-x system sdcard_rw 83223 2010-05-28 07:34 hires-image-cache42754796232
10216146_1024.cache
19. ----rwxr-x system sdcard_rw 292837 2010-05-28 07:34 hires-image-cache-6463165569
36433937_1024.cache
20. ----rwxr-x system sdcard_rw 191377 2010-05-28 07:35 hires-image-cache26313646045
09958174_1024.cache
21. ----rwxr-x system sdcard_rw 366905 2010-05-28 07:35 hires-image-cache-3280562009
766080884_1024.cache
22. ----rwxr-x system sdcard_rw 323671 2010-05-28 07:35 hires-image-cache57524718275
33329222_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-thumbsind
ex
3. public static final DiskCache sThumbnailCacheVideo = new DiskCache("local-video-thum
bs");--------------------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("pica
sa-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, in
t 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. }