2010年11月18日 星期四

Android筆記_Activity切換頁面

我們的程式應該不太可能只由一個Activity就完成,所以就必須要學會Activity的相互切換,要達到頁面切換的方式有兩種:
1. 直接換原本Activity的layout
2. 利用intent.setClass,並執行這個intent來達成兩個Activity的切換
* 除了呼叫同一Package的Activity以外,也有可能呼叫不同Package的Activity。

所以開啟專案,來看看這三種狀況怎麼做!

先來看看專案的架構,因為要做三種狀況,所以總共開啟了3隻繼承Activity的Class,並將其中一隻放到不同的Package中;而在Layout方面則準備四個Layout。

所以要達成的功能是:
1. OlaTeach_Activity1擺上三顆按鈕,先使用main.xml Layout。
2. 第一顆鈕將OlaTeach_Activity1的Layout換成main2.xml。
3. 第二顆鈕將OlaTeach_Activity1轉到同Package的OlaTeach_Activity2。
4. 第四顆鈕將OlaTeach_Activity1轉到不同Package的OlaTeach_Activity3。
先來看主要的程式碼:

1. 利用findViewById將三顆按鈕抓到,並都去監聽OnClickListener事件。
2. 第一個按鈕利用setContentView(R.layout.main2);將layout轉到main2。
3. 第二個按鈕利用intent.setClass後,執行startActivity(intent),呼叫另一個Activity
4. 第二個按鈕也利用intent.setClass後,執行startActivity(intent),呼叫另一個Activity,但此處因需呼叫不同Package的Activity,所以setClass的參數有點點不一樣,必須要給包含Package的class全名。


最後來看一下AndroidManifest.xml的配置:

可以看出來,因為使用了三個Activity,所以檔案中有三個Activity的定義,需要注意的是,OlaTeach_Activity3為不同Package的Activity,所以android:name必須給全名,也就是android:name="ola.Package2.OlaTeach_Activity3",這樣才可以正常呼叫到。

註:第一種轉換頁面的方法,原本以為只是向CSS一樣套上另一個皮,裡面寫的方法應該都可以在變換Layout後使用,後來發現當換了Layout之後,必須重新再去取得按鈕物件,並加入OnClickListener才可以正常使用。

如果需要操作步驟,可以參考piggy的文章,寫的非常詳細!

26 則留言:

柳丁男孩 提到...

感激不盡!!! 很清楚明瞭 :D

馬上就實作成功 :DD 非常感謝您~

如果程式碼部份能改成直接變成類似coding的顯示方式(新增一個框架,裡面直接顯示code)會更好,不需要在點擊圖片才能放大 : )

(另外想問:你備註的地方不太懂意思。 不是只要按返回鍵一樣可以回到原來的view嗎?)

ola的家 提到...

恭喜你呀。 =)

我有時後貼code有時候貼圖啦,也忘記這篇為什麼沒貼code了。

備註的意思是:我原本以為setContentView只是像網頁的CSS一樣切換版面,而原本已經註冊的監聽事件都可以保留使用;但其實這樣想不太對,他是在原本的Activity上面置換layout,置換以後當然還是必須要重新設定監聽事件,也就是main切換到main2的layout後,要繼續在main2動作,就要註冊屬於他的事件。
(越寫越模糊 XD)

柳丁男孩 提到...

網站似乎沒辦法顯示,所以我把它改成()
麻煩若要複製的人不要忘記把()改回<>喔。

正確版
(activity android:name=".TabWidget")(/activity)
(activity android:name="WriteDiary")(/activity)


錯誤版
(activity android:name=".TabWidget")(/activity)
(activity android:name=".WriteDiary")(/activity)

ola的家 提到...

因為在manifest裡面已經定義了package為Ola.OlaTeach_Activity1,所以在指定activity的name屬性時,可以用".OlaTeach_Activity1"的簡寫表示"Ola.OlaTeach_Activity1.OlaTeach_Activity1"。

而如果是另一個package內的activity,就必須要重新由根目錄指進去,就跟網頁相對路徑的意思相同。

柳丁男孩 提到...

@@為啥我有時候回復的一些文章沒有發佈... 見鬼了!!

現在我遇到一個問題就是

我有一個class 繼承itemizedOverlay,當使用者點及地圖上的標籤時,就觸發這個類別中的onTap方法,我想在此class理實作兩個頁面的轉換,但由於這個類別不屬於Activity所以好像沒辦法在這個類別裡面使用是件轉換。

想問說有沒有辦法可以讓我的itemizedOverlay這個類別當中能時做兩個頁面的轉換。

ola的家 提到...

我不確定是不是可以在別的class操作Activity;但是我猜測你現在想做的事情是:地圖上有幾個itemizedOverlay產生的小圖(可能是景點),點擊以後讓畫面轉到相關的介紹頁面。如果是上面的功能,我不會把轉換頁面的動作寫在itemizedOverlay類別裡面,因為這樣未來的專案也沒辦法繼續使用該類別,而必須重新針對專案來寫一個itemizedOverlay類別;我是沒有去測試可不可以「itemizedOverlay這個類別當中能時做兩個頁面的轉換」,但是我建議Activity要做的動作還是留在自己java code比較好。

Dexter 提到...

Ola 您好 我是最近開始接觸Android的新手

寫到Intent傳值的部分 是不是有什麼方法

可以在一個Activity(1)把數值一次傳送兩個頁面

Activity(2),Activity(3)

或者是 透過Activity(1)傳送到Activity(2)接收完再

送給Activity(3) 謝謝您

ola的家 提到...

如果轉換Activity時要進行傳值,就要使用Bundle,而一個Bundle裡面可以放入很多種格式,程式碼:

//設定Bundle
Bundle bundle = new Bundle();
bundle.putByteArray("key_map_image", 要傳的陣列));
bundle.putString("key_show_String", 要傳的字串);
intent.putExtras(bundle);

以上就是一次傳遞一個名叫key_map_image的Array與叫做key_show_String的String,利用"intent.putExtras(bundle)"的方式放進intent裡面。

至於你說要一次傳送到兩個Activity,其實有一個很大的盲點,因為Activity就是要呈現在使用者面前的UI部分,我們理論上不會一次呈現出兩個Activity(應該也不能);

所以,應該會是你說的第二種狀況,由Activity1傳值到Activity2,然後因為別的需求又轉換並傳值到Activity3;如果是這個情況就可以以上面的程式碼進行傳值動作。

而在接值的部分可以使用:
Bundle bundle = this.getIntent().getExtras();

mapbyte = bundle.getByteArray("key_map_image");

OutPutString_facebook = bundle.getString("key_show_String");

不知道這樣有回答到你的問題嗎?

我也是新手啦 XD

Dexter 提到...

ola 您好

我了解您的意思了 謝謝你給我的觀念 受益良多

其實我原本想法是這樣

因為我有4個Activity 第一個是用來讓使用者key數值進去透過Button把數值傳送出去

之後下一個Activity是一個用上方為Textview下面用TabHost

把剩下兩個Activity組合起來的TabActivity

我想把第一個Activity(1)的數值傳送到Activity(2)Activity(3)去做處理

所以才會有這個想法...如果Bundle無法直接傳送 那我就只好再想看看了

感謝ola 啾咪...

匿名 提到...

請問一下~
為何當我寫上
Button btn0 = (Button) OlaTeach_Activity1.this.findViewById(R.id.btn_change0);
這行指令時,系統顯示紅色X 是因為我沒註冊setContentView事件嗎? 如果是的話又該如何註冊呢?

ola的家 提到...

單憑你的描述並沒有辦法確認錯誤原因,還是需要Eclipse所提供的錯誤訊息才能判斷;而沒有使用setContentView這個方法並不會造成撰寫程式時的錯誤,執行程式時才會產生相關錯誤。

提供你可能的錯誤方向作為參考:
1. 你的Activity的Class名稱可能非"OlaTeach_Activity1"
2. 你的xml檔案可能沒有名為"btn_change0"的按鈕ID

匿名 提到...

如板大正確的敘述 的確是沒有"btn_change0"的按鈕ID

所以是把原先預設第一個按鈕Button名稱改成btn_change0嗎?

-Daniel-

匿名 提到...

板大 依照你的指示後~ 我的程式碼已經修正完全 ^_^
也成功地能開啟專案,但是出現3個Button 我點擊依然無法變換? 這又是什麼問題呢˙_˙? 因為沒有程式碼任何地方有顯示X


-Daniel-

ola的家 提到...

ㄜ....這樣的敘述實在很難判斷問題所在。

所以,你要先確認"按鈕按下後,是否有執行轉換activity的程式碼(可以利用log方式)"

程式碼有'x'訊息代表語法有問題,但執行後沒顯示相對反應就是程式邏輯錯誤,所以你要先確認一下你的程式流程。

匿名 提到...

請問一下我出現這樣的錯誤
"Cannot make a static reference to the non-static method setClass(Context, Class) from the type Intent"
是哪出問題呢><?

ola的家 提到...

意思是...你在static的方法中呼叫了non-static的setClass,所以我猜你的Intent沒有new。

匿名 提到...

大大您好,我是一位新手,想請教大大我想用一個MENU點下後會跳出一張圖或者跳到別的頁面,需要用什麼方法呢~我是用SWITCH CASE~之後DIALOG顯示,但點下去都沒反應!

另外我使用INAGEBUTTON想點下去後,背景會有背景黑色提示那個按鈕點下去,那要如何作或設定呢?例如這個圖片
http://uploadingit.com/file/i8ojhgbxmobria7r/device-2011-11-03-162141.png

匿名 提到...

您好
我有依照上面程式碼
執行之後第1個按鈕可以成功的轉到另外一個頁面
但是第2個第3個按下去就跳出停止了
好像是程式碼沒對應到layout
不知道大大的程式碼還有留者嗎
可以給寄給我嗎m8716@hotmail.com
謝謝

匿名 提到...

大大您好,MENU已經解決了~跟大大所說的一樣,沒對到~哈哈
再請教大大,如何做才能讓IMAGE BUTTON按下去有反應那種,不像是貼一張圖那樣死死的(EX:手機或平板點一樣東西,那個東西背景會有顏色)那個是設定的~還是打程式的呢?

匿名 提到...

大大您好,我剛去找到這方法,我是用.png檔然後背景設為#00000000透明,按下去都沒被按下的感覺,因此用這方法"重繪",給大大您參考^^~謝謝大大幫我解決問題~^^

imageButton1.setOnTouchListener(new OnTouchListener(){

@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if(event.getAction()==MotionEvent.ACTION_DOWN){
imageButton1.getDrawable().setAlpha(150);//設圖片透明度0~255,0完全透明,255不透明
imageButton1.invalidate();
}
else {
imageButton1.getDrawable().setAlpha(255);//還原圖片
imageButton1.invalidate();//重繪圖片
}
return false;
}
});

匿名 提到...

大大您好,剛去測試沒太大效果~大大是否有更好方法,我原本想要的是按下後,IMAGE BUTTON周遭會有顏色跑出來~

ola的家 提到...

客製化按鈕請參考:http://wangshifuola.blogspot.tw/2011/10/android.html

林則宇 提到...

想請問一個問題
最近也在學習

當我跳入另外一個頁面時候
再從另外一個頁面跳回來

原本畫面的按鈕就失去功能
為什麼會這樣呢

ola的家 提到...

我沒有遇過這個狀況耶!

匿名 提到...

請問一下 我使用imagebutton來控制更換頁面
如果只用button模擬器都可以跑但如果使用imagebutton模擬器都會崩潰
請問知道位什麼嗎???

ola的家 提到...

去看錯誤訊息,才會知道原因。

張貼留言