您好,登錄后才能下訂單哦!
現如今主流的Android應用中,都少不了左右滑動滾屏這項功能,(貌似現在好多人使用智能機都習慣性的有事沒事的左右滑屏,也不知道在干什么。。。嘿嘿),由于前段時間項目的需要,所以也對其研究了一下,總的來說滑屏實現有三種方式:(至于其他的實現方式目前后還沒碰到。。。)
1.ViewPager 2.ViewFlipper 3.ViewFlow
一.ViewPager
官方文檔介紹:http://developer.android.com/reference/android/support/v4/view/ViewPager.html
根據繼承關系我們可以看出,ViewPager不在android sdk 自帶jar包中,來源google 的補充組件android-support-v4.jar中,所以我們在3.0以前的版本中使用就需要導入該jar包了。
1.1 介紹:該類是一個布局管理器,它允許用戶通過滑動左、右頁的數據。你必須要一個實現了PagerAdapter接口從而生成的頁面視圖。
1.2 使用:
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </RelativeLayout>
MainActivity類:
package comzhf.android_viewpager; import java.util.ArrayList; import java.util.List; import android.os.Bundle; import android.app.Activity; import android.support.v4.view.ViewPager; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; /** * 主界面:ViewPagerViewPager不在android sdk 自帶jar包中,來源google 的補充組件android-support-v4.jar */ public class ViewPagerActivity extends Activity { private ViewPager mViewPager; List<View> viewList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); LayoutInflater mInflater = getLayoutInflater().from(this); View v1 = mInflater.inflate(R.layout.layout1, null); View v2 = mInflater.inflate(R.layout.layout2, null); View v3 = mInflater.inflate(R.layout.layout3, null); //添加頁面數據 viewList = new ArrayList<View>(); viewList.add(v1); viewList.add(v2); viewList.add(v3); //實例化適配器 mViewPager = (ViewPager) findViewById(R.id.viewpager); mViewPager.setAdapter(new MyPagerAdapter(viewList)); mViewPager.setCurrentItem(0); //設置默認當前頁 View view = viewList.get(0); TextView textView = (TextView) view.findViewById(R.id.text_1); textView.setText("我是第一頁"); Button button = (Button) view.findViewById(R.id.button_1); button.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO Auto-generated method stub Toast.makeText(getApplicationContext(), "你點擊了按鈕", Toast.LENGTH_SHORT).show(); } }); } }
這里還有三個布局文件:layout1.xml (其余兩個類似,略)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:background="@drawable/guide01" > <TextView android:id="@+id/text_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="葉片一" android:textSize="25sp" /> <Button android:id="@+id/button_1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="點擊我" > </Button> </LinearLayout>
效果圖:
補充說明:
1.這里我們用了Layout作為每個page的填充數據,其實官方文檔說ViewPager+Fragment配合使用更好
2.每個頁面的響應事件我們可以在OnPageChangeListener監聽器類中進行捕獲和處理對應事件。
二.ViewFlipper
官方文檔:http://developer.android.com/reference/android/widget/ViewFlipper.html
2.1 介紹:ViewFilpper控件是系統自帶控件之一,主要用于在同一個屏幕間的切換及設置動畫效果、間隔時間,且可以自動播放。
順便提及一下,View動畫關系圖:
2.2 使用:
2.2.1 靜態加載:
activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <ViewFlipper android:id="@+id/body_flipper" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#f0f0f0" > <include android:id="@+id/layout01" layout="@layout/page1" /> <include android:id="@+id/layout02" layout="@layout/page2" /> <include android:id="@+id/layout02" layout="@layout/page3" /> <include android:id="@+id/layout02" layout="@layout/page4" /> </ViewFlipper> </RelativeLayout>
MainActivity類:
package com.zhf.android_viewflipper_view; import android.os.Bundle; import android.app.Activity; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.animation.AnimationUtils; import android.widget.ViewFlipper; /** * ViewFlipper 靜態加載 * @author ZHF **/ public class MainActivity extends Activity implements OnTouchListener{ private ViewFlipper viewFlipper; private float touchDownX; // 手指按下的X坐標 private float touchUpX; //手指松開的X坐標 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewFlipper = (ViewFlipper) findViewById(R.id.body_flipper); viewFlipper.setOnTouchListener(this); } @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { // 取得左右滑動時手指按下的X坐標 touchDownX = event.getX(); return true; } else if (event.getAction() == MotionEvent.ACTION_UP) { // 取得左右滑動時手指松開的X坐標 touchUpX = event.getX(); // 從左往右,看前一個View if (touchUpX - touchDownX > 100) { // 顯示上一屏動畫 viewFlipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_right_in)); viewFlipper.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.push_right_out)); // 顯示上一屏的View viewFlipper.showPrevious(); // 從右往左,看后一個View } else if (touchDownX - touchUpX > 100) { //顯示下一屏的動畫 viewFlipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_in)); viewFlipper.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_out)); // 顯示下一屏的View viewFlipper.showNext(); } return true; } return false; } }
動畫配置文件(右進右出同理,略):
push_left_in.xml:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="500" android:fromXDelta="100.0%p" android:toXDelta="0.0" /> <alpha android:duration="500" android:fromAlpha="0.1" android:toAlpha="1.0" /> </set>
push_left_out.xml:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="500" android:fromXDelta="0.0" android:toXDelta="-100.0%p" /> <alpha android:duration="500" android:fromAlpha="1.0" android:toAlpha="0.1" /> </set>
效果:
向左滑屏 向右滑屏
補充:
上述的page只有4個,而真實項目中的page頁面個數是不確定的,所以下面這種方式是項目中經常用到的。
2.2.2 動態加載(重要)
參考文章:http://blog.csdn.net/yuzhiboyi/article/details/7702953
activity_main2.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <com.zhf.android_viewflipper_view.MyViewFlipper android:id="@+id/body_flipper" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#f0f0f0" > </com.zhf.android_viewflipper_view.MyViewFlipper> </RelativeLayout>
flipper_view.xml:
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scrollbars="none" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="vertical" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/textView" android:textSize="100dip" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> </ScrollView>
注:這里并不是所有的View都能有onFling回調函數,外部需要加ScrollView !
MyGestureListener類:自定義滑動事件監聽器
package com.zhf.android_viewflipper_view; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; /** * 自定義滑動事件監聽器 * SimpleOnGestureListener已經實現了OnGestureListener接口和OnDoubleTapListener接口, * 可以有選擇性的復寫需要的方法,提供方法onFling()作為滑動事件的回調函數 * @author ZHF * */ public class MyGestureListener extends SimpleOnGestureListener{ private OnFlingListener mOnFlingListener; /**用戶按下觸摸屏、快速移動后松開,由1個MotionEvent ACTION_DOWN, 多個ACTION_MOVE, 1個ACTION_UP觸發 **/ @Override public final boolean onFling(final MotionEvent e1, final MotionEvent e2, final float speedX, final float speedY) { if (mOnFlingListener == null) { return super.onFling(e1, e2, speedX, speedY); } float XFrom = e1.getX(); //按下坐標 float XTo = e2.getX(); float YFrom = e1.getY(); float YTo = e2.getY(); // 左右滑動的X軸幅度大于100,并且X軸方向的速度大于100 if (Math.abs(XFrom - XTo) > 100.0f && Math.abs(speedX) > 100.0f) { // X軸幅度大于Y軸的幅度 if (Math.abs(XFrom - XTo) >= Math.abs(YFrom - YTo)) { if (XFrom > XTo) { // 下一個 mOnFlingListener.flingToNext(); } else { // 上一個 mOnFlingListener.flingToPrevious(); } } } else { return false; } return true; } /**自定義滑動的回調接口**/ public interface OnFlingListener { void flingToNext(); //滑動到下一頁 void flingToPrevious(); //滑動到上一頁 } public OnFlingListener getOnFlingListener() { return mOnFlingListener; } public void setOnFlingListener(OnFlingListener mOnFlingListener) { this.mOnFlingListener = mOnFlingListener; } }
MyViewFlipper類:自定義View滑動類:監聽滑動事件,并做切換視圖的處理。
package com.zhf.android_viewflipper_view; import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; import android.widget.ViewFlipper; import com.zhf.android_viewflipper_view.MyGestureListener.OnFlingListener; /** * 自定義View滑動類:監聽滑動事件,并做切換視圖的處理。 * @author ZHF * */ public class MyViewFlipper extends ViewFlipper implements OnFlingListener { //手勢監聽類 private GestureDetector mGestureDetector = null; private OnViewFlipperListener mOnViewFlipperListener = null; public MyViewFlipper(Context context) { super(context); } public MyViewFlipper(Context context, AttributeSet attrs) { super(context, attrs); } public void setOnViewFlipperListener(OnViewFlipperListener mOnViewFlipperListener) { this.mOnViewFlipperListener = mOnViewFlipperListener; //初始化自定義滑動事件監聽器 MyGestureListener myGestureListener = new MyGestureListener(); //綁定自定義的滑動監聽器 myGestureListener.setOnFlingListener(this); mGestureDetector = new GestureDetector(myGestureListener); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (null != mGestureDetector) { return mGestureDetector.onTouchEvent(ev); } else { return super.onInterceptTouchEvent(ev); } } /**向下一條滑動事件**/ @Override public void flingToNext() { if (null != mOnViewFlipperListener) { int childCnt = getChildCount(); if (childCnt == 2) { removeViewAt(1); } addView(mOnViewFlipperListener.getNextView(), 0); if (0 != childCnt) { setInAnimation(getContext(), R.anim.push_left_in); setOutAnimation(getContext(), R.anim.push_left_out); setDisplayedChild(0); } } } /**向上一條滑動事件**/ @Override public void flingToPrevious() { if (null != mOnViewFlipperListener) { int childCnt = getChildCount(); if (childCnt == 2) { removeViewAt(1); } addView(mOnViewFlipperListener.getPreviousView(), 0); if (0 != childCnt) { setInAnimation(getContext(), R.anim.push_right_in); setOutAnimation(getContext(), R.anim.push_right_out); setDisplayedChild(0); } } } /**自定義View變化監聽回調接口**/ public interface OnViewFlipperListener { View getNextView(); //獲取下一頁View View getPreviousView(); //獲取上一頁View } }
MainActivity2類:
package com.zhf.android_viewflipper_view; import com.zhf.android_viewflipper_view.MyViewFlipper.OnViewFlipperListener; import android.app.Activity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.widget.ScrollView; import android.widget.TextView; /** * ViewFlipper 動態加載 * @author ZHF */ public class MainActivity2 extends Activity implements OnViewFlipperListener{ private MyViewFlipper myViewFlipper; private int currentNumber; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); currentNumber = 1; //默認頁號 myViewFlipper = (MyViewFlipper) findViewById(R.id.body_flipper); //給ViewFlipper綁定自定義的滑動監聽器 myViewFlipper.setOnViewFlipperListener(this); //初始化頁面數據,即View myViewFlipper.addView(createView(currentNumber)); } /**獲取下一頁View**/ @Override public View getNextView() { currentNumber = currentNumber == 10 ? 1 : currentNumber + 1; return createView(currentNumber); } /**獲取上一頁View**/ @Override public View getPreviousView() { currentNumber = currentNumber == 1 ? 10 : currentNumber - 1; return createView(currentNumber); } /**更換View數據:這里是根據頁號來更換textView上的文字**/ private View createView(int currentNumber) { LayoutInflater layoutInflater = LayoutInflater.from(this); ScrollView resultView = (ScrollView) layoutInflater.inflate(R.layout.flipper_view, null); ((TextView) resultView.findViewById(R.id.textView)).setText(currentNumber + ""); return resultView; } }
效果圖:
--向左滑動(漸變過程不好截圖)-->
補充說明:
上述的三個類:
MyGestureListener:繼承了SimpleGestureListener手勢監聽類, 復寫了該類onFling()方法,用于監聽用戶按下滑動事件的處理;還自定義了滑動的回調接口OnFlingListener(包含了兩個抽象方法flingToNext(),flingToPrevious)。
MyViewFlipper:是一個自定義ViewFlipper,該類首先實現和綁定了上一個類中的滑動的回調接口OnFlingListener,完成了接口中兩個重要的方法。同時定義了一個View變化監聽回調接口OnViewFlipperListener(包含了兩個抽象方法getNextView(),getPreviousView())。
MainActivity2:加載布局,實現監聽,統一處理頁面數據View和滑動事件的綁定。
三.ViewFlow類
3.1介紹:
ViewFlow不是google官方的api,它是gethub上的一個開源項目,利用ViewFlow可以產生視圖切換的效果。ViewFlow 相當于 Android UI 部件提供水平滾動的 ViewGroup,使用 Adapter 進行條目綁定,例如ViewPager或是ViewFlipper。它提供了三個組件ViewFlow、FlowIndicator和TitleFlowIndicator,一般情況下,當你需要做一個滑動然而不確定view的數目時,可以考慮使用ViewFlow。如果你的view數目確定,使用Fragments 或兼容庫里的ViewPager比較好 。
3.2使用:
A.首先下載ViewFlow開源庫代碼:
官方文檔:https://github.com/pakerfeldt/android-viewflow
B.下載之后我們解壓打開viewflow文件夾:
C.建項目將這三個類直接復制過來放項目中使用即可。
注:這里可能還需要一個styleable文件,直接將value文件夾下的attrs.xml拷入即可。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res/com.zhf.android_viewflow" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <RelativeLayout android:layout_width="fill_parent" android:layout_height="135dp" android:orientation="vertical" > <com.zhf.android_viewflow.ViewFlow android:id="@+id/viewflow" android:layout_width="fill_parent" android:layout_height="fill_parent" app:sidebuffer="3"/> </RelativeLayout> <com.zhf.android_viewflow.CircleFlowIndicator android:id="@+id/viewflowindic" android:layout_width="wrap_content" android:layout_height="140dp" android:layout_alignParentBottom="true" android:layout_gravity="center_horizontal" app:fadeOut="0" app:inactiveType="fill" android:paddingTop="125dp" /> <!--圓點指示器還支持activeColor、inactiveColor、activeType(填充或描邊)、 inactiveType(填充或描邊)、 fadeOut(設置圓點自動隱藏的秒數,若為0則不會自動隱藏)、 radius(圓點的半徑)等。 --> </FrameLayout> </LinearLayout>
注:這里需要強調一下,因為使用第三方的庫組件,所以要在使用之前引入:
xmlns:app="http://schemas.android.com/apk/res/com.zhf.android_viewflow"
main_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:isScrollContainer="true" android:scrollbarAlwaysDrawVerticalTrack="true" android:scrollbars="vertical" > <!-- isScrollContainer 設置當前View為滾動容器 scrollbarAlwaysDrawVerticalTrack 設置是否始終顯示垂直滾動條--> <ImageView android:id="@+id/imgView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical|center_horizontal" > </ImageView> </LinearLayout>
MainActivity類
package com.zhf.android_viewflow; import android.os.Bundle; import android.app.Activity; import android.content.res.Configuration; public class MainActivity extends Activity { private ViewFlow viewFlow; private CircleFlowIndicator indic; //頁表指示器 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewFlow = (ViewFlow) findViewById(R.id.viewflow); //為其綁定適配器 viewFlow.setAdapter(new ImageAdapter(this),5); //初始位置5 indic = (CircleFlowIndicator) findViewById(R.id.viewflowindic); //為viewFlow綁定頁表指示器 viewFlow.setFlowIndicator(indic); } /**處理轉屏操作**/ @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); viewFlow.onConfigurationChanged(newConfig); } }
這里還有一個圖片適配器:ImageAdapter
package com.zhf.android_viewflow; import com.cjf.ui.R; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; public class ImageAdapter extends BaseAdapter{ private LayoutInflater mInflater; //圖片資源的id private static final int[] ids = { R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e, R.drawable.f, R.drawable.g, R.drawable.h}; public ImageAdapter(Context context) { this.mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public int getCount() { // TODO Auto-generated method stub return ids == null ? 0 :ids.length; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return position; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = mInflater.inflate(R.layout.p_w_picpath_item, null); } ((ImageView) convertView.findViewById(R.id.imgView)).setImageResource(ids[position]); return convertView; } }
運行一下吧!效果圖:
轉屏后
恩,終于寫完了! 希望這篇博客能幫助到大家!好累~~
三個例子的源碼我已總結好(獨立的三個項目,壓縮在一個zip里了)
下載地址:http://down.51cto.com/data/976370
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。