ViewPager(Pager尋呼機 Page頁):這個控件不是安卓系統原生態的,雖然是第三方jar包,但是也是谷歌提供的,在android.support.v4.view.ViewPager下。
代碼工程目錄如下: 注意:viewpager顯示的界面可以是任意視圖,也可以是任意布局文件,還可以在布局文件中添加ListView,也就實現了即上下滑又左右滑,並且還不影響ListView的單擊事件. 不過下面給出的例子顯示的都是圖片
代碼如下:
import java.util.ArrayList; import android.os.Bundle; import android.app.Activity; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.widget.TextView; /** 如果報這個類沒有找到異常: Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.v4.view.ViewPager" 解決方法見圖: */ public class MainActivity extends Activity { private ViewPager viewPager;//圖片滑動的控件 private TextView textView;//圖片上顯示的文字 private LinearLayout pointGroup;//滑動的指示 private int[] imageArr={R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e}; private String[] textArr={"第一張顯示的文字","第二張顯示的文字","第三張顯示的文字","第四張顯示的文字","第五張顯示的文字",}; private ArrayList<ImageView> imgList; private int lastPointPosition;//上一個頁面的位置索引 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewPager = (ViewPager) findViewById(R.id.viewPager); textView = (TextView) findViewById(R.id.textView); pointGroup = (LinearLayout) findViewById(R.id.point_group); imgList=new ArrayList<ImageView>(); for (int i=0;i<imageArr.length;i++) { //初始化圖片 ImageView image=new ImageView(this); image.setBackgroundResource(imageArr[i]); imgList.add(image); //添加圖片的指示點 ImageView point=new ImageView(this); LinearLayout.LayoutParams params=new LayoutParams(10,10);//布局參數,point的布局寬與高 params.rightMargin=10;//右邊距 point.setLayoutParams(params);//設置布局參數 point.setBackgroundResource(R.drawable.point_bg);//point_bg是根據setEnabled的值來確定形狀的 if(i==0){ point.setEnabled(true);//初始化的時候設置第一張圖片的形狀 }else{ point.setEnabled(false);//根據該屬性來確定這個圖片的顯示形狀 } pointGroup.addView(point);//將該指示的圖片添加到布局中 } textView.setText(textArr[0]);//將第一次顯示的文本初始化到視圖中 //添加適配器 viewPager.setAdapter(new MyPagerAdapter()); //為viewPager設置監聽 viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { //頁面改變的時候調用(穩定),positon表示被選中的索引 @Override public void onPageSelected(int position) { textView.setText(textArr[position]);//設置文字描述內容 //改變指示點的狀態 pointGroup.getChildAt(position).setEnabled(true);//將當前點enbale設置為true pointGroup.getChildAt(lastPointPosition).setEnabled(false);//將上一個點設置為false lastPointPosition=position; } //頁面正在滑動的時候調用,position指的是左側頁面的索引,positionOffset代表偏移量[0,1]的范圍,positionOffsetPixels也是偏移量,不過是像素點的偏移量 范圍[0,顯示的控件的絕對長度] @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override //頁面滾動狀態發送改變的時候回調 public void onPageScrollStateChanged(int state) { //當手指點擊屏幕滾動的時狀態碼為1,當手指離開viewpager自動滾動的狀態碼為2,自動滾動選中了顯示了頁面的時候狀態碼為0 } }); } /** *ViewPager的適配器,原理: *它最多只會創建三個圖片(即當前屏幕顯示的這張圖片與該圖片的左右兩張圖片,當滑動的時候,就會把多余的銷毀掉,需要的創建出來) */ private class MyPagerAdapter extends PagerAdapter{ /** * 獲得頁面的總數 */ @Override public int getCount() { return imageArr.length; } /** * 判斷view和object的對應關系,如果當前要顯示的控件是來之於instantiateItem方法創建的就顯示,否則不顯示 * object 為instantiateItem方法返回的對象 * 如果為false就不會顯示該視圖 */ @Override public boolean isViewFromObject(View view, Object object) { System.out.println("view:"+view); System.out.println("object:"+object); return view==object; } /** * 實例化下一個要顯示的子條目,獲取相應位置上的view,這個為當前顯示的視圖的下一個需要顯示的控件 * container view的容器,其實就是viewager自身 * position ViewPager相應的位置 */ @Override public Object instantiateItem(ViewGroup container, int position) { container.addView(imgList.get(position)); System.out.println("創建一個視圖"); return imgList.get(position); } /** * 銷毀一個子條目,object就為instantiateItem方法創建的返回的對象,也是滑出去需要銷毀了的視圖對象 */ @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); object=null; System.out.println("銷毀一個視圖"); } } }
類找不到異常的解決辦法: 如果還異常就把android-support-v4.jar Top到置頂
布局文件: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" tools:context=".MainActivity" > <!-- 廣告條布局(視圖頁) --> <android.support.v4.view.ViewPager android:layout_width="match_parent" android:layout_height="200dp" android:id="@+id/viewPager" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#33000000" android:orientation="vertical" android:layout_alignBottom="@id/viewPager"> <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:textColor="@android:color/white" android:textSize="20sp" android:text="默認文字"/> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:id="@+id/point_group"> </LinearLayout> </LinearLayout> </RelativeLayout>
關於指示器的文件:
1. point_nomal.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <!-- 一個圓形的圖形 --> <size android:width="5dp" android:height="5dp"/> <solid android:color="#55000000"/> </shape>
2.point_focured.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <size android:width="5dp" android:height="5dp"/> <solid android:color="#aaffffff"/> </shape>
3. point_bg.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" > <!-- 可使用就為point_focured形狀, 否則為point_nomal形狀 所以java代碼中根據setEnabled(false)方法來確定顯示什么形狀--> <item android:drawable="@drawable/point_nomal" android:state_enabled="false"></item> <item android:drawable="@drawable/point_focured" android:state_enabled="true"></item> </selector>
效果圖如下:
循環滑動功能與自動滑動功能的實現以及點擊指示器顯示對應的頁面(在上面的java代碼中進行修改,代碼如下):
import java.util.ArrayList; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.app.Activity; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.widget.TextView; /** 如果報這個類沒有找到異常: Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.v4.view.ViewPager" 解決方法見圖. 這里和上面的不同: 1.將當前顯示的圖片的指示器setEnabled(false),讓當前的不可點擊,其他的可以點擊 2.為指示器設置了單擊事件,利用到了tag 3.將數據的初始化抽取成了一個方法 新增功能: 1.可以點擊指示器,ViewPager跳轉到對應的圖片顯示 2.循環顯示,自動滑動 ViewPager兩個比較重要的方法: viewPager.setCurrentItem(tag);//指定顯示哪個頁面 viewPager.getCurrentItem();//獲取當前顯示的界面的索引 */ public class MainActivity extends Activity { private ViewPager viewPager;//圖片滑動的控件 private TextView textView;//圖片上顯示的文字 private LinearLayout pointGroup;//滑動的指示 /** * 裝圖片的資源id */ private int[] imageArr={R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e}; private String[] textArr={"第一張顯示的文字","第二張顯示的文字","第三張顯示的文字","第四張顯示的文字","第五張顯示的文字",}; private ArrayList<ImageView> imgList; private int lastPointPosition;//上一個頁面的位置索引,也是上一個指示器的索引 /** * 為true才發生消息給handler,避免程序退出后還一直發送消息給handler */ private boolean isRuning=true; /** * 用於實現自動滑動 */ private Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what==1 && isRuning){ //收到消息,開始滑動 int currentItem = viewPager.getCurrentItem();//獲取當前顯示的界面的索引 //如果當前顯示的是最后一個頁面,就顯示第一張,否則顯示下一張 if(currentItem==imgList.size()-1){ viewPager.setCurrentItem(0); }else{ viewPager.setCurrentItem(currentItem+1); } //2ms后再發送消息,實現循環 handler.sendEmptyMessageDelayed(1, 5000); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewPager = (ViewPager) findViewById(R.id.viewPager); textView = (TextView) findViewById(R.id.textView); pointGroup = (LinearLayout) findViewById(R.id.point_group); initData();//初始化 //添加適配器 viewPager.setAdapter(new MyPagerAdapter()); //為viewPager設置監聽 viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { //頁面改變的時候調用(穩定),positon表示被選中的索引 @Override public void onPageSelected(int position) { textView.setText(textArr[position]);//設置文字描述內容 //改變指示點的狀態 pointGroup.getChildAt(position).setEnabled(false);//將當前點enbale設置為false,讓當前的指示器點擊無效 pointGroup.getChildAt(lastPointPosition).setEnabled(true);//將上一個點設置為true lastPointPosition=position; } /*當頁面正在滾動的時候調用 * int position, 頁面的索引,指向的是左側頁面的索引 * float positionOffset, 表示偏移量, 值為 0- 1 ,0表示相對於左側頁面沒有偏移 , 1表示相對於左側頁面偏移1個單位長度(完全偏移) int positionOffsetPixels 表示偏移量, 值為 0-控件的絕對長度 */ @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } /* 當頁面滾動狀態改變的時候調用 * 當手指點擊屏幕在屏幕上滾動的時候 狀態為1 * 當手指離開,viewpager自動 滾動 選中頁面時 狀態為2 * 當手指離開,自動 選中上頁面時 狀態為0 */ @Override public void onPageScrollStateChanged(int state) { } }); //發送第一條消息給handler,實現循環 handler.sendEmptyMessageDelayed(1, 5000); } /** * 初始化數據,將圖片和指示器都創建出來添加到集合 * 這里通過數組的長度,動態添加圖片和指示器,有利於從網絡上獲取數據顯示 */ private void initData(){ imgList=new ArrayList<ImageView>(); for (int i=0;i<imageArr.length;i++) { //初始化圖片 ImageView image=new ImageView(this); image.setBackgroundResource(imageArr[i]); imgList.add(image); //添加圖片的指示點 final ImageView point=new ImageView(this); LinearLayout.LayoutParams params=new LayoutParams(20,20);//布局參數,point的布局寬與高 params.rightMargin=10;//右邊距 point.setLayoutParams(params);//設置布局參數 point.setBackgroundResource(R.drawable.point_bg);//point_bg是根據setEnabled的值來確定形狀的 if(i==0){ point.setEnabled(false);//初始化的時候設置第一張圖片的形狀 }else{ point.setEnabled(true);//根據該屬性來確定這個圖片的顯示形狀 } point.setClickable(true);//設置為可點擊 //為point設置單擊事件,實現點擊后ViewPager顯示對應的圖片 point.setTag(i);//設置標記,好知道點擊的指示器的索引 point.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int tag = (Integer) point.getTag();//獲取這個指示器的標記 viewPager.setCurrentItem(tag);//設置當前顯示的為第tag張圖片,執行后會調用監聽事件,所以指示器顏色的變化不需要在這里處理 } }); pointGroup.addView(point);//將該指示的圖片添加到布局中 } textView.setText(textArr[0]);//將第一次顯示的文本初始化到視圖中 } /** *ViewPager的適配器,原理: *它最多只會創建三個圖片(即當前屏幕顯示的這張圖片與該圖片的左右兩張圖片,當滑動的時候,就會把多余的銷毀掉,需要的創建出來) */ private class MyPagerAdapter extends PagerAdapter{ /** * 獲得頁面的總數 */ @Override public int getCount() { return imgList.size(); } /** * 判斷view和object的對應關系,如果當前要顯示的控件是來之於instantiateItem方法創建的就顯示,否則不顯示 * object 為instantiateItem方法返回的對象 * 如果為false就不會顯示該視圖 */ @Override public boolean isViewFromObject(View view, Object object) { return view==object; } /** * 實例化下一個要顯示的子條目,獲取相應位置上的view,這個為當前顯示的視圖的下一個需要顯示的控件 * container view的容器,其實就是viewager自身 * position ViewPager相應的位置 */ @Override public Object instantiateItem(ViewGroup container, int position) { container.addView(imgList.get(position)); return imgList.get(position); } /** * 銷毀一個子條目,object就為instantiateItem方法創建的返回的對象,也是滑出去需要銷毀了的視圖對象 */ @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); object=null; } } /** * 當程序退出時,結束handler消息的發送 */ @Override protected void onDestroy() { super.onDestroy(); isRuning=false; } }