日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android如何自定义viewpager,Android自定义ViewPager实现个性化的图片切换效果

發布時間:2025/4/5 Android 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android如何自定义viewpager,Android自定义ViewPager实现个性化的图片切换效果 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第一次見到ViewPager這個控件,瞬間愛不釋手,做東西的主界面通通ViewPager,以及圖片切換也拋棄了ImageSwitch之類的,開始讓ViewPager來做。時間長了,ViewPager的切換效果覺得枯燥,形成了審美疲勞~~我們需要改變,今天教大家如何改變ViewPager切換時的效果,實現個性化的圖片切換

看一下這樣效果的圖片切換:

是不是比傳統的效果個性很多,嘿嘿~~其實很簡單,學習完這篇文章,保證你可以自定義切換效果,做出各式各樣的效果。

1、制作前的分析

觀察下效果圖,實際上改變的就是切換時的動畫,那么簡單了,只需要用戶在切換時,拿到當前的View和下一個View,然后添加動畫是不是就可以了。

第一步,獲取用戶切換時的當前View和切換至的目的View。

我們在來看一下,如果或者了當前View和目的View,對于動畫我們需要緩慢的變化,最好是根據用戶的手勢滑動。比如上述效果,用戶滑動時,目的圖片根據用戶滑動距離緩緩出現和慢慢變大。

第二步,設計動畫的梯度變化。

經過分析,我們總結出兩個步驟,下面我們開始一步一步來打造千變萬化的圖片切換效果

2、獲取用戶切換時當前View和切換至的目的View。ViewPager也需要監聽用戶的手勢,所以肯定提供了某個方法。于是縱觀ViewPager的方法,發現了一個叫做 onPageScrolled(int position, float positionOffset, int positionOffsetPixels)的方法~~

沒錯就是這個方法:在頁面滾動時調用~

下面仔細研究下這幾個參數:

直接說測試結果:

在非第一頁與最后一頁時,滑動到下一頁,position為當前頁位置;滑動到上一頁:position為當前頁-1

positionOffset 滑動到下一頁,[0,1)區間上變化;滑動到上一頁:(1,0]區間上變化

positionOffsetPixels這個和positionOffset很像:滑動到下一頁,[0,寬度)區間上變化;滑動到上一頁:(寬度,0]區間上變化

第一頁時:滑動到上一頁position=0 ,其他基本為0 ;最后一頁滑動到下一頁 position為當前頁位置,其他兩個參數為0

豁然發現,我們需要的步驟的第二步解決了,positionOffset很適合作為,漸變,縮放的控制參數;positionOffsetPixels則可以作為平移等的控制參數。

那么如何獲得當前View和目的View呢:

分享幾個我的歧途:

1、【錯誤】我通過getChildAt(position),getChildAt(position+1),getChildAt(position-1)獲得滑動時,左右的兩個View;乍一看,還真覺得不錯~~~在代碼寫出來,再乍效果也出不來~~錯誤原因:我們忽略一個特別大的東西,ViewPager的機制,滑動時動態加載和刪除View,ViewPager其實只會維持2到3個View,而position的范圍基本屬于無限~~

2、【錯誤】我通過getCurrentItem獲得當前的位置,然后+1,-1獲得后一個或者前一個~~正在竊喜,趕快代碼改過來,效果怎么也不對,亂七八糟的~~仔細觀察日志,這個getCurrentItem當用戶手指離開的屏幕,Page還在動畫執行時,就改變了~~難怪~整個滑動過程并不是固定的~~唉,心都碎了~

3、【錯誤】position在整個滑動的過程中是不變化的,而且ViewPager會保存2個或3個View;那么我考慮,如果是第一頁、或者最后一頁那么我取getChildAt(0)和getChildAt(1),如果在其他頁面則為getChildAt(0),getChildAt(2),然后經過一系列的變化~我想這會總該對了吧,于是我遇到第一問題,第一頁的時候,不管左右position都為0,尼瑪,這哪個為左View,哪個為右View~~

說了這么多錯誤,大家可以繞過這些彎路,也能從這些彎路里面看出點什么~

下面說正確的,其實ViewPager在添加一個View或者銷毀一個View時,是我們自己的PageAdapter中控制的,于是我們可以在ViewPager里面維系一個HashMap,然后滑動的時候,通過get(position)取出,比如上述效果,始終是右邊的View變化,要么從小到大,要么從大到小

那么滑倒下一頁:左邊的View:map.get(position) ,右邊的View : map.get(position+1) .

那么滑倒上一頁:左邊的View : map.get(position) , 右邊的View : map.get(position+1) , 一樣的,因為滑到上一頁,position為當前頁-1

好了,至此,我們分析了且解決了所有步驟。

3、代碼MainActivity

package com.example.zhy_jazzyviewpager;

import android.app.Activity;

import android.os.Bundle;

import android.support.v4.view.PagerAdapter;

import android.view.Menu;

import android.view.View;

import android.view.ViewGroup;

import android.widget.ImageView;

import android.widget.ImageView.ScaleType;

public class MainActivity extends Activity

{

protected static final String TAG = "MainActivity";

private int[] mImgIds;

private MyJazzyViewPager mViewPager;

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mImgIds = new int[] { R.drawable.a, R.drawable.b, R.drawable.c,

R.drawable.d };

mViewPager = (MyJazzyViewPager) findViewById(R.id.id_viewPager);

mViewPager.setAdapter(new PagerAdapter()

{

@Override

public boolean isViewFromObject(View arg0, Object arg1)

{

return arg0 == arg1;

}

@Override

public void destroyItem(ViewGroup container, int position,

Object object)

{

container.removeView((View) object);

}

@Override

public Object instantiateItem(ViewGroup container, int position)

{

ImageView imageView = new ImageView(MainActivity.this);

imageView.setImageResource(mImgIds[position]);

imageView.setScaleType(ScaleType.CENTER_CROP);

container.addView(imageView);

mViewPager.setObjectForPosition(imageView, position);

return imageView;

}

@Override

public int getCount()

{

return mImgIds.length;

}

});

}

}

這個很常見的代碼,就是初始化ViewPager~~就沒啥可說的了~~有一點需要注意:在instantiateItem方法,我們多調用了一個mViewPager.setObjectForPosition(imageView, position);其實就是為了給我們的Map存值

主要看自定義的ViewPager

package com.example.zhy_jazzyviewpager;

import java.util.HashMap;

import java.util.LinkedHashMap;

import android.content.Context;

import android.support.v4.view.ViewPager;

import android.util.AttributeSet;

import android.util.Log;

import android.view.View;

import com.nineoldandroids.view.ViewHelper;

public class MyJazzyViewPager extends ViewPager

{

private float mTrans;

private float mScale;

/**

* 最大的縮小比例

*/

private static final float SCALE_MAX = 0.5f;

private static final String TAG = "MyJazzyViewPager";

/**

* 保存position與對于的View

*/

private HashMap mChildrenViews = new LinkedHashMap();

/**

* 滑動時左邊的元素

*/

private View mLeft;

/**

* 滑動時右邊的元素

*/

private View mRight;

public MyJazzyViewPager(Context context, AttributeSet attrs)

{

super(context, attrs);

}

@Override

public void onPageScrolled(int position, float positionOffset,

int positionOffsetPixels)

{

// Log.e(TAG, "position=" + position+", positionOffset = "+positionOffset+" ,positionOffsetPixels = " + positionOffsetPixels+" , currentPos = " + getCurrentItem());

//滑動特別小的距離時,我們認為沒有動,可有可無的判斷

float effectOffset = isSmall(positionOffset) ? 0 : positionOffset;

//獲取左邊的View

mLeft = findViewFromObject(position);

//獲取右邊的View

mRight = findViewFromObject(position + 1);

// 添加切換動畫效果

animateStack(mLeft, mRight, effectOffset, positionOffsetPixels);

super.onPageScrolled(position, positionOffset, positionOffsetPixels);

}

public void setObjectForPosition(View view, int position)

{

mChildrenViews.put(position, view);

}

/**

* 通過過位置獲得對應的View

*

* @param position

* @return

*/

public View findViewFromObject(int position)

{

return mChildrenViews.get(position);

}

private boolean isSmall(float positionOffset)

{

return Math.abs(positionOffset) < 0.0001;

}

protected void animateStack(View left, View right, float effectOffset,

int positionOffsetPixels)

{

if (right != null)

{

/**

* 縮小比例 如果手指從右到左的滑動(切換到后一個):0.0~1.0,即從一半到最大

* 如果手指從左到右的滑動(切換到前一個):1.0~0,即從最大到一半

*/

mScale = (1 - SCALE_MAX) * effectOffset + SCALE_MAX;

/**

* x偏移量: 如果手指從右到左的滑動(切換到后一個):0-720 如果手指從左到右的滑動(切換到前一個):720-0

*/

mTrans = -getWidth() - getPageMargin() + positionOffsetPixels;

ViewHelper.setScaleX(right, mScale);

ViewHelper.setScaleY(right, mScale);

ViewHelper.setTranslationX(right, mTrans);

}

if (left != null)

{

left.bringToFront();

}

}

}

可以看到,核心代碼都是onPageScrolled,我們通過findViewFromObject(position); findViewFromObject(position + 1);分別獲取了左右兩邊的View,然后添加動畫效果;當前這個例子添加了兩個動畫,一個是從0.5放大到1.0或者1.0縮小到0.5,沒錯由我們的positionOffset提供梯度的變化~~還有個平移的動畫:下一頁直接移動到當前屏幕(默認是在右邊,可以注釋這個效果,怎么運行看看),然后不斷的通過positionOffsetPixels抵消原來默認移動時的位移,讓用戶感覺它就在原地放大縮小~~

好了,這樣就實現了~~你可以隨便寫自己喜歡的動畫效果,比如在默認上面加個淡入淡出或者神馬,隨便~~是不是很隨意~~

我們的布局文件:

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:id="@+id/id_viewPager" />

4、JazzyViewPager的使用其實上面的實現就是github上JazzyViewPager的源碼,用法不用說了,就是我們的MainActivity,它內置了大概10來種效果,我們可以通過代碼或者布局上面設置動畫效果~~我們上面的例子效果,它叫做Stack;

使用JazzViewPager的代碼:其實基本一樣~~最后也會貼上JazzyViewPager的源碼的下載

MainActivity

package com.jfeinstein.jazzyviewpager;

import com.jfeinstein.jazzyviewpager.JazzyViewPager.TransitionEffect;

import android.app.Activity;

import android.os.Bundle;

import android.support.v4.view.PagerAdapter;

import android.view.View;

import android.view.ViewGroup;

import android.widget.ImageView;

import android.widget.ImageView.ScaleType;

public class MainActivity extends Activity

{

protected static final String TAG = "MainActivity";

private int[] mImgIds;

private JazzyViewPager mViewPager;

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mImgIds = new int[] { R.drawable.a, R.drawable.b, R.drawable.c,

R.drawable.d };

mViewPager = (JazzyViewPager) findViewById(R.id.id_viewPager);

//設置切換效果

mViewPager.setTransitionEffect(TransitionEffect.Stack);

mViewPager.setAdapter(new PagerAdapter()

{

@Override

public boolean isViewFromObject(View arg0, Object arg1)

{

return arg0 == arg1;

}

@Override

public void destroyItem(ViewGroup container, int position,

Object object)

{

container.removeView((View) object);

}

@Override

public Object instantiateItem(ViewGroup container, int position)

{

ImageView imageView = new ImageView(MainActivity.this);

imageView.setImageResource(mImgIds[position]);

imageView.setScaleType(ScaleType.CENTER_CROP);

container.addView(imageView);

mViewPager.setObjectForPosition(imageView, position);

return imageView;

}

@Override

public int getCount()

{

return mImgIds.length;

}

});

}

}

與我們的代碼唯一區別就是:

//設置切換效果

mViewPager.setTransitionEffect(TransitionEffect.Stack);

它有12種可選的切換效果,其實就是寫了12個切換的動畫~~~

好了,最后附上一個我比較喜歡的效果:Tablet

以上就是本文的全部內容,希望對大家學習Android軟件編程有所幫助。

總結

以上是生活随笔為你收集整理的android如何自定义viewpager,Android自定义ViewPager实现个性化的图片切换效果的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。