亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android自定義ViewPager實(shí)現(xiàn)個(gè)性化的圖片切換效果

 更新時(shí)間:2016年05月24日 15:25:54   作者:鴻洋_  
這篇文章主要介紹了Android自定義ViewPager實(shí)現(xiàn)個(gè)性化的圖片切換效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

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

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

是不是比傳統(tǒng)的效果個(gè)性很多,嘿嘿~~其實(shí)很簡(jiǎn)單,學(xué)習(xí)完這篇文章,保證你可以自定義切換效果,做出各式各樣的效果。
1、制作前的分析
觀察下效果圖,實(shí)際上改變的就是切換時(shí)的動(dòng)畫,那么簡(jiǎn)單了,只需要用戶在切換時(shí),拿到當(dāng)前的View和下一個(gè)View,然后添加動(dòng)畫是不是就可以了。

第一步,獲取用戶切換時(shí)的當(dāng)前View和切換至的目的View。
我們?cè)趤砜匆幌?,如果或者了?dāng)前View和目的View,對(duì)于動(dòng)畫我們需要緩慢的變化,最好是根據(jù)用戶的手勢(shì)滑動(dòng)。比如上述效果,用戶滑動(dòng)時(shí),目的圖片根據(jù)用戶滑動(dòng)距離緩緩出現(xiàn)和慢慢變大。

第二步,設(shè)計(jì)動(dòng)畫的梯度變化。

經(jīng)過分析,我們總結(jié)出兩個(gè)步驟,下面我們開始一步一步來打造千變?nèi)f化的圖片切換效果

2、獲取用戶切換時(shí)當(dāng)前View和切換至的目的View。ViewPager也需要監(jiān)聽用戶的手勢(shì),所以肯定提供了某個(gè)方法。于是縱觀ViewPager的方法,發(fā)現(xiàn)了一個(gè)叫做 onPageScrolled(int position, float positionOffset, int positionOffsetPixels)的方法~~
沒錯(cuò)就是這個(gè)方法:在頁(yè)面滾動(dòng)時(shí)調(diào)用~
下面仔細(xì)研究下這幾個(gè)參數(shù):
直接說測(cè)試結(jié)果:
在非第一頁(yè)與最后一頁(yè)時(shí),滑動(dòng)到下一頁(yè),position為當(dāng)前頁(yè)位置;滑動(dòng)到上一頁(yè):position為當(dāng)前頁(yè)-1
positionOffset 滑動(dòng)到下一頁(yè),[0,1)區(qū)間上變化;滑動(dòng)到上一頁(yè):(1,0]區(qū)間上變化
positionOffsetPixels這個(gè)和positionOffset很像:滑動(dòng)到下一頁(yè),[0,寬度)區(qū)間上變化;滑動(dòng)到上一頁(yè):(寬度,0]區(qū)間上變化
第一頁(yè)時(shí):滑動(dòng)到上一頁(yè)position=0 ,其他基本為0 ;最后一頁(yè)滑動(dòng)到下一頁(yè) position為當(dāng)前頁(yè)位置,其他兩個(gè)參數(shù)為0

豁然發(fā)現(xiàn),我們需要的步驟的第二步解決了,positionOffset很適合作為,漸變,縮放的控制參數(shù);positionOffsetPixels則可以作為平移等的控制參數(shù)。
那么如何獲得當(dāng)前View和目的View呢:
分享幾個(gè)我的歧途:
1、【錯(cuò)誤】我通過getChildAt(position),getChildAt(position+1),getChildAt(position-1)獲得滑動(dòng)時(shí),左右的兩個(gè)View;乍一看,還真覺得不錯(cuò)~~~在代碼寫出來,再乍效果也出不來~~錯(cuò)誤原因:我們忽略一個(gè)特別大的東西,ViewPager的機(jī)制,滑動(dòng)時(shí)動(dòng)態(tài)加載和刪除View,ViewPager其實(shí)只會(huì)維持2到3個(gè)View,而position的范圍基本屬于無限~~
2、【錯(cuò)誤】我通過getCurrentItem獲得當(dāng)前的位置,然后+1,-1獲得后一個(gè)或者前一個(gè)~~正在竊喜,趕快代碼改過來,效果怎么也不對(duì),亂七八糟的~~仔細(xì)觀察日志,這個(gè)getCurrentItem當(dāng)用戶手指離開的屏幕,Page還在動(dòng)畫執(zhí)行時(shí),就改變了~~難怪~整個(gè)滑動(dòng)過程并不是固定的~~唉,心都碎了~
3、【錯(cuò)誤】position在整個(gè)滑動(dòng)的過程中是不變化的,而且ViewPager會(huì)保存2個(gè)或3個(gè)View;那么我考慮,如果是第一頁(yè)、或者最后一頁(yè)那么我取getChildAt(0)和getChildAt(1),如果在其他頁(yè)面則為getChildAt(0),getChildAt(2),然后經(jīng)過一系列的變化~我想這會(huì)總該對(duì)了吧,于是我遇到第一問題,第一頁(yè)的時(shí)候,不管左右position都為0,尼瑪,這哪個(gè)為左View,哪個(gè)為右View~~
說了這么多錯(cuò)誤,大家可以繞過這些彎路,也能從這些彎路里面看出點(diǎn)什么~
下面說正確的,其實(shí)ViewPager在添加一個(gè)View或者銷毀一個(gè)View時(shí),是我們自己的PageAdapter中控制的,于是我們可以在ViewPager里面維系一個(gè)HashMap<Position,View>,然后滑動(dòng)的時(shí)候,通過get(position)取出,比如上述效果,始終是右邊的View變化,要么從小到大,要么從大到小
那么滑倒下一頁(yè):左邊的View:map.get(position) ,右邊的View : map.get(position+1) .
那么滑倒上一頁(yè):左邊的View : map.get(position) , 右邊的View : map.get(position+1) , 一樣的,因?yàn)榛缴弦豁?yè),position為當(dāng)前頁(yè)-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; 
  } 
 }); 
 
 } 
 
} 

這個(gè)很常見的代碼,就是初始化ViewPager~~就沒啥可說的了~~有一點(diǎn)需要注意:在instantiateItem方法,我們多調(diào)用了一個(gè)mViewPager.setObjectForPosition(imageView, position);其實(shí)就是為了給我們的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與對(duì)于的View 
 */ 
 private HashMap<Integer, View> mChildrenViews = new LinkedHashMap<Integer, View>(); 
 /** 
 * 滑動(dòng)時(shí)左邊的元素 
 */ 
 private View mLeft; 
 /** 
 * 滑動(dòng)時(shí)右邊的元素 
 */ 
 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()); 
  
 //滑動(dòng)特別小的距離時(shí),我們認(rèn)為沒有動(dòng),可有可無的判斷 
 float effectOffset = isSmall(positionOffset) ? 0 : positionOffset; 
  
 //獲取左邊的View 
 mLeft = findViewFromObject(position); 
 //獲取右邊的View 
 mRight = findViewFromObject(position + 1); 
  
 // 添加切換動(dòng)畫效果 
 animateStack(mLeft, mRight, effectOffset, positionOffsetPixels); 
 super.onPageScrolled(position, positionOffset, positionOffsetPixels); 
 } 
 
 public void setObjectForPosition(View view, int position) 
 { 
 mChildrenViews.put(position, view); 
 } 
 
 /** 
 * 通過過位置獲得對(duì)應(yīng)的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) 
 { 
  /** 
  * 縮小比例 如果手指從右到左的滑動(dòng)(切換到后一個(gè)):0.0~1.0,即從一半到最大 
  * 如果手指從左到右的滑動(dòng)(切換到前一個(gè)):1.0~0,即從最大到一半 
  */ 
  mScale = (1 - SCALE_MAX) * effectOffset + SCALE_MAX; 
  /** 
  * x偏移量: 如果手指從右到左的滑動(dòng)(切換到后一個(gè)):0-720 如果手指從左到右的滑動(dòng)(切換到前一個(gè)):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,然后添加動(dòng)畫效果;當(dāng)前這個(gè)例子添加了兩個(gè)動(dòng)畫,一個(gè)是從0.5放大到1.0或者1.0縮小到0.5,沒錯(cuò)由我們的positionOffset提供梯度的變化~~還有個(gè)平移的動(dòng)畫:下一頁(yè)直接移動(dòng)到當(dāng)前屏幕(默認(rèn)是在右邊,可以注釋這個(gè)效果,怎么運(yùn)行看看),然后不斷的通過positionOffsetPixels抵消原來默認(rèn)移動(dòng)時(shí)的位移,讓用戶感覺它就在原地放大縮小~~
好了,這樣就實(shí)現(xiàn)了~~你可以隨便寫自己喜歡的動(dòng)畫效果,比如在默認(rèn)上面加個(gè)淡入淡出或者神馬,隨便~~是不是很隨意~~
我們的布局文件:

<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" 
 > 
 
 <com.example.zhy_jazzyviewpager.MyJazzyViewPager 
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content" 
 android:id="@+id/id_viewPager" /> 
 
</RelativeLayout> 

4、JazzyViewPager的使用
其實(shí)上面的實(shí)現(xiàn)就是github上JazzyViewPager的源碼,用法不用說了,就是我們的MainActivity,它內(nèi)置了大概10來種效果,我們可以通過代碼或者布局上面設(shè)置動(dòng)畫效果~~我們上面的例子效果,它叫做Stack;
使用JazzViewPager的代碼:其實(shí)基本一樣~~最后也會(huì)貼上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); 
 //設(shè)置切換效果 
 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; 
  } 
 }); 
 
 } 
 
} 

與我們的代碼唯一區(qū)別就是:
//設(shè)置切換效果
mViewPager.setTransitionEffect(TransitionEffect.Stack);

它有12種可選的切換效果,其實(shí)就是寫了12個(gè)切換的動(dòng)畫~~~
好了,最后附上一個(gè)我比較喜歡的效果:Tablet

源碼下載: ViewPager圖片切換

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家學(xué)習(xí)Android軟件編程有所幫助。

相關(guān)文章

最新評(píng)論