.
參考界面 : 攜程app首頁的廣告欄, 使用ViewPager實現
自制頁面效果圖 :
.
一. ViewPager適配頁面問題
1. ViewPager出現的問題
ViewPager占滿全屏問題 : ViewPager在XML中定義瞭android:layout_height 和 android:layout_width 之後, 不論這兩個屬性的值是 fill_parent 還是 wrap_content, 都會出現ViewPager占滿全屏的問題;
不使用固定值定義寬高: 為瞭使ViewPager能適配各種類型的手機, 如果給ViewPager定義瞭高度和寬度, 與各種手機的界面兼容性肯定要大大的降低, 因此出現瞭下面的解決方案;
2. 解決方案
代碼中添加組件 : 不在XML界面定義該組件, 可以在佈局文件中,定義一個LinearLayout容器, 然後在代碼中動態添加ViewPager;
好處 : 這樣的好處是可以在代碼中獲取屏幕的寬高, 我們可以根據比例設定ViewPager的大小, 這樣就解決瞭屏幕適配的問題;
3. 代碼實現
//從佈局文件中獲取ViewPager父容器 pagerLayout = (LinearLayout) findViewById(R.id.view_pager_content); //創建ViewPager adViewPager = new ViewPager(this); //獲取屏幕像素相關信息 DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); //根據屏幕信息設置ViewPager廣告容器的寬高 adViewPager.setLayoutParams(new LayoutParams(dm.widthPixels, dm.heightPixels * 2 / 5)); //將ViewPager容器設置到佈局文件父容器中 pagerLayout.addView(adViewPager);
二. ViewPager廣告欄基本解決方案
1. ViewPager適配器PagerAdapter
自定義PagerAdapter類 : 我們需要自定義一個類, 去繼承PageAdapter, 至少實現下面四個方法 :
destroyItem(View container, int position, Object object) :
作用 :刪除container中指定位置position的頁面;
參數 : container 就是容器, 這裡指的是ViewPager對象, position就是刪除的頁面索引;
int getCount() :
作用 :獲取ViewPager頁面的個數;
返回值 : ViewPager頁面個數;
Object instantiateItem(View container, int position) :
作用 :在給定的位置創建頁面, PageAdapter負責向指定的position位置添加View頁面;
參數 : container容器就是ViewPager, position指的是ViewPager的索引;
返回值 : 返回代表新的一頁的對象;
boolean isViewFromObject(View view, Object object) :
作用 :決定instantiateItem()方法返回的Object對象是不是需要顯示的頁面關聯, 這個方法必須要有;
參數 : view 要關聯的頁面, object instantiateItem()方法返回的對象;
返回值 : 是否要關聯顯示頁面與 instantiateItem()返回值;
為PageAdapter關聯數據源 : 可以將一個數組或者集合與PageAdapter關聯,集合的索引與ViewPager的索引對應, destroyItem()方法中刪除集合中對應索引的元素對象, instantiateItem 添加對應索引的元素對象;
PageAdapter 代碼示例 :
private final class AdvAdapter extends PagerAdapter { private List views = null; /** * 初始化數據源, 即View數組 */ public AdvAdapter(List views) { this.views = views; } /** * 從ViewPager中刪除集合中對應索引的View對象 */ @Override public void destroyItem(View container, int position, Object object) { ((ViewPager) container).removeView(views.get(position)); } /** * 獲取ViewPager的個數 */ @Override public int getCount() { return views.size(); } /** * 從View集合中獲取對應索引的元素, 並添加到ViewPager中 */ @Override public Object instantiateItem(View container, int position) { ((ViewPager) container).addView(views.get(position), 0); return views.get(position); } /** * 是否將顯示的ViewPager頁面與instantiateItem返回的對象進行關聯 * 這個方法是必須實現的 */ @Override public boolean isViewFromObject(View view, Object object) { return view == object; } }
創建PageAdapter代碼 :
private void initPageAdapter() { pageViews = new ArrayList(); ImageView img1 = new ImageView(this); img1.setBackgroundResource(R.drawable.view_add_1); pageViews.add(img1); ImageView img2 = new ImageView(this); img2.setBackgroundResource(R.drawable.view_add_2); pageViews.add(img2); ImageView img3 = new ImageView(this); img3.setBackgroundResource(R.drawable.view_add_3); pageViews.add(img3); ImageView img4 = new ImageView(this); img4.setBackgroundResource(R.drawable.view_add_4); pageViews.add(img4); ImageView img5 = new ImageView(this); img5.setBackgroundResource(R.drawable.view_add_5); pageViews.add(img5); ImageView img6 = new ImageView(this); img6.setBackgroundResource(R.drawable.view_add_6); pageViews.add(img6); adapter = new AdPageAdapter(pageViews); }
2. 小圓點導航策略
圓點存放策略 : 所有的小圓點都放在一個ViewGroup中, 有兩種圓點, 一種是當前顯示的, 一種是沒激活的, 這裡我們將一組圓點分別放入ImageView中, 並且將這些ImageView組裝起來放到ViewGroup中即可;
圓點導航初始化 : 最初默認顯示第一個頁面, 第一個圓點激活, 根據ViewPager個數初始化圓點的個數, 組裝圓點的時候, 第一個圓點狀態激活;
代碼如下 :
private void initCirclePoint(){ ViewGroup group = (ViewGroup) findViewById(R.id.viewGroup); imageViews = new ImageView[pageViews.size()]; //廣告欄的小圓點圖標 for (int i = 0; i < pageViews.size(); i++) { //創建一個ImageView, 並設置寬高. 將該對象放入到數組中 imageView = new ImageView(this); imageView.setLayoutParams(new LayoutParams(20,20)); imageViews[i] = imageView; //初始值, 默認第0個選中 if (i == 0) { imageViews[i] .setBackgroundResource(R.drawable.point_focused); } else { imageViews[i] .setBackgroundResource(R.drawable.point_unfocused); } //將小圓點放入到佈局中 group.addView(imageViews[i]); } }
ViewPager頁面改變時圓點導航隨之改變 : 獲取ViewPager當前顯示頁面索引,重新組裝ViewGroup中的圓點排列順序, 這個方法在ViewPager頁面改變監聽器中實現;
代碼如下 :
/** * ViewPager 頁面改變監聽器 */ private final class AdPageChangeListener implements OnPageChangeListener { /** * 頁面滾動狀態發生改變的時候觸發 */ @Override public void onPageScrollStateChanged(int arg0) { } /** * 頁面滾動的時候觸發 */ @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } /** * 頁面選中的時候觸發 */ @Override public void onPageSelected(int arg0) { //獲取當前顯示的頁面是哪個頁面 atomicInteger.getAndSet(arg0); //重新設置原點佈局集合 for (int i = 0; i < imageViews.length; i++) { imageViews[arg0] .setBackgroundResource(R.drawable.point_focused); if (arg0 != i) { imageViews[i] .setBackgroundResource(R.drawable.point_unfocused); } } } }
3. 自動翻頁導航策略
線程中處理自動翻頁 : 啟動一個線程, 獲取當前頁面顯示索引, 計算出下一個顯示位置, 顯示下一個頁面;
.
相關代碼 :
線程代碼 :
new Thread(new Runnable() { @Override public void run() { while (true) { if (isContinue) { viewHandler.sendEmptyMessage(atomicInteger.get()); atomicOption(); } } } }).start();
handler代碼 :
private void atomicOption() { atomicInteger.incrementAndGet(); if (atomicInteger.get() > imageViews.length - 1) { atomicInteger.getAndAdd(-5); } try { Thread.sleep(3000); } catch (InterruptedException e) { } } /* * 每隔固定時間切換廣告欄圖片 */ private final Handler viewHandler = new Handler() { @Override public void handleMessage(Message msg) { adViewPager.setCurrentItem(msg.what); super.handleMessage(msg); } };
三. 程序所有代碼 和 資源文件
XML佈局文件 :
主Activity源碼 :
package shuliang.han.myviewpager; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.DisplayMetrics; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.widget.ImageView; import android.widget.LinearLayout; public class MainActivity extends Activity { private ViewPager adViewPager; private LinearLayout pagerLayout; private List pageViews; private ImageView[] imageViews; private ImageView imageView; private AdPageAdapter adapter; private AtomicInteger atomicInteger = new AtomicInteger(0); private boolean isContinue = true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViewPager(); } private void initViewPager() { //從佈局文件中獲取ViewPager父容器 pagerLayout = (LinearLayout) findViewById(R.id.view_pager_content); //創建ViewPager adViewPager = new ViewPager(this); //獲取屏幕像素相關信息 DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); //根據屏幕信息設置ViewPager廣告容器的寬高 adViewPager.setLayoutParams(new LayoutParams(dm.widthPixels, dm.heightPixels * 2 / 5)); //將ViewPager容器設置到佈局文件父容器中 pagerLayout.addView(adViewPager); initPageAdapter(); initCirclePoint(); adViewPager.setAdapter(adapter); adViewPager.setOnPageChangeListener(new AdPageChangeListener()); new Thread(new Runnable() { @Override public void run() { while (true) { if (isContinue) { viewHandler.sendEmptyMessage(atomicInteger.get()); atomicOption(); } } } }).start(); } private void atomicOption() { atomicInteger.incrementAndGet(); if (atomicInteger.get() > imageViews.length - 1) { atomicInteger.getAndAdd(-5); } try { Thread.sleep(3000); } catch (InterruptedException e) { } } /* * 每隔固定時間切換廣告欄圖片 */ private final Handler viewHandler = new Handler() { @Override public void handleMessage(Message msg) { adViewPager.setCurrentItem(msg.what); super.handleMessage(msg); } }; private void initPageAdapter() { pageViews = new ArrayList(); ImageView img1 = new ImageView(this); img1.setBackgroundResource(R.drawable.view_add_1); pageViews.add(img1); ImageView img2 = new ImageView(this); img2.setBackgroundResource(R.drawable.view_add_2); pageViews.add(img2); ImageView img3 = new ImageView(this); img3.setBackgroundResource(R.drawable.view_add_3); pageViews.add(img3); ImageView img4 = new ImageView(this); img4.setBackgroundResource(R.drawable.view_add_4); pageViews.add(img4); ImageView img5 = new ImageView(this); img5.setBackgroundResource(R.drawable.view_add_5); pageViews.add(img5); ImageView img6 = new ImageView(this); img6.setBackgroundResource(R.drawable.view_add_6); pageViews.add(img6); adapter = new AdPageAdapter(pageViews); } private void initCirclePoint(){ ViewGroup group = (ViewGroup) findViewById(R.id.viewGroup); imageViews = new ImageView[pageViews.size()]; //廣告欄的小圓點圖標 for (int i = 0; i < pageViews.size(); i++) { //創建一個ImageView, 並設置寬高. 將該對象放入到數組中 imageView = new ImageView(this); imageView.setLayoutParams(new LayoutParams(10,10)); imageViews[i] = imageView; //初始值, 默認第0個選中 if (i == 0) { imageViews[i] .setBackgroundResource(R.drawable.point_focused); } else { imageViews[i] .setBackgroundResource(R.drawable.point_unfocused); } //將小圓點放入到佈局中 group.addView(imageViews[i]); } } /** * ViewPager 頁面改變監聽器 */ private final class AdPageChangeListener implements OnPageChangeListener { /** * 頁面滾動狀態發生改變的時候觸發 */ @Override public void onPageScrollStateChanged(int arg0) { } /** * 頁面滾動的時候觸發 */ @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } /** * 頁面選中的時候觸發 */ @Override public void onPageSelected(int arg0) { //獲取當前顯示的頁面是哪個頁面 atomicInteger.getAndSet(arg0); //重新設置原點佈局集合 for (int i = 0; i < imageViews.length; i++) { imageViews[arg0] .setBackgroundResource(R.drawable.point_focused); if (arg0 != i) { imageViews[i] .setBackgroundResource(R.drawable.point_unfocused); } } } } private final class AdPageAdapter extends PagerAdapter { private List views = null; /** * 初始化數據源, 即View數組 */ public AdPageAdapter(List views) { this.views = views; } /** * 從ViewPager中刪除集合中對應索引的View對象 */ @Override public void destroyItem(View container, int position, Object object) { ((ViewPager) container).removeView(views.get(position)); } /** * 獲取ViewPager的個數 */ @Override public int getCount() { return views.size(); } /** * 從View集合中獲取對應索引的元素, 並添加到ViewPager中 */ @Override public Object instantiateItem(View container, int position) { ((ViewPager) container).addView(views.get(position), 0); return views.get(position); } /** * 是否將顯示的ViewPager頁面與instantiateItem返回的對象進行關聯 * 這個方法是必須實現的 */ @Override public boolean isViewFromObject(View view, Object object) { return view == object; } } }
效果圖 :
源碼下載地址 : https://download.csdn.net/detail/han1202012/6835401
.