손 으로 가르쳐 드릴 게 요.ViewPager 사용자 정의 로 Banner 윤 방 을 실현 하도록 하 겠 습 니 다.

12246 단어 ViewPagerBanner윤파
안 드 로 이 드 오픈 소스 네트워크 프레임 워 크 에 관심 을 가 져 주 셔 서 감사합니다. 
우 리 는 실제 개발 에서 많은 앱 들 이 광고 윤방송 기(그림 일 수도 있 고 다른 View 일 수도 있 음)를 만 들 고 있다.많은 친구 들 이 다른 사람 이 봉 한 것 을 사용 하거나 ViewPager 를 직접 사용 하여 고 쳤 지만 안의 원 리 를 이해 하지 못 하거나 제스처 가 미 끄 러 지 는 충돌 을 만 났 을 수도 있다.우 리 는 오늘 150 줄 코드 로 사용자 정의 광고 윤 파 기 를 실현 하 는데 원래 의 View 슬라이딩 사건 을 방해 하지 않 는 다.
이 예 코드 원본 및 데모 전송 문
효과 시범

수요 분석,해결 방안
윤파기 의 가장 중요 한 몇 가지 특징 은 자동 스크롤,수 동 미끄럼,스크롤 방향,모든 Item 표시 시간 이다.따라서 우 리 는 다음 과 같은 몇 가지 방법 을 외부 에서 호출 할 수 있 도록 설계 했다.

/**
 *     Item     ,  3000  
 */
public void setShowTime(int showTimeMillis);

/**
 *       ,      
 */
public void setDirection(Direction direction);

/**
 *       
 */
public void start();

/**
 *       
 */
public void stop();

/**
 *      
 */
public void previous();

/**
 *      
 */
public void next();

위의 방법 을 자세히 본 동창 회 는 우리 의 분석 과 비교 하면 수 동 으로 미 끄 러 지 는 방법 이 부족 하 다 는 것 을 알 게 되 었 다.우 리 는 제스처 가 미 끄 러 지 려 면 반드시 onTouch 등 방법 을 사용 해 야 한 다 는 것 을 알 고 있 기 때문에 우 리 는 v4 가방 에서 ViewPager 가 자체 적 으로 미 끄 러 지 는 효 과 를 가지 고 코드 를 제어 하여 특정한 Item 으로 넘 어 갈 수 있다 고 생각 했다.따라서 뷰 퍼 거 를 사용자 정의 로 계승 하면 완벽 하 게 해 결 될 수 있 지 않 습 니까?
우 리 는 위의 방법 중 에 Direction 류 가 있 는 것 을 보 았 습 니 다.이런 종 류 는 시스템 이 아니 라 달 고 가 사용자 정의 방향 으로 매 거 진 것 입 니 다.현재 가장 흔히 볼 수 있 는 라운드 방향 은 좌우 라운드 방송(상하 이번 에는 토론 하지 않 음)일 뿐 입 니 다.코드 는 다음 과 같 습 니 다.

public enum Direction {
 /**
 *     ,            
 */
 LEFT,

 /**
 *     ,            
 */
 RIGHT
}

사용자 정의 View 어떻게 실현 및 원리
위 에서 ViewPager 를 계승 해 야 한 다 는 것 을 분 석 했 습 니 다.그래서 우 리 는 먼저 위의 몇 가지 방법 을 결합 하여 완전한 코드 를 훑 습 니 다.

public class AutoPlayViewPager extends ViewPager {

 public AutoPlayViewPager(Context context) {
 super(context);
 }

 public AutoPlayViewPager(Context context, AttributeSet attrs) {
 super(context, attrs);
 }

 /**
 *     
 */
 private int showTime = 3 * 1000;
 /**
 *     
 */
 private Direction direction = Direction.LEFT;

 /**
 *       ,  3 
 *
 * @param showTimeMillis   
 */
 public void setShowTime(int showTimeMillis) {
 this.showTime = showTime;
 }

 /**
 *       ,      
 *
 * @param direction   
 */
 public void setDirection(Direction direction) {
 this.direction = direction;
 }

 /**
 *   
 */
 public void start() {
 // TODO        
 }

 /**
 *   
 */
 public void stop() {
 // TODO        
 }

 /**
 *      
 */
 public void previous() {
 // TODO         
 }

 /**
 *      
 */
 public void next() {
 // TODO         
 }

 public enum Direction {
 /**
  *     ,         
  */
 LEFT,

 /**
  *     ,         
  */
 RIGHT
 }
}

setShowTime(int showTimeMillis)방법 과 setDirection(Direction direction)은 특정한 상 태 를 기록 하 는 것 일 뿐 이 며,지금 은 간단하게 실현 되 었 으 며,중점 은 재생 을 시작 하고 재생 을 중단 하 는 것 이다.  
정시 윤파 의 원리 분석 과 실현
전방 의 고에너지 이 니,관리 여러분 바지 가 떨 어 지지 않도록 조심 하 세 요.지금 우리 가 ViewPager 를 사용 하 는 가장 중요 한 것 은 자동 재생 입 니 다.그래서 우 리 는 타 이 머 를 사용 하여 임 무 를 수행 해 야 합 니 다.그러나 이렇게 하면 Handler 를 사용 해 야 하기 때문에 작은 일 을 크게 할 수 있 습 니 다.View 의 두 가지 방법 을 소개 합 니 다.

//            ,       UI  (   )  。
public boolean post(Runnable action);

//            ,          ,       UI  (   )  。
public boolean postDelayed(Runnable action, long delayMillis);

두 번 째 방법 을 보면 제호 가 정수리 에 들 어 가 는 것 과 같 습 니 다.나무 가 있 습 니 다.모든 View 에 있 는 방법 이 니 ViewPager 는 반드시 있어 야 합 니 다.그러면 메 인 스 레 드 에서 정시 에 미 션 을 발표 할 수 있 지 않 습 니까?그래서 우 리 는 이 정시 임 무 를 수행 하기 위해 Runnable 을 썼 다.

/**
 *    
 */
private Runnable player = new Runnable() {
 @Override
 public void run() {
 play(direction);
 }
};

여기 play(direction)가 있 습 니 다.방법 은 우리 가 실현 하 기 를 기다 리 고 있 습 니 다.우 리 는 잠시 이 방법 을 먼저 놓 겠 습 니 다.우 리 는 먼저 이 private Runnable player 를 이용 하여 재생 을 시작 하고 재생 을 중단 하 는 방법 을 살 펴 보 겠 습 니 다.  
재생 시작 과 정지 실현
재생 을 시작 할 때 현재 표 시 된 그림 에 showTime 의 시간 을 표시 하기 위해 postDelayed(Runnable action,long delay Millis)를 사용 합 니 다.방법 은 쇼 타임 이후 private Runnable player 를 터치 합 니 다:

/**
 *   
 */
public void start() {
 postDelayed(player, showTime);
}

재생 을 중지 합 니 다.우 리 는 이 스 레 드 를 취소 하면 됩 니 다.따라서 정지 하 는 방법 은 다음 과 같 습 니 다.

/**
 *   
 */
public void stop() {
 removeCallbacks(player);
}

그러나 개발 자가 끊임없이 start 방법 을 호출 하여 카드 사 현상 을 일 으 키 는 것 을 방지 하기 위해 start 에서 최 적 화 를 합 니 다.매번 star 전에 private Runable player 를 제거 하기 때문에 start 방법의 완전한 코드 는 다음 과 같 습 니 다.

/**
 *   
 */
public void start() {
 stop();
 postDelayed(player, showTime);
}

핵심 포인트:어떻게 방향 에 따라 이전 과 다음 을 재생 합 니까?
이 사례 의 핵심 과 중점 이 왔 습 니 다.지금 은 고 개 를 돌려 방금 방치 한 play(direction)를 실현 합 니 다.방법,그것 은 재생 방향 에 따라 이전 장과 다음 장 을 재생 해 야 합 니 다.우 리 는 코드 를 구체 적 으로 보고 특히 주석 을 자세히 음미 해 야 합 니 다.

/**
 *     
 *
 * @param direction     
 */
private synchronized void play(Direction direction) {
 //   ViewPager    
 PagerAdapter pagerAdapter = getAdapter();
 if (pagerAdapter != null) {//   
 // Item  
 int count = pagerAdapter.getCount();
 // ViewPager        ?
 int currentItem = getCurrentItem();
 switch (direction) {
  case LEFT://        ,currentItem+1     
  currentItem++;

  //   +      ,     
  if (currentItem >= count)
   currentItem = 0;
  break;
  case RIGHT://        ,currentItem-1     
  currentItem--;

  //   -     ,      
  if (currentItem < 0)
   currentItem = count - 1;
  break;
 }
 setCurrentItem(currentItem);//            position item
 }

 //              ,       ,          
 start();
}

여기까지 사실 우 리 는 윤방송 을 실 현 했 습 니 다.그러나 우 리 는 사용 할 때 한 가지 상황 이 존재 한 다 는 것 을 알 게 되 었 습 니 다.우 리 는 손가락 으로 한 장 을 미 끄 러 뜨 렸 고 두 번 째 장 이 다시 나 왔 습 니 다.뜸 을 들 이지 않 았 습 니 다.그 이 유 는 우리 가 손가락 이 미 끄 러 질 때 private Runnable player 라 는 임 무 를 멈 추 지 않 았 기 때 문 입 니 다.그래서 우 리 는 손가락 이 미 끄 러 질 때 play손가락 이 풀 렸 을 때 player 다시 시작:

@Override
protected void onFinishInflate() {
 addOnPageChangeListener(new OnPageChangeListener() {
 @Override
 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
 }

 @Override
 public void onPageSelected(int position) {
 }

 @Override
 public void onPageScrollStateChanged(int state) {
  if (state == SCROLL_STATE_IDLE)
  start();
  else if (state == SCROLL_STATE_DRAGGING)
  stop();
 }
 });
}

일부 학생 들 은 왜 구조 방법 에 있 지 않 고 onFinish Inflate 에서 addOnPage Change Listener 를 사용 해 야 하 는 지 모 를 수도 있 습 니 다.이 방법 은 view 가 불 러 온 후에 호출 되 기 때문에 우 리 는 여기 서 초기 화 작업 을 하 는 것 이 합 리 적 입 니 다.
사용자 정의 ViewPager 의 전체 코드 는 다음 과 같 습 니 다.

package com.yolanda.autoviewpager;

import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;

/**
 * <p> ViewPager         。</p>.
 * 
 * @author Yolanda; 
 */
public class AutoPlayViewPager extends ViewPager {

 public AutoPlayViewPager(Context context) {
 super(context);
 }

 public AutoPlayViewPager(Context context, AttributeSet attrs) {
 super(context, attrs);
 }

 /**
 *     
 */
 private int showTime = 3 * 1000;
 /**
 *     
 */
 private Direction direction = Direction.LEFT;
 /**
 *       ,  3 
 *
 * @param showTimeMillis   
 */
 public void setShowTime(int showTimeMillis) {
 this.showTime = showTime;
 }

 /**
 *       ,      
 *
 * @param direction   
 */
 public void setDirection(Direction direction) {
 this.direction = direction;
 }

 /**
 *   
 */
 public void start() {
 stop();
 postDelayed(player, showTime);
 }

 /**
 *   
 */
 public void stop() {
 removeCallbacks(player);
 }

 /**
 *      
 */
 public void previous() {
 if (direction == Direction.RIGHT) {
  play(Direction.LEFT);
 } else if (direction == Direction.LEFT) {
  play(Direction.RIGHT);
 }
 }

 /**
 *      
 */
 public void next() {
 play(direction);
 }

 /**
 *     
 *
 * @param direction     
 */
 private synchronized void play(Direction direction) {
 PagerAdapter pagerAdapter = getAdapter();
 if (pagerAdapter != null) {
  int count = pagerAdapter.getCount();
  int currentItem = getCurrentItem();
  switch (direction) {
  case LEFT:
   currentItem++;
   if (currentItem > count)
   currentItem = 0;
   break;
  case RIGHT:
   currentItem--;
   if (currentItem < 0)
   currentItem = count;
   break;
  }
  setCurrentItem(currentItem);
 }
 start();
 }

 /**
 *    
 */
 private Runnable player = new Runnable() {
 @Override
 public void run() {
  play(direction);
 }
 };

 public enum Direction {
 /**
  *     ,         
  */
 LEFT,
  /**
  *     ,         
  */
 RIGHT
 }

 @Override
 protected void onFinishInflate() {
 super.onFinishInflate();
 addOnPageChangeListener(new OnPageChangeListener() {
  @Override
  public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
  }

  @Override
  public void onPageSelected(int position) {
  }

  @Override
  public void onPageScrollStateChanged(int state) {
  if (state == SCROLL_STATE_IDLE)
   start();
  else if (state == SCROLL_STATE_DRAGGING)
   stop();
  }
 });
 }
}


어떻게 사용 합 니까?
사실 우 리 는 ViewPager 에 대해 큰 간섭 을 하지 않 았 기 때문에 우 리 는 원생 의 것 과 다 를 것 이 없다.누군가가 구 덩이 를 밟 지 않도록 여기에 몇 가지 주의 할 곳 도 써 라.
하면,만약,만약...

AutoPlayViewPager autoPlayViewPage = (AutoPlayViewPager) findViewById(R.id.view_pager);
autoPlayViewPage.setAdapter(bannerAdapter);

//            ,      
autoPlayViewPage.setDirection(AutoPlayViewPager.Direction.LEFT);//       
autoPlayViewPage.setCurrentItem(200); //     Item     

autoPlayViewPage.start(); //     

어떻게 어댑터 를 최적화 합 니까?
사실 우 리 는 스타 방법 을 하나 더 호출 한 것 을 보 았 지만,아직 부족 하 다.우 리 는 어댑터 에서 작은 일 을 해 야 한다.윤방송 이 무한 순환 할 수 있 도록 getCount 에서 int 의 최대 값 을 되 돌려 줍 니 다.

@Override
public int getCount() {
 return resIds == null ? 0 : Integer.MAX_VALUE;
}

resIds 는 우리 의 데이터 원본 입 니 다.이 Count 를 받 은 후에 우리 의 instantiate Item()방법 도 수정 해 야 합 니 다.그렇지 않 으 면 아래 표 시 된 경계선 을 넘 는 이상 이 발생 할 수 있 습 니 다.우 리 는 position 를 받 은 후에 처리 해 야 합 니 다.

@Override
public Object instantiateItem(ViewGroup container, int position) {
 position = position % resIds.size();
 Object xxoo = resIds.get(position);
 ...
}

이 예 코드 원본:https://github.com/yanzhenjie/NoHttp
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기