[Android 맞춤형 컨트롤] ScrollView 없이 위아래 두 화면 슬라이딩
10966 단어 Android사용자 정의view
전언
최근 프로젝트 원인은 상하 두 스크린이 미끄러지는 효과가 필요하다.viewpager 좌우 미끄럼이 상하 미끄럼으로 변한다고 상상할 수 있습니다.Srcollview로 실현하려고 하였으나, 버튼 충돌,listview 레이아웃 충돌 등 몇 가지 이유로, 마지막에 사용자 정의 컨트롤을 쓰기로 결정하였다.
사고의 방향
이전에 슬라이딩 Menu를 실현한 적이 있기 때문에 그 패턴을 참고하여 좌우 슬라이딩이 상하 슬라이딩으로 바뀌면 된다.사실은 두 개의 크기가 같은 구조로 하나는 화면에 나타나고 다른 하나는 화면 밖으로 숨어 미끄러질 때까지 기다리면 나타난다.
코드
내가 물려받은 건 View Group이야.다시 onLayout 방법을 다시 써서 하나의 레이아웃이 화면을 가득 채우고 다른 하나는 화면 밖에 놓는다.
public class MySlidingMenu extends ViewGroup {
private static final String TAG = MySlidingMenu.class.getName();
private enum Scroll_State {
Scroll_to_Open, Scroll_to_Close;
}
private Scroll_State state;
private int mMostRecentY;
private int downY;
private boolean isOpen = false;
private View menu;
private View mainView;
private Scroller mScroller;
private OnSlidingMenuListener onSlidingMenuListener;
public MySlidingMenu(Context context, View main, View menu) {
super(context);
setMainView(main);
setMenu(menu);
init(context);
}
private void init(Context context) {
mScroller = new Scroller(context);
}
@Override
protected void onLayout(boolean arg0, int l, int t, int r, int b) {
mainView.layout(l,t,r,b);
//
menu.layout(l, menu.getMeasuredHeight(), r, menu.getMeasuredHeight()*2);
}
public void setMainView(View view) {
mainView = view;
addView(mainView);
}
public void setMenu(View view) {
menu = view;
addView(menu);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mainView.measure(widthMeasureSpec, heightMeasureSpec);
menu.measure(widthMeasureSpec, heightMeasureSpec);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mMostRecentY = (int) event.getY();
downY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
int moveY = (int) event.getY();
int deltaY = mMostRecentY - moveY;
// Scroll
if ((!isOpen && (downY - moveY) > 0)
|| (isOpen && (downY - moveY) < 0)) {
scrollBy(0, deltaY);
}
mMostRecentY = moveY;
break;
case MotionEvent.ACTION_UP:
int upY = (int) event.getY();
int dy = upY - downY;
if (!isOpen) {
// menu
if (dy < - menu.getMeasuredHeight() / 3) {
state = Scroll_State.Scroll_to_Open;
} else {
state = Scroll_State.Scroll_to_Close;
}
} else {
// menu , menu ,
if (dy > menu.getMeasuredHeight() / 3) {
state = Scroll_State.Scroll_to_Close;
} else {
state = Scroll_State.Scroll_to_Open;
}
}
smoothScrollto();
break;
default:
break;
}
return true;
}
private void smoothScrollto() {
int scrolly = getScrollY();
switch (state) {
case Scroll_to_Close:
mScroller.startScroll(0, scrolly, 0, - scrolly, 500);
isOpen = false;
break;
case Scroll_to_Open:
mScroller.startScroll(0, scrolly, 0, menu.getMeasuredHeight()- scrolly, 500);
isOpen = true;
break;
default:
break;
}
// invalidate, computeScroll
invalidate();
}
@Override
public void computeScroll() {
// computeScrollOffset false, startScroll true
if (mScroller.computeScrollOffset()) {
scrollTo(0, mScroller.getCurrY());
postInvalidate();
}
super.computeScroll();
}
}
전체 코드는 복잡한 편은 아니지만, 가장 중요한 것은 좌표의 계산이다.startScroll(int startX, int startY, int dx, int dy, int duration) 이 방법은 좌표가 미끄러지는 데 비교적 어렵다.처음에 나는 줄곧 dx,dy가 어느 방향으로 가고 마이너스가 어느 방향으로 가는지 고민했다.나중에 원본 코드를 봤어요.
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
mMode = SCROLL_MODE;
mFinished = false;
mDuration = duration;
mStartTime = AnimationUtils.currentAnimationTimeMillis();
mStartX = startX;
mStartY = startY; //
mFinalX = startX + dx;
mFinalY = startY + dy; //
mDeltaX = dx;
mDeltaY = dy;
mDurationReciprocal = 1.0f / (float) mDuration;
// This controls the viscous fluid effect (how much of it)
mViscousFluidScale = 8.0f;
// must be set to 1.0 (used in viscousFluid())
mViscousFluidNormalize = 1.0f;
mViscousFluidNormalize = 1.0f / viscousFluid(1.0f);
}
그래서 A(a1,a2)에서 B(b1,b2)로 미끄러지면 startScroll(a1,a2,b1-a1,b2-a2)만 있으면 된다.주로 차액을 구하다.
사용법
private MySlidingMenu mSlidingMenu;
......
mSlidingMenu = new MySlidingMenu(this, LayoutInflater
.from(this).inflate(R.layout.fragment1, null), LayoutInflater
.from(this).inflate(R.layout.fragment2, null));
보태다
이것은listview 슬라이딩 충돌을 초래할 수 있습니다. 열 수가 고정되면listviewe를 다시 쓰는 onTouchEvent가false로 되돌아오는 것을 한 화면에 표시할 수 있습니다.만약 비교적 많으면, 온터치 이벤트 ()에서 getParent () 를 통과합니다.requestDisallowInterceptTouchEvent (bool) 는 어떤 컨트롤 응답 이벤트를 설정합니다.
일반적인 사고방식은list가 머리와 꼬리를 미끄러질 때 상응하는 방향의 미끄러짐 사건을 부모 구성 요소에 전달하는 것이다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 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에 따라 라이센스가 부여됩니다.