Android 사용자 정의 ViewPager 맞 춤 형 이미지 전환 효과 구현

ViewPager 라 는 컨트롤 을 처음 봤 을 때 순간 손 을 떼 지 못 했 습 니 다.물건 을 만 드 는 메 인 인터페이스 가 ViewPager 와 그림 전환 도 ImageSwitch 같은 것 을 버 리 고 ViewPager 에 게 시 키 기 시 작 했 습 니 다.시간 이 지나 면서 ViewPager 의 전환 효과 가 지루 해 지고 심미 적 피로 가 형성 되 었 습 니 다~우 리 는 변화 가 필요 합 니 다.오늘 은 ViewPager 전환 시의 효 과 를 어떻게 바 꾸 고 개성 화 된 이미지 전환 을 실현 하 는 지 알려 드 립 니 다.
이러한 효과 의 그림 전환 을 보십시오:

전통 적 인 효과 보다 개성 이 많 지 않 습 니까?헤헤~~사실 간단 합 니 다.이 글 을 배우 고 나 면 전환 효 과 를 사용자 정의 하여 다양한 효 과 를 낼 수 있 습 니 다.
1.제작 전 분석
효과 도 를 살 펴 보면 실제 적 으로 바 뀐 것 은 전환 할 때의 애니메이션 입 니 다.그러면 간단 합 니 다.사용자 가 전환 할 때 현재 의 View 와 다음 View 를 받 은 다음 에 애니메이션 을 추가 하면 됩 니 다.
첫 번 째 단 계 는 사용자 가 전환 할 때의 현재 View 와 전환 할 목적 View 를 가 져 옵 니 다.
현재 View 와 목적 View 가 있 거나 애니메이션 에 대해 느 린 변화 가 필요 하 다 면 사용자 의 손짓 에 따라 미 끄 러 지 는 것 이 좋 습 니 다.예 를 들 어 상기 효과,사용자 가 미 끄 러 질 때 목적 사진 은 사용자 의 미끄럼 거리 에 따라 천천히 나타 나 고 점점 커진다.
두 번 째 단 계 는 애니메이션 의 경사도 변 화 를 디자인 한다.
분석 을 통 해 우 리 는 두 가지 절 차 를 정리 했다.다음은 우리 가 한 걸음 한 걸음 변화 하 는 이미지 전환 효 과 를 만 들 기 시작 했다.
2.사용자 전환 시 현재 View 와 전환 한 목적 View 를 가 져 옵 니 다.ViewPager 도 사용자 의 손짓 을 감청 해 야 하기 때문에 틀림없이 어떤 방법 을 제 공 했 을 것 이다.그래서 ViewPager 의 방법 을 살 펴 보면 onPageScrolled(int position,float position Offset,int position Offset Pixels)라 는 방법 을 발 견 했 습 니 다~~
맞아요.바로 이 방법 이에 요.페이지 가 굴 러 갈 때 호출~
다음은 이 몇 가지 매개 변 수 를 자세히 연구 해 보 겠 습 니 다.
테스트 결 과 를 직접 말 하 다.
첫 페이지 와 마지막 페이지 가 아 닐 때 다음 페이지 로 미 끄 러 지고 position 는 현재 페이지 의 위치 입 니 다.이전 페이지 로 미 끄 러 짐:position 는 현재 페이지-1
position Offset 이 다음 페이지 로 미 끄 러 지고[0,1)구간 이 변 합 니 다.이전 페이지 로 미 끄 러 짐:(1,0)구간 변화
position Offset Pixels 이것 은 position Offset 과 비슷 합 니 다.다음 페이지 로 미 끄 러 지고[0,너비)구간 에서 변화 합 니 다.이전 페이지 로 미 끄 러 짐:(너비,0)구간 변화
첫 페이지 시:이전 페이지 position=0 으로 미 끄 러 지 며,기타 기본 은 0 입 니 다.마지막 페이지 가 다음 페이지 position 로 미 끄 러 지 는 것 은 현재 페이지 의 위치 이 고 다른 두 매개 변 수 는 0 입 니 다.
우리 가 필요 로 하 는 절차 의 두 번 째 단계 가 해결 되 었 다 는 것 을 알 게 되 었 습 니 다.position Offset 는'그 라 데 이 션,확대 제어 파라미터'로 적합 합 니 다.position Offset Pixels 는 평이 등의 제어 매개 변수 로 사용 할 수 있 습 니 다.
그러면 현재 View 와 목적 View 를 어떻게 얻 습 니까?
나의 잘못된 길 을 몇 개 나 누 기:
1.【오 류】저 는 getChildAt(position),getChildAt(position+1),getChildAt(position-1)을 통 해 미 끄 러 질 때 좌우 두 개의 View 를 얻 습 니 다.언뜻 보기 에는 정말 괜 찮 은 것 같 습 니 다~~코드 에 쓰 면 언뜻 효과 가 나 오지 않 습 니 다~~오류 원인:우 리 는 아주 큰 것 을 무시 합 니 다.ViewPager 의 메커니즘 은 미 끄 러 질 때 동적 으로 View 를 불 러 오고 삭제 합 니 다.ViewPager 는 사실 2~3 개의 View 만 유지 하고 position 의 범 위 는 거의 무한 합 니 다~
2.【오 류】저 는 getCurrent Item 을 통 해 현재 위 치 를 얻 었 습 니 다.그리고+1,-1 획득 후 하나 또는 이전~~기 쁘 게 하고 있 습 니 다.코드 를 빨리 고치 고 있 습 니 다.효과 가 아무리 좋 지 않 아 도 엉망 입 니 다.로 그 를 자세히 살 펴 보 세 요.이 getCurrent Item 은 사용자 가 손가락 으로 떠 난 화면,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 를 초기 화 하 는 것 입 니 다~~더 이상 할 말 이 없습니다~~주의 할 점 이 있 습 니 다.인 스 턴 트 Item 방법 에서 mViewPager.setObject ForPosition(imageView,position)을 하나 더 호출 했 습 니 다.사실 저희 맵 에 저 장 된 값 을 주기 위해 서 였 어 요.
사용자 정의 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<Integer, View> mChildrenViews = new LinkedHashMap<Integer, View>(); 
 /** 
 *          
 */ 
 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 로 축소 되 었 습 니 다.맞습니다.우리 의 position Offset 에서 경사도 변 화 를 제공 합 니 다~그리고 이동 하 는 애니메이션 도 있 습 니 다.다음 페이지 는 현재 화면 으로 직접 이동 합 니 다(기본 값 은 오른쪽 입 니 다.이 효 과 를 설명 할 수 있 습 니 다.어떻게 실행 하 는 지 보 세 요).그리고 position Offset Pixels 를 통 해 기본 이동 시의 위 치 를 계속 상쇄 하여 사용자 로 하여 금 제자리 에서 확대 하고 축소 하 는 것 을 느끼 게 합 니 다~
자,이렇게 실현 되 었 습 니 다~~당신 은 자신 이 좋아 하 는 애니메이션 효 과 를 마음대로 쓸 수 있 습 니 다.예 를 들 어 기본 값 에 페이드아웃 이나 신 마 를 추가 하여 마음대로~~편 하지 않 습 니까?
우리 의 레이아웃 파일:

<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 의 사용
사실 위의 실현 은 바로 github 에서 Jazzy ViewPager 의 소스 코드 입 니 다.용법 은 말 할 필요 도 없 이 우리 의 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

원본 다운로드:ViewPager 그림 전환
이상 은 본 고의 모든 내용 입 니 다.여러분 이 안 드 로 이 드 소프트웨어 프로 그래 밍 을 배 우 는 데 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기