ViewPager 詳解(四)----自主實現滑動指示條
前言:前面我們用了三篇的時間講述了有關ViewPager的基礎知識,到這篇就要進入點實際的了。在第三篇《ViewPager 詳解(三)---PagerTabStrip與PagerTitleStrip新增標題欄的異同》中,我們說了,PagerTabStrip和PagerTitleStrip都不適合用在實際用途中,當要在實際運用中,我們就要自己去實現相關的功能。這篇文章中單純講述划動指示條的實現方法,而對於互動Tab的實現,就不再講解,最後給出網上的一段原始碼,大家可以去研究一下,有關互動Tab的實現原理是一樣的,難度不大。
相關文章:
先上本篇效果圖:
一、XML佈局
佈局程式碼如下:
採用線性垂直佈局,在滑動頁面的上方新增一個小水平條。<LinearLayout 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:orientation="vertical" tools:context="com.example.testviewpage_2.MainActivity" > <ImageView android:id="@+id/cursor" android:layout_width="fill_parent" android:layout_height="wrap_content" android:scaleType="matrix" android:src="@drawable/a" /> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center"/> </LinearLayout>
二、JAVA程式碼
先給出全部程式碼,然後再逐步講解。
從易到難一步步來講。public class MainActivity extends Activity { private View view1, view2, view3; private List<View> viewList;// view陣列 private ViewPager viewPager; // 對應的viewPager private ImageView cursor; private int bmpw = 0; // 遊標寬度 private int offset = 0;// // 動畫圖片偏移量 private int currIndex = 0;// 當前頁卡編號 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewPager = (ViewPager) findViewById(R.id.viewpager); LayoutInflater inflater = getLayoutInflater(); view1 = inflater.inflate(R.layout.layout1, null); view2 = inflater.inflate(R.layout.layout2, null); view3 = inflater.inflate(R.layout.layout3, null); viewList = new ArrayList<View>();// 將要分頁顯示的View裝入陣列中 viewList.add(view1); viewList.add(view2); viewList.add(view3); //初始化指示器位置 initCursorPos(); viewPager.setAdapter(new MyPagerAdapter(viewList)); viewPager.setOnPageChangeListener(new MyPageChangeListener()); } //初始化指示器位置 public void initCursorPos() { // 初始化動畫 cursor = (ImageView) findViewById(R.id.cursor); bmpw = BitmapFactory.decodeResource(getResources(), R.drawable.a) .getWidth();// 獲取圖片寬度 DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); int screenW = dm.widthPixels;// 獲取解析度寬度 offset = (screenW / viewList.size() - bmpw) / 2;// 計算偏移量 Matrix matrix = new Matrix(); matrix.postTranslate(offset, 0); cursor.setImageMatrix(matrix);// 設定動畫初始位置 } //頁面改變監聽器 public class MyPageChangeListener implements OnPageChangeListener { int one = offset * 2 + bmpw;// 頁卡1 -> 頁卡2 偏移量 int two = one * 2;// 頁卡1 -> 頁卡3 偏移量 @Override public void onPageSelected(int arg0) { Animation animation = null; switch (arg0) { case 0: if (currIndex == 1) { animation = new TranslateAnimation(one, 0, 0, 0); } else if (currIndex == 2) { animation = new TranslateAnimation(two, 0, 0, 0); } break; case 1: if (currIndex == 0) { animation = new TranslateAnimation(offset, one, 0, 0); } else if (currIndex == 2) { animation = new TranslateAnimation(two, one, 0, 0); } break; case 2: if (currIndex == 0) { animation = new TranslateAnimation(offset, two, 0, 0); } else if (currIndex == 1) { animation = new TranslateAnimation(one, two, 0, 0); } break; } currIndex = arg0; animation.setFillAfter(true);// True:圖片停在動畫結束位置 animation.setDuration(300); cursor.startAnimation(animation); } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageScrollStateChanged(int arg0) { } } /** * ViewPager介面卡 */ public class MyPagerAdapter extends PagerAdapter { public List<View> mListViews; public MyPagerAdapter(List<View> mListViews) { this.mListViews = mListViews; } @Override public boolean isViewFromObject(View arg0, Object arg1) { // TODO Auto-generated method stub return arg0 == arg1; } @Override public int getCount() { // TODO Auto-generated method stub return mListViews.size(); } @Override public void destroyItem(ViewGroup container, int position, Object object) { // TODO Auto-generated method stub container.removeView(mListViews.get(position)); } @Override public Object instantiateItem(ViewGroup container, int position) { // TODO Auto-generated method stub container.addView(mListViews.get(position)); return mListViews.get(position); } } }
1、MyPagerAdapter類
在前幾篇中,我們對於介面卡的實現總是new一個PageAdapter的例項。我們這裡做了一點稍微的更改,將其集合成一個類,內容都沒變,只是多了一個建構函式而已。所以針對這個類的具體程式碼,我就不再細講,如果對其中的複寫的函式為什麼要這麼寫不理解的同學,請看《ViewPager 詳解(二)---詳解四大函式》
2、initCursorPos()---初始化指示器位置
遊標在初始化顯示時,我們要根據螢幕寬度來顯示遊標位置。先看看這部分程式碼:
//初始化指示器位置 public void initCursorPos() { // 初始化動畫 cursor = (ImageView) findViewById(R.id.cursor); bmpw = BitmapFactory.decodeResource(getResources(), R.drawable.a) .getWidth();// 獲取圖片寬度 DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); int screenW = dm.widthPixels;// 獲取解析度寬度 offset = (screenW / viewList.size() - bmpw) / 2;// 計算偏移量 Matrix matrix = new Matrix(); matrix.postTranslate(offset, 0); cursor.setImageMatrix(matrix);// 設定動畫初始位置 }
可能有些同學不明白的位置在於,初始化位置的偏移量為什麼這麼算,下面,我畫了張圖,看下就應該明白了。
最後對於偏移的方法,可用的很多,這裡仿網上的程式碼用了matrix;當然大家可以用其它的偏移方法,一樣。
3、MyPageChangeListener()---頁面改變監聽器
程式碼如下 :
public class MyPageChangeListener implements OnPageChangeListener {
int one = offset * 2 + bmpw;// 頁卡1 -> 頁卡2 偏移量
int two = one * 2;// 頁卡1 -> 頁卡3 偏移量
@Override
public void onPageSelected(int arg0) {
Animation animation = null;
switch (arg0) {
case 0:
if (currIndex == 1) {
animation = new TranslateAnimation(one, 0, 0, 0);
} else if (currIndex == 2) {
animation = new TranslateAnimation(two, 0, 0, 0);
}
break;
case 1:
if (currIndex == 0) {
animation = new TranslateAnimation(offset, one, 0, 0);
} else if (currIndex == 2) {
animation = new TranslateAnimation(two, one, 0, 0);
}
break;
case 2:
if (currIndex == 0) {
animation = new TranslateAnimation(offset, two, 0, 0);
} else if (currIndex == 1) {
animation = new TranslateAnimation(one, two, 0, 0);
}
break;
}
currIndex = arg0;
animation.setFillAfter(true);// True:圖片停在動畫結束位置
animation.setDuration(300);
cursor.startAnimation(animation);
}
原理是這樣,根據滑動到的頁面,把遊標滑動找指定位置。這裡可能有難度的地方在於,數學……
我畫了一張圖,解釋從第一個頁面到第二個頁面時的距離為什麼是“遊標寬度+offset*2”,其它距離類似。
這篇就到這了,時間比較緊,而且這個難度不太大,講的可能不太細。
原始碼中,給大家列出了一個有Tab互動的Demo,圖片如下:
相關文章:
原始碼包含:
1、TestViewPage_scroll_cursor:文中示例原始碼
2、DWinterTabDemo:帶Tab互動的Demo
相關推薦
ViewPager 詳解(四)----自主實現滑動指示條
前言:前面我們用了三篇的時間講述了有關ViewPager的基礎知識,到這篇就要進入點實際的了。在第三篇《ViewPager 詳解(三)---PagerTabStrip與PagerTitleStrip新增標題欄的異同》中,我們說了,PagerTabStrip和PagerTitl
ViewPager 詳解(四)—-自主實現滑動指示條
前言:前面我們用了三篇的時間講述了有關ViewPager的基礎知識,到這篇就要進入點實際的了。在第三篇《ViewPager 詳解(三)—PagerTabStrip與PagerTitleStrip新增標題欄的異同》中,我們說了,PagerTabStrip和Page
郵件實現詳解(四)------JavaMail 發送(帶圖片和附件)和接收郵件
發送 網絡圖 發送對象 true n) com 訪問權限 sub map 好了,進入這個系列教程最主要的步驟了,前面郵件的理論知識我們都了解了,那麽這篇博客我們將用代碼完成郵件的發送。這在實際項目中應用的非常廣泛,比如註冊需要發送郵件進行賬號激活,再比如OA項目中利用郵
實現螢幕切換、滑動-ViewPager詳解(二)之--------PagerTitleStrip與PagerTabStrip新增標題欄
PagerTabStrip 1.PagerTabStrip概述:(API解釋) PagerTabStrip是ViewPager的一個關於當前頁面、上一個頁面和下一個頁面的一個非互動的指示器。它經常作為ViewPager控制元件的一個子控制元件被被新增
HTTP詳解(四):JAVA實現HTTP請求
通過上幾篇的文章,我們對HTTP已經已經有了一個初步的認識,對於"為什麼要用HTTP","怎麼用HTTP","HTTP是什麼"相信大家都有了一個了一個屬於自己的看法,今天這篇文章主要是程式碼的角度上去實現HTTP的請求。
PullScrollView詳解(四)——完全使用listview實現下拉回彈(方法一)
在前面三篇中,我為大家展示了使用ScrollView實現下拉回彈的效果。但如果ScrollView裡如果巢狀使用ListView就可能會出現問題,因為兩者都會有滑動監聽。操作起來可能會起衝突,然後解決了衝突問題,到後面頁面效能也會很差強人意。即然如此,那我們就直接使用
elastic-job詳解(四):失效轉移
shard out utm monit 設置 borde 點滴 title 等於 elastic-job中最關鍵的特性之一就是失效轉移。配置了失效轉移之後,如果在任務執行過程中有一個執行實例掛了,那麽之前被分配到這個實例的任務(或者分片)會在下次任務執行之前被重新分配到其他
Quartz學習——SSMM(Spring+SpringMVC+Mybatis+Mysql)和Quartz集成詳解(四)
webapp cron表達式 msi 接口 cli post 定時 報錯 gets Quartz學習——SSMM(Spring+SpringMVC+Mybatis+Mysql)和Quartz集成詳解(四) 當任何時候覺你得難受了,其實你的大腦是在進化,當任何時候你覺得
07-Linux中DNS詳解(四)
用戶 mail all 驗證 src 更改 條目 http nslookup 接“06-Linux中DNS詳解(三)” 九、配置主從DNS服務器實現域名解析容錯 1、實驗環境zhangyujia.com(192.168.80.100)為主區域,com(192.168.8
編碼原理詳解(四)---之字形掃描
便是 集中 img 詳解 工作 -- 漢字 如何 編碼原理 上一篇我們講到,經過量化後得到了諸多零值和整數值,本篇接下來講講編碼過程中過對這些值如何組織和處理,那就是ZigZag掃描嘍。 一、簡介 ZigZag掃描也稱作之字形掃描,何以得此稱謂,是因為其掃描的路徑特
Nginx詳解(四)模塊
nginx https fastcgi 一、Nginx之目錄瀏覽二、Nginx之log模塊三、Ning之gzip模塊四、Nginx之https服務五、Nginx之fastCGI模塊 一、配置Nginx提供目錄瀏覽功能 1.修改nginx配置文件 server { listen
Zookeeper詳解(四):Zookeeper中的zkCli.sh客戶端使用
zkCli.sh zookeeper客戶端 最好配置上環境變量連接操作:zkCli.sh -timeout 1000 -r -server 127.0.0.1 # -timeout 設置客戶端和服務器之間的超時時長,單位毫秒 # -r 只讀模式,不加就是讀寫模式 # -server IP:PORT 要
Keepalived詳解(四)
mysql pan 節點 ios all -s 關閉 定義 interval 一.通過vrrp_script實現對集群資源的監控: Keepalived基礎HA功能時用到了vrrp_script這個模塊,此模塊專門用於對集群中服務資源進行監控。與此模塊一起使用
PE文件格式詳解(四)
ebs 位置 數位 地址 inf font pe文件 。。 地址轉換 PE文件格式詳解(四) 0x00 前言 上一篇介紹了區塊表的信息,以及如何在hexwrokshop找到區塊表。接下來,我們繼續深入了解區塊,並且學會文件偏移和虛擬地址轉換的知識。 0x01 區塊對齊值
PE檔案格式詳解(四)
PE檔案格式詳解(四) 0x00 前言 上一篇介紹了區塊表的資訊,以及如何在hexwrokshop找到區塊表。接下來,我們繼續深入瞭解區塊,並且學會檔案偏移和虛擬地址轉換的知識。 0x01 區塊對齊值 首先我們要知道啥事區塊對齊?為啥要區塊對齊?這個問題
安卓專案實戰之強大的網路請求框架okGo使用詳解(四):Cookie的管理
Cookie概念相關 具體來說cookie機制採用的是在客戶端保持狀態的方案,而session機制採用的是在伺服器端保持狀態的方案。同時我們也看到,由於採用伺服器端保持狀態的方案在客戶端也需要儲存一個標識,所以session機制是需要藉助於cookie機制來達到儲存標識的目的,所謂ses
安卓專案實戰之強大的網路請求框架okGo使用詳解(一):實現get,post基本網路請求,下載上傳進度監聽以及對Callback自定義的深入理解
1.新增依賴 //必須使用 compile 'com.lzy.net:okgo:3.0.4' //以下三個選擇新增,okrx和okrx2不能同時使用,一般選擇新增最新的rx2支援即可 compile 'com.lzy.net:okrx:1.0.2' compile 'com.lzy
【SpringBoot學習之路】08.Springboot配置檔案詳解(四)
轉載宣告:商業轉載請聯絡作者獲得授權,非商業轉載請註明出處.原文來自 © 呆萌鍾【SpringBoot學習之路】08.Springboot配置檔案詳解(四) 自動配置原理 配置檔案到底能寫什麼?怎麼寫?自動配置原理; 配置檔案能配置的屬性參照
Java 反射機制詳解(四)
Java 反射機制詳解(四) 4. 反射與泛型 定義一個泛型類: public class DAO<T> { //根據id獲取一個物件 T get(Integer id){ return null; }