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.+-*/%
()」
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" 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) + "
");
}
@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: [email protected]
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: [email protected]
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. }
推薦閱讀:
