跳到主要內容

[Android] 頁面切換的方式-ViewFlipper

利用ViewFlipper來實現頁面左右滑動切換的效果很簡單,
只要使用ViewFlipper將View裝在一起,再用GestureDetector做手勢辨別就可以了。

Step1 在layout加上ViewFlipper元件

<ViewFlipper
android:id="@+id/vf"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ViewFlipper>


Step2 在anim資料夾中新增左右滑動動畫的XML

新增anim資料夾,並且將Resource Type 選擇 anim



















新增四個anim檔案,分別為左進、左出、右進、右出




























左進 (push_left_in.xml):手勢往左滑的進場動作
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="500"
android:fromXDelta="100%p"
android:toXDelta="0" />
<alpha
android:duration="500"
android:fromAlpha="0.1"
android:toAlpha="1.0" />
</set>

左出(push_left_out.xml):手勢往左滑的出場動作
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="500"
android:fromXDelta="0"
android:toXDelta="-100%p" />
<alpha
android:duration="500"
android:fromAlpha="1.0"
android:toAlpha="0.1" />
</set>

右進(push_right_in.xml):手勢往右滑的進場動作
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="500"
android:fromXDelta="-100%p"
android:toXDelta="0" />
<alpha
android:duration="500"
android:fromAlpha="0.1"
android:toAlpha="1.0" />
</set>

右出(push_right_out.xml):手勢往右滑的出場動作
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="500"
android:fromXDelta="0"
android:toXDelta="100%p" />
<alpha
android:duration="500"
android:fromAlpha="1.0"
android:toAlpha="0.1" />
</set>
translate標籤(位置移動)屬性介紹:
    fromXDelta:X軸方向的起始位置
    toXDelta:X軸方向的結束位置
    fromYDelta:Y軸方向的起始位置
    toYDelta:Y軸方向的結束位置
    以上屬性的值可以填入
        (1) 數值 → 如果數值為50,代表在目前View的左上角加上50px後做為起點
        (2) % → 如果為50%,代表在目前View的左上角加上自己寬度的50%後做為起點
        (3) %p → 如果為50%p,代表在目前View的左上角加上父元件寬度的50%後做為起點

Step3 設定MainActivity.java檔

宣告ViewFlipper並新增addImgView、addMyView的方法,再將要可切換的view新增到ViewFlipper中
public class MainActivity extends AppCompatActivity {
ViewFlipper vf;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
vf = (ViewFlipper) findViewById(R.id.vf);
//增加view
vf.addView(addImgView(R.drawable.img3));
vf.addView(addImgView(R.drawable.img4));
vf.addView(addImgView(R.drawable.img5));
vf.addView(addMyView(R.layout.layout1));
vf.addView(addMyView(R.layout.layout2));
}
//addImgView方法(切換圖片)
private View addImgView(int id){
ImageView iv = new ImageView(this);
iv.setImageResource(id);
return iv;
}
//addMyView方法(切換layout)
private View addMyView(int layout) {
LayoutInflater loi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View vi = loi.inflate(layout,null);
return vi;
}
}

手勢的判斷要繼承OnGestureListener方法。
(出現錯誤按下Alt+Enter,並匯入Method)






























接著在onCreate中宣告GestureDetector方法,並在onFling的方法中加上判斷手勢方向的方法
gd = new GestureDetector(this);
@Override
public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
//手勢往左滑
if (motionEvent.getX() - motionEvent1.getX() > 120){
vf.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_in));
vf.setOutAnimation(AnimationUtils.loadAnimation(this,R.anim.push_left_out));
vf.showNext();
return true;
}
//手勢往右滑
else if(motionEvent.getX() - motionEvent1.getX() < -120){
vf.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_right_in));
vf.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.push_right_out));
vf.showPrevious();
return true;
}
return false;
}

最後宣告onTouchEvent,如果沒宣告的話,會無法滑動
@Override
public boolean onTouchEvent(MotionEvent event) {
return this.gd.onTouchEvent(event);
}

完整MainActivity.java程式碼:
public class MainActivity extends AppCompatActivity implements GestureDetector.OnGestureListener{
ViewFlipper vf;
GestureDetector gd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gd = new GestureDetector(this);
vf = (ViewFlipper) findViewById(R.id.vf);
//增加view
vf.addView(addImgView(R.drawable.img3));
vf.addView(addImgView(R.drawable.img4));
vf.addView(addImgView(R.drawable.img5));
vf.addView(addMyView(R.layout.layout1));
vf.addView(addMyView(R.layout.layout2));
}
//addImgView方法(切換圖片)
private View addImgView(int id){
ImageView iv = new ImageView(this);
iv.setImageResource(id);
return iv;
}
//addMyView方法(切換layout)
private View addMyView(int layout) {
LayoutInflater loi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View vi = loi.inflate(layout,null);
return vi;
}
@Override
public boolean onDown(MotionEvent motionEvent) {
return false;
}
@Override
public void onShowPress(MotionEvent motionEvent) {
}
@Override
public boolean onSingleTapUp(MotionEvent motionEvent) {
return false;
}
@Override
public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
return false;
}
@Override
public void onLongPress(MotionEvent motionEvent) {
}
@Override
public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
//手勢往左滑
if (motionEvent.getX() - motionEvent1.getX() > 120){
vf.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_in));
vf.setOutAnimation(AnimationUtils.loadAnimation(this,R.anim.push_left_out));
vf.showNext();
return true;
}
//手勢往右滑
else if(motionEvent.getX() - motionEvent1.getX() < -120){
vf.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_right_in));
vf.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.push_right_out));
vf.showPrevious();
return true;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return this.gd.onTouchEvent(event);
}
}


參考資料:启舰的博客





留言

這個網誌中的熱門文章

[Android] 使用shape自訂形狀及陰影

shape可以定義下面四種類型的形狀:     rectangle- 矩形(直角矩形、圓角矩形),默認的形狀     oval- 橢圓形、圓形     line- 線形(實線、虛線)     ring- 環形、環形進度條 rectangle 執行結果: 如果填色要填入漸層色的話,需要將solid標籤改成gradient標籤,用法如下: 執行結果: oval 執行結果: oval和ring的漸層有三種類型(android:type):linear(線性)、radial(放射性)、sweep(掃描) 如果漸層效果為radial(放射性)的話,必須加上android:gradientRadius屬性(指定漸層的半徑)。 執行結果: line 線的高度是透過stroke的android:width屬性設置,而size的android:height是定義整個形狀區域的高度,所以 size的height必須大於stroke的width 。 執行結果: ring 屬於ring的屬性:     android:innerRadius 內環的半徑     android:thickness 環的厚度     android:useLevel 一般設為false,要不然環可能會無法顯示 執行結果: 將環設計成環狀進度條的樣式: 1,在shape標籤外再加上rotate標籤 rotate屬性:     android:fromDegrees:開始旋轉的角度位置     android:toDegrees:結束時轉到的角度位置     android:pivotX:旋轉起點的X軸座標位置,可以是數值、百分比、百分比p     android:pivotY:旋轉起點的Y軸座標位置,可以是數值、百分比、百分比p 2,在style.xml裡加上style樣式 3,在activity_main.xml裡加上progressBar標籤...

[隋堂筆記] Android 利用BaseAdapter來自訂ListView

BaseAdapter 可以讓使用者自己定義許多種 View ,像是 Spinner, ListView, GridView等,而且 可以重用View來節省資源 :使用setTag將View存起來,之後就可以利用getTag將數據取出來 Step1  在activity_main.xml中新增ListView 例如: Step2 在layout中新增list_content.xml,並排好想要的ListView item佈局 Step3 在MainActivity.java 新增一個類別BA並繼承BaseAdapter 透過繼承 BaseAdapter,我們可以重新覆寫4個方法:     public int getCount();     取得 ListView 列表 Item 的數量。通常數量就是從建構子傳入的陣列或是集合大小。     public Object getItem(int position);     取得 ListView 列表於 position 位置上的 Item。position 通常是資料在陣列或是集合上的位置。     public long getItemId(int position);     取得 ListView 列表於 position 位置上的 Item 的 ID,一般用 position 的值即可。     public View getView(int position, View view, ViewGroup viewGroup);     通常會設定與回傳View 作為顯示在這個 position 位置的 Item 的 View。 基本上只要處理兩個方法 getCount跟getView即可。 getCount回傳我所宣告的String陣列st1的長度。 在getView之前,要先取得LayoutInflater 再來要先宣告一個類別viewHolder,用來存放list_content.xml內所有元件的內容 接著判斷view是否為空,如果為空就要...

[iOS] Objective-C 自訂UITableViewCell樣式

Step1 在Storyboard中拉出TableView和按下TableView Cell後要切換的View,並設定對應的class檔 TableView連結至ListController類別,並設定Storyboard ID為ListController 要切換的View連結至ViewController類別,並設定Storyboard ID為viewController Step2 新增CustomCell.xib 新增File(File → New → File...),選擇View,並將檔案命名為CustomCell 開啟CustomCell.xib,把預設的View元件刪掉,然後從元件庫拖曳Table View Cell,並拉好想要的Cell內容排版 Step3 新增自訂Objective-C class給這個NIB檔 新增File(File → New → File...),選擇Cocoa Touch class 需要繼承UITableViewCell Step4 回到CustomCell.xib,將Class連結到CustomTableViewCell Step5 在CustomTableViewCell.h檔中,設定元件變數 Step6 在ListController.h中設定TableView的元件變數,且宣告一個陣列,負責儲存表格上要呈現的資料 Step7 在ListController.m  的viewDidLoad方法中設定TableView的兩個輸出口:dataSource、delegate,並初始化陣列資料 dataSource所連結到的View Controller用來提供表格上Cell的內容 delegate為指定哪一個View Controller需要處理使用者在表格上的操作 Step8 在ListController.m中,實作tableView:numberOfRowsInSection:方法 -通知Table View需要產生多少個Cell(儲存格)來顯示資料 Step9 在ListController.m中,實作tableView:cellForRowAtIndexPat...