손 으로 가르쳐 드릴 게 요.ViewPager 사용자 정의 로 Banner 윤 방 을 실현 하도록 하 겠 습 니 다.
우 리 는 실제 개발 에서 많은 앱 들 이 광고 윤방송 기(그림 일 수도 있 고 다른 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이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Android ViewPager로 무한 스크롤 가능조금 조사해 보았더니, 라고 하는 기사가 돈피샤였습니다. 영어 기사라고 하는 것과, 데이터의 갱신에 대해서는 접하고 있지 않다(조금 유스 케이스가 다르다), 라고 하는 것으로 여기에 정리해 보겠습니다. ViewPag...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.