Android 사용자 정의 레이아웃 세로 뷰 퍼 구현
16667 단어 Android세로 ViewPager
효과 그림:
이 사용자 정의 컨트롤 에 대한 지식:
ViewGroup 의 onMeasure 와 onLayout 의 쓰기 사용자 정의
신축성 스크롤 스크롤 스크롤 러 사용법
속도 궤적 추적 기 Velocity Tracker 의 용법
미끄럼 사건 충돌 을 어떻게 처리 합 니까?
dispatchTouchEvent:(외부 차단)스크롤 레이아웃 의 부모 레이아웃 을 알려 줍 니 다.터치 이 벤트 를 언제 차단 해 야 하 는 지,터치 이 벤트 를 언제 차단 하지 말 아야 하 는 지 알려 줍 니 다.
onInterceptTouchEvent:(내부 차단)ScrollLayout 는 내부 자 View 의 터치 이 벤트 를 언제 차단 해 야 하 는 지,내부 자 View 의 터치 이 벤트 를 언제 차단 하지 말 아야 하 는 지 알려 줍 니 다.
터치 슬라이딩 처리 방법:
// ,
//
if (Math.abs(velocityY) > criticalVelocityY) {// ,
// 、 , , ( , , )
if (shouZhiXiangXiaHuaDong) {
if (currentPage > 1) {//★★★★★★★★ , , , ★(currentPage-2)
mScroller.startScroll(0, getScrollY(), 0, childHeight * (currentPage - 2) - getScrollY());
currentPage--;
}
} else {
if (currentPage < childCount) {//★★★★★★★ , , , ★currentPage
mScroller.startScroll(0, getScrollY(), 0, childHeight * currentPage - getScrollY());
currentPage++;
}
}
Log.e("eee", currentPage + "");
총결산알고리즘 을 쓰 려 고 할 때 급 하 게 한꺼번에 쓰 려 고 하지 마 세 요.그러면 맹목적 인 것 에 빠 집 니 다.한 걸음 한 걸음 코드 를 실현 하고 마지막 에 규칙 을 찾 도록 지도 해 야 합 니 다.요약,통 항 공식 과 유사 한 방법 입 니 다.
코드 는 다음 과 같 습 니 다.(주석 이 완전 합 니 다)
package beautlful.time.com.beautlfultime.view;
import android.content.Context;
import android.support.v4.view.ViewConfigurationCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;
/**
* : viewgroup match_parent ,
* : viewgroup, padding , ScrollerLayout padding, ,
* padding , ScrollerLayout ( ), padding
* viewgroup , , :
* Android Scroller , Scroller
* http://blog.csdn.net/guolin_blog/article/details/48719871
*/
public class VerticalViewPager extends ViewGroup {
int currentPage = 1;
/**
*
*/
private VelocityTracker mVelocityTracker;
/**
*
*/
private final int mMaxVelocity;
/**
* id, ,
*/
private int mPointerId;
/**
*
*/
private float velocityY;
/**
* , , ,
*/
private int criticalVelocityY = 2500;
/**
*
*/
private Scroller mScroller;
/**
*
*/
private int mTouchSlop;
/**
*
*/
private float mYDown;
/**
*
*/
private float mYMove;
/**
* ACTION_MOVE
*/
private float mYLastMove;
/**
*
*/
private int topBorder;
/**
*
*/
private int bottomBorder;
/**
* ( , match_parent)
*/
private int childHeight;
/**
*
*/
private boolean shouZhiXiangXiaHuaDong;
private int childCount;
public VerticalViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
// , Scroller
mScroller = new Scroller(context);
ViewConfiguration configuration = ViewConfiguration.get(context);
// TouchSlop
mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
//
mMaxVelocity = ViewConfiguration.get(context).getMaximumFlingVelocity();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i);
// ScrollerLayout
measureChild(childView, widthMeasureSpec, heightMeasureSpec);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed) {
/**
*
*/
int preChildViewTotalHeight = 0;
for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i);
// ScrollerLayout
if (i == 0) {
childView.layout(
0,
0,
childView.getMeasuredWidth(),
childView.getMeasuredHeight());
} else {
childView.layout(
0,
preChildViewTotalHeight,
childView.getMeasuredWidth(),
preChildViewTotalHeight + childView.getMeasuredHeight());
}
preChildViewTotalHeight += childView.getMeasuredHeight();
}
//
topBorder = getChildAt(0).getTop();
bottomBorder = getChildAt(getChildCount() - 1).getBottom();
childHeight = getChildAt(0).getMeasuredHeight();
}
}
private int downX;
private int downY;
// ScrollLayout , ,
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// ScrollerLayout
getParent().requestDisallowInterceptTouchEvent(true);
downX = (int) ev.getX();
downY = (int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
int moveX = (int) ev.getX();
int moveY = (int) ev.getY();
// ViewPager ,ViewPager ,
if (Math.abs(moveY - downY) < Math.abs(moveX - downX)) {
getParent().requestDisallowInterceptTouchEvent(false);
} else {
// ViewPager ,ScrollerLayout
getParent().requestDisallowInterceptTouchEvent(true);
}
break;
case MotionEvent.ACTION_CANCEL:
break;
case MotionEvent.ACTION_UP:
break;
}
return super.dispatchTouchEvent(ev);
}
// ScrollLayout View , View
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
//▲▲▲1. id, ,
mPointerId = ev.getPointerId(0);
mYDown = ev.getRawY();
mYLastMove = mYDown;
break;
case MotionEvent.ACTION_MOVE:
mYMove = ev.getRawY();
float diff = Math.abs(mYMove - mYDown);
mYLastMove = mYMove;
// TouchSlop , ,
if (diff > mTouchSlop) {
return true;
}
break;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//▲▲▲2. VelocityTracker MotionEvent
acquireVelocityTracker(event);
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
//▲▲▲3.
mVelocityTracker.computeCurrentVelocity(1000, mMaxVelocity);
velocityY = mVelocityTracker.getYVelocity(mPointerId);
mYMove = event.getRawY();
int scrolledY = (int) (mYLastMove - mYMove);// , ,
if (getScrollY() + scrolledY < topBorder) {// , ( 、 , )
scrollTo(0, topBorder);
return true;//★★★★★★★★★★★★★★★★ true false , 。
} else if (getScrollY() + getHeight() + scrolledY > bottomBorder) {// ,
scrollTo(0, bottomBorder - getHeight());
return true;//★★★★★★★★★★★★★★★★★ true false , 。
}
scrollBy(0, scrolledY);// move ,
if (mYDown <= mYMove) {//★★★ , , mYDown, mYLastMove
shouZhiXiangXiaHuaDong = true;//
} else {
shouZhiXiangXiaHuaDong = false;//
}
mYLastMove = mYMove;
break;
case MotionEvent.ACTION_UP:
// 4.▲▲▲ VelocityTracker
releaseVelocityTracker();
// , , , invalidate();
if (Math.abs(velocityY) > criticalVelocityY) {// ,
// 、 , , ( , , )
if (shouZhiXiangXiaHuaDong) {
if (currentPage > 1) {//★★★★★★★★ , , , ★(currentPage-2)
mScroller.startScroll(0, getScrollY(), 0, childHeight * (currentPage - 2) - getScrollY());
currentPage--;
}
} else {
if (currentPage < childCount) {//★★★★★★★ , , , ★currentPage
mScroller.startScroll(0, getScrollY(), 0, childHeight * currentPage - getScrollY());
currentPage++;
}
}
Log.e("eee", currentPage + "");
} else {// , ,
// 、 , ,( , , )
if ((getScrollY() >= childHeight * (currentPage - 1) + childHeight / 2 && !shouZhiXiangXiaHuaDong)) {
// ,
mScroller.startScroll(0, getScrollY(), 0, childHeight * (currentPage) - getScrollY());
currentPage++;
} else if ((getScrollY() < childHeight * (currentPage - 1) + childHeight / 2 && !shouZhiXiangXiaHuaDong)) {
// ,
mScroller.startScroll(0, getScrollY(), 0, childHeight * (currentPage - 1) - getScrollY());
} else if
((getScrollY() <= childHeight * (currentPage - 2) + childHeight / 2
&& shouZhiXiangXiaHuaDong)) {
// ,
mScroller.startScroll(0, getScrollY(), 0, childHeight * (currentPage - 2) - getScrollY());
currentPage--;
} else if
((getScrollY() > childHeight * (currentPage - 2) + childHeight / 2
&& shouZhiXiangXiaHuaDong)) {
// ,
mScroller.startScroll(0, getScrollY(), 0, childHeight * (currentPage - 1) - getScrollY());
}
/* if ((getScrollY() >= childHeight && !shouZhiXiangXiaHuaDong)// , ,viewgroup
|| ((getScrollY() >= (totalChildHeight - firstChildHeight - lastChildHeight) && shouZhiXiangXiaHuaDong))) {// , ,viewgroup
// ( , ) , viewgroup Viewgroup ,
// 600, getScrollX,
// , 600-getScrollX(),
mScroller.startScroll(0,getScrollY(), 0, (totalChildHeight - firstChildHeight) - getScrollY());
} else if ((getScrollY() <= (totalChildHeight - firstChildHeight - lastChildHeight) && shouZhiXiangXiaHuaDong)// , ,viewgroup
|| (getScrollY() <= childHeight && !shouZhiXiangXiaHuaDong)) {// , ,viewgroup
// , viewgroup Viewgroup ,
// , viewgroup 0, getScrollX,
// , 0-getScrollX(),
mScroller.startScroll(0,getScrollY(), 0, 0 - getScrollY());
}*/
}
// invalidate()
invalidate();
break;
case MotionEvent.ACTION_CANCEL:
// 5.▲▲▲ VelocityTracker
releaseVelocityTracker();
break;
}
return super.onTouchEvent(event);
}
@Override
public void computeScroll() {
// , computeScroll() ,
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
invalidate();
}
}
/**
* @param event VelocityTracker MotionEvent
* @see VelocityTracker#obtain()
* @see VelocityTracker#addMovement(MotionEvent)
*/
private void acquireVelocityTracker(final MotionEvent event) {
if (null == mVelocityTracker) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
}
/**
* VelocityTracker
*
* @see VelocityTracker#clear()
* @see VelocityTracker#recycle()
*/
private void releaseVelocityTracker() {
if (null != mVelocityTracker) {
mVelocityTracker.clear();
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
/* getScrollX() viewgroup View scrollTo(int x, int y) scrollBy(int x, int y) X
// , , viewgroup ,
//
Log.e("qqq","getX():"+event.getX());
//
Log.e("qqq","getRawX():"+event.getRawX());*/
}
레이아웃 파일
<beautlful.time.com.beautlfultime.view.VerticalViewPager
android:id="@+id/verticalViewPager"
android:layout_width="match_parent"
android:layout_height="150dp">
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_orange_dark"
android:text=" " />
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
android:text=" " />
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"
android:text=" " />
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
android:text=" " />
</beautlful.time.com.beautlfultime.view.VerticalViewPager>
읽 어 주 셔 서 감사합니다. 여러분 에 게 도움 이 되 기 를 바 랍 니 다.본 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.