androidviewpager自定義
A. android viewpager怎麼用
一. 導入ViewPager第三方jar包android-support-v13.jar
在開發之前先在已經創建好的應用程序工程中導入jar包,方法如下:
選中應用程序工程,在eclipse的菜單欄選擇Project->properties->java Build Path->Libraries->Add External Jars中加入已經下載好的jar包。加入這個jar包之後就可以使用ViewPager類來開發相關的應用了。
舉一反三,其它第三方jar包的添加應該也是走這個步驟。
二. ViewPager的使用
下面以一個簡單的demo來實現ViewPager的使用,該Demo的效果圖如下:
該Demo總共四個頁面,每個頁面用一個Fragment來實現,所以分別創建FirstFragmentPage、SecondFragmentPage、ThirdFragmentPage、ForthFragmentPage四個類來實現四個頁面,這個四個類都繼承Fragment。這四個Fragment將在MainActivity中添加處理。以下主要代碼實現:
1. 主布局文件main.xml代碼如下:
[html] view plain
<?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" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<!-- ViewPager界面布局 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="50dip" >
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<!-- 指示圖標和按鈕的布局 -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="vertical" >
<!-- ViewPager界面下方的指示翻頁圖標 -->
<LinearLayout
android:id="@+id/indicator_group"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dip"
android:gravity="center"
android:orientation="horizontal" >
</LinearLayout>
<!-- 底部的後退和前進按鈕布局 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="30dip"
android:paddingRight="30dip" >
<Button
android:id="@+id/back_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/back" />
<Button
android:id="@+id/next_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/next" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
2. MainActivity:
[java] view plain
package com.stevenhu.vpt;
import java.util.ArrayList;
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.support.v13.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class MainActivity extends Activity implements OnClickListener
{
private final static String TAG = "MainActivity";
private ViewPager mViewPager;
private ViewPagerAdapter mViewPagerAdapter;
private LinearLayout mIndicatorGroup;
//定義指示翻頁圖標數組
private ImageView[] mIndicatorImage;
private Button mBackButton, mNextButton;
//定義當前在第幾頁
private int mCurrentPage = 0;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mViewPager = (ViewPager)findViewById(R.id.viewpager);
//創建自定義的ViewPagerAdapter對象
mViewPagerAdapter = new ViewPagerAdapter(this, mViewPager);
//添加Fragment
mViewPagerAdapter.addFragment(FirstFragmentPage.class, null);
mViewPagerAdapter.addFragment(SecondFragmentPage.class, null);
mViewPagerAdapter.addFragment(ThirdFragmentPage.class, null);
mViewPagerAdapter.addFragment(ForthFragmentPage.class, null);
//獲取指示器圖標所在界面布局對象
mIndicatorGroup = (LinearLayout)findViewById(R.id.indicator_group);
mIndicatorImage = new ImageView[mViewPagerAdapter.getCount()];
mBackButton = (Button)findViewById(R.id.back_button);
mNextButton = (Button)findViewById(R.id.next_button);
mBackButton.setOnClickListener(this);
mNextButton.setOnClickListener(this);
initIndicator();
}
//初始化指示器,實現隨著創建頁數的增加從而添加相應個數的指示圖標。
private void initIndicator()
{
for (int i = 0; i < mViewPagerAdapter.getCount(); i ++)
{
ImageView imageView = new ImageView(this);
imageView.setLayoutParams(new ViewGroup.LayoutParams(20,20));
imageView.setPadding(20, 0, 20, 0);
if (i == 0)
{
imageView.setBackgroundResource(R.drawable.page_indicator_focused);
}
else
{
imageView.setBackgroundResource(R.drawable.page_indicator);
}
mIndicatorImage[i] = imageView;
mIndicatorGroup.addView(mIndicatorImage[i]);
}
}
http://blog.csdn.net/stevenhu_223/article/details/8024925
B. Android ViewPager 控制滑動速度
參考 《ViewPager smoothScroll 速度控制》 ,很不錯的文章,用Kotlin改寫記錄如下:
自定義滑動控制類,以實現自定義滑動
在自定義ViewPager中,通過反射,更改原生滑動控制類為自定義類
附ViewPager源碼:
見 自適應高度(最低高度為屏幕高度) & 橫屏閃退不拉長頁面 & 自定義滑動速度
C. android 自定義view可以用在viewpager上嗎
一部分:自定義ViewGroup的使用,手勢識別器和Scroller滑動
第二部分:處理滑動監聽,處理滑動沖突,增加ViewPager的指示器
基礎概念:
常見的滑動沖突:外部滑動方向和內部滑動方向不一致、外部滑動方向和內部滑動方向一致。
我們自定義的ViewPager如果在其中一頁中存在ListView,那麼就需要解決滑動沖突的問題。
由於系統自帶ViewPager中,自己已經解決了滑動沖突。
D. Android (基礎自定義組件)viewpagertap滑動器
視頻地址: http://www.imooc.com/learn/615
2.1.1主要定義畫筆、三角形使用path來實現。接著定義三角形的大小(寬高)以及初始化位置。
2.1.2設置mInitTranslationX參數,表示三角形初始化的位置,相當於marginLeft,計算方式是:
mInitTranslationX = 一個tab的寬度 - 三角形寬度的/2
2.1.3設置mTranslationX參數,表示每一移動一個tab時,三角形需要平移的寬度,如圖:
2.1.4 mTabVisibleCount,自定義屬性,布局中要顯示幾個tab,如上圖4個tab
2.2.1構造中主要獲取自定義屬性值,默認為4;以及設置畫筆
2.3.1三角形的寬度 = 一個tab寬度的1/6;如果覺得寬度的大小不合適, 可以改變1/6這個常量的比例
2.3.2三角形的高度 = 高度/2如圖:
2.4.1重寫父類dispatchDraw方法,此方法在invalidate()時,會重新執行
2.4.2通過 canvas.translate()設置三角形所在位置;X軸(上去看2.1.3),Y軸為但前組件的高度(最底部)。以及調用drawPath()方法使用畫筆。
2.5.1如標題主要是通過viewpager的position和positionOffset來計算mTranslationX的值;再通過scrollTo方法來平移但前組件,最後通過invalidate()方法重繪布局
2.5.2剩下的就是一些演算法和邏輯判斷
2.6.1獲取viewpager,監聽viewpager的滑動事件,自定義setScroll方法(2.5的方法)將但前position和滑動偏移量傳進去
2.6.2在此次以及監聽的viewpager的滑動事件,如果外界也需要監聽當前viewpager的話,會起沖突;此時就需要設置回調,對外提供介面
2.6.3setTextHighLight()方法設置選中的tab為高亮顏色
2.7.1獲取list集合,將每一個item設置成一個textview,再通過setTextItemOnclickEvent()方法設置點擊事件
3.1app:visible_tab_count自定義屬性;如果不設置默認為自定義組件的COUNT_TAB_VISIBLE變數值
http://pan..com/s/1qYGUTAW
http://pan..com/s/1slpi5v3
E. android viewpager如何動態添加頁面
動態創建Adapter即可。ViewPager的數據是通過PageAdapter來裝載的,刷新數據的方法有以下:
1. 調用adapter.notifyDataSetChanged(); 刷新控制項,但是要覆蓋PagerAdapter的getItemPosition方法,並返回 return POSITION_NONE;
2. 利用PagerAdapter的工作機制,就是PagerAdapter的執行順序, PagerAdapter作為ViewPager的適配器,無論ViewPager有多少頁,PagerAdapter在初始化時也只初始化開始的2個View,即調用2次instantiateItem方法。而接下來每當ViewPager滑動時,PagerAdapter都會調用destroyItem方法將距離該頁2個步幅以上的那個View銷毀,以此保證PagerAdapter最多隻管轄3個View,且當前View是3個中的中間一個,如果當前View缺少兩邊的View,那麼就instantiateItem,如里有超過2個步幅的就destroyItem。
3. 每當Adapter調用instantiateItem時,運用View.setTag方法將該View標識。當需要更新這個View的數據時,通過調用ViewPager.findViewWithTag方法找到相應的View,然後更新View中的數據。
F. android中在彈出的對話框中如何加viewpager
AlertDialog.Builderbuilder=newBuilder(this);
builder.setPositiveButton("確認",newOnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
dialog.dismiss();
finish();
}
});
builder.setNegativeButton("取消",newOnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
dialog.dismiss();
}
});
//填充布局
Viewinflate=LayoutInflater.from(this).inflate(R.layout.viewpager_layout,null);
...........
//setView這個方法把填充好的布局添加到對話框中
builder.setView(inflate);
builder.create().show();
G. Android-ViewPager源碼解析與性能優化
ViewPager高度設置為wrap_content或者具體的高度值無效,是因為ViewPager的onMeasure方法在度量寬高的時候,在方法體的最開始就直接調用了setMeasuredDimension()方法將自身的寬高度量,但是並沒有在其onMeasure()計算完其具體的子View的寬高之後,重新度量一次自身的寬高
從這里我們可以看到,ViewPager的寬高會受其父容器的寬高的限制,但是並不會因為自身子View的寬高而影響ViewPager的寬高。
看setMeasuredDimension的源碼調用可以看出,當父容器的高度確定時,ViewPager的寬高其實就是父容器的寬高,ViewPager就是在onMeasure方法一進來的時候就直接填充滿整個父容器的剩餘空間。在計算孩子節點之前,就已經計算好了ViewPager的寬高,在計算完孩子節點之後,並不會再去重新計算ViewPager的寬高。
自定義一個ViewPager,根據子View的寬高重新度量ViewPager的寬高。其實做法就是在自定義onMeasure的super.onMeasure(widthMeasureSpec, heightMeasureSpec);之前重新計算heightMeasureSpec,將原本ViewPager接收的父容器的限定的heightMeasureSpec替換成我們自定義的heightMeasureSpec。
但是這樣的做法,會有種問題,即在ViewPager的子View是採用LinearLayout作為根布局的時候,並且給LinearLayout設置了固定的高度值,那麼會出現ViewPager動態高度無效的問題
其實具體的做法,就是仿造measureChild的做法,自定義子View的heightMeasureSpec然後度量整個子View,其實子View的寬度也可以這樣做。
這里其實是源碼層做了限制,在setOffscreenPageLimit中設置了一個默認值,而這個默認值的大小為1
所以從這里可以看出,ViewPager的最小緩存的limit是1,而不能小於1,當小於1的時候就會被強制的設置為1。
而populate()函數就是用來處理ViewPager的緩存的。
populate()的生命周期是與Adapter的生命周期綁定的。
其實在setOffscreenPageLimit()的時候,調用的populate(),而populate()內部調用的
而pupulate(int newCurrentItem)方法在另一處調用的地方就是在setCurrentItem。
其實ViewPager緩存都是基於ItemInfo這個類來進行的,
看下ViewPager.addNewItem的源碼
其實ViewPager.addNewItem就是通過調用Adapter.instantiateItem來創建對應的View,並且將View保存到ItemInfo中的object屬性,並且判斷ViewPager緩存中是否已經有ItemInfo,如果沒有,則添加,如果有則做修改替換
從分析FragmentStatePagerAdapter來看,setUserVisibleHint方法會優先於Fragment的生命周期函數 執行。因為在FragmentStatePagerAdapter中提交事務,是在調用finishUpdate方法中進行的,只有提交事務的時候,才會去執行Fragment的生命周期。
FragmentStatePagerAdapter中的instantiateItem和destroyItem都實現了對fragment的事務的添加和刪除,而finishUpdate實現了事務的提交,所以在實現FragmentStatePagerAdapter的時候,並不需要重寫instantiateItem和destroyItem
H. Android 用自定義高度自適應的viewpager,在進行滑動的時候滑動很不順暢,有時根本劃不動,求大神幫忙下
自已重寫ViewPager就行了在onMeasure里做一下處理就可以實現自適應高度了.
主要是重寫onMeasure方法來實現的。源代碼已上傳附件。