안 드 로 이 드 제작 단순 수직 상 향 하강 View 효과
최근 친구 회 사 는 수직 으로 떨 어 지 는 View 를 실현 해 야 합 니 다.이 View 는 처음에는 일부분 만 화면 맨 아래 에 표시 되 었 고,위 에서 당 기 는 부분 은 이 View 를 모두 끌 어 내 어 화면 에 표시 할 수 있 습 니 다.이 View 는 이 View 를 화면 아래 에 숨 길 수 있 습 니 다.
일단 최종 실현 효 과 를 살 펴 보 자.
2.사고 방향 실현
1.이 효 과 는 사실 많은 실현 방법 이 있 습 니 다.손 을 놓 을 때 viewpager 와 같은 느 린 미끄럼 효 과 를 얻 기 위해 저 는 scrollBy 로 Scroller 에 맞 추 는 것 을 선 택 했 습 니 다.편리 하면 서도 실 용적 일 것 입 니 다.
2.이 View 의 디자인 은 다음 과 같다.
(1)이 View 의 하위 view 를 layot 를 통 해 이 View 아래 에 놓 습 니 다.
(2)onTouchEvent 재 작성 방법 을 통 해 이 서브 View 에 미끄럼 효 과 를 주 고 MOVEUP 의 동작 은 이 하위 View 에 Scroller 를 추가 하여 View 의 상단 이나 아래쪽 까지 부 드 럽 게 합 니 다.
그림 참조:
실현
1.먼저 하나의 속성 을 정의 하고 서브 뷰 가 얼마나 많은 부분 을 밖으로 드 러 내야 하 는 지 를 나타 낸다.즉,위의 그림 에서 빨간색 과 녹색 이 교차 하 는 부분 이다.
res 폴 더-values 폴 더 아래 에 attrs.xml 파일 을 만 듭 니 다.
attrs.xml :
<resources>
<declare-styleable name="MyScrollerView">
<attr name="visibility_height" format="dimension"></attr>
</declare-styleable>
</resources>
XML 파일 에서 이 속성 을 참조 합 니 다:
<com.zw.myfirstapp.MyScrollerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@android:color/transparent"
android:id="@+id/msv"
app:visibility_height="100dp"
></com.zw.myfirstapp.MyScrollerView>
코드 에서 이 속성 을 호출 합 니 다.(이 View 의 이름 은 MyScrollerView 입 니 다.제 그림 은 LinearLayout 입 니 다.ViewGroup 이나 다른 레이아웃 View 를 계승 할 수 있 습 니 다)
public MyScrollerView(Context context) {
this(context,null);
}
public MyScrollerView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MyScrollerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.MyScrollerView);
visibilityHeight = ta.getDimension(R.styleable.MyScrollerView_visibility_height,200);
ta.recycle();
init(context);
}
2.onFinish Inflate 방법 을 다시 쓰 는데 이 방법 을 다시 쓰 는 이 유 는 제 가 키 View 만 있 었 으 면 좋 겠 기 때 문 입 니 다.그러면 미끄럼 의 높이 를 확정 할 수 있 습 니 다.그렇지 않 으 면 저 는 서브 View 들 의 높이 를 다시 계산 해 야 합 니 다.비교적 번 거 롭 습 니 다.이 방법 은 onMeasure 전에 호출 될 것 이다.
@Override
protected void onFinishInflate() {
super.onFinishInflate();
if(getChildCount() == 0 || getChildAt(0) == null){
throw new RuntimeException(" !");
}
if(getChildCount() > 1){
throw new RuntimeException(" !");
}
mChild = getChildAt(0);
}
3.init 방법 에서 초기 화 작업 을 합 니 다.예 를 들 어 Scroller 대상 을 만 들 고 View 의 배경 을 투명 하 게 설정 합 니 다.
private void init(Context context) {
mScroller = new Scroller(context);
this.setBackgroundColor(Color.TRANSPARENT);
}
4.onMeasure 방법 과 onLayout 방법 을 다시 쓰 고 미 끄 러 질 수 있 는 최대 높이 와 하위 View 의 배열 위 치 를 확인한다(사실은 onMeasure 를 다시 쓰 지 않 아 도 된다.나 는 이렇게 쓰 는 것 이 습관 일 뿐이다).
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mScrollHeight = (int) (mChild.getMeasuredHeight() - visibilityHeight);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
mChild.layout(0,mScrollHeight,mChild.getMeasuredWidth(),mChild.getMeasuredHeight() + mScrollHeight);
}
5.제 가 정의 한 멤버 변수의 의 미 를 먼저 보 세 요.
/**
* downY: View
* moveY: ( )
* movedY: ( , )
*/
private int downY,moveY,movedY;
// View
private View mChild;
private Scroller mScroller;
//
private int mScrollHeight;
// View
private boolean isTop = false;
// View View
private float visibilityHeight;
6.onTouchEvent 방법 을 다시 쓰 고 미끄럼 판단 을 하 며 설명 은 모두 주석 에 적 혀 있 습 니 다.
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
// View
downY = (int) event.getY();
// View && View , ,
if(!isTop && downY < mScrollHeight ){
return super.onTouchEvent(event);
}
return true;
case MotionEvent.ACTION_MOVE:
moveY = (int) event.getY();
//deY , deY>0 , deY<0
int deY = downY - moveY;
//
if(deY > 0){
// , View View
movedY += deY;
if(movedY > mScrollHeight) movedY = mScrollHeight;
if(movedY < mScrollHeight){
scrollBy(0,deY);
downY = moveY;
return true;
}
}
// , View ,
if(deY < 0 && isTop){
movedY += deY;
if(movedY < 0 ) movedY = 0;
if(movedY > 0){
scrollBy(0,deY);
}
downY = moveY;
return true;
}
break;
case MotionEvent.ACTION_UP:
// , 1/4, View ,
if(movedY > mScrollHeight / 4 && !isTop){
mScroller.startScroll(0,getScrollY(),0,(mScrollHeight - getScrollY()));
invalidate();
movedY = mScrollHeight;
isTop = true;
}else {
// ,
mScroller.startScroll(0,getScrollY(),0, -getScrollY());
postInvalidate();
movedY = 0;
isTop = false;
}
break;
}
return super.onTouchEvent(event);
}
7.마지막 으로 coptute Scroll 방법 을 다시 써 야 합 니 다.이 방법 은 scroller 에 맞 는 것 입 니 다.
@Override
public void computeScroll() {
super.computeScroll();
if(mScroller.computeScrollOffset()){
scrollTo(0,mScroller.getCurrY());
postInvalidate();
}
}
8.scroller 의 용법 에 대해 곽 림 의 이 블 로 그 를 참고 할 수 있 습 니 다http://blog.csdn.net/guolin_blog/article/details/487198714.전체 코드:
xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.zw.myfirstapp.MyScrollerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@android:color/transparent"
android:id="@+id/msv"
app:visibility_height="100dp"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="@mipmap/b"
android:gravity="center"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn"
android:text=" "/>
</LinearLayout>
</com.zw.myfirstapp.MyScrollerView>
</RelativeLayout>
MyScrollerView:
public class MyScrollerView extends LinearLayout {
/**
* downY: View
* moveY: ( )
* movedY: ( , )
*/
private int downY,moveY,movedY;
// View
private View mChild;
private Scroller mScroller;
//
private int mScrollHeight;
// View
private boolean isTop = false;
// View View
private float visibilityHeight;
public MyScrollerView(Context context) {
this(context,null);
}
public MyScrollerView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MyScrollerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.MyScrollerView);
visibilityHeight = ta.getDimension(R.styleable.MyScrollerView_visibility_height,200);
ta.recycle();
init(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mScrollHeight = (int) (mChild.getMeasuredHeight() - visibilityHeight);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
mChild.layout(0,mScrollHeight,mChild.getMeasuredWidth(),mChild.getMeasuredHeight() + mScrollHeight);
}
private void init(Context context) {
mScroller = new Scroller(context);
this.setBackgroundColor(Color.TRANSPARENT);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
if(getChildCount() == 0 || getChildAt(0) == null){
throw new RuntimeException(" !");
}
if(getChildCount() > 1){
throw new RuntimeException(" !");
}
mChild = getChildAt(0);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
// View
downY = (int) event.getY();
// View && View , ,
if(!isTop && downY < mScrollHeight ){
return super.onTouchEvent(event);
}
return true;
case MotionEvent.ACTION_MOVE:
moveY = (int) event.getY();
//deY , deY>0 , deY<0
int deY = downY - moveY;
//
if(deY > 0){
// , View View
movedY += deY;
if(movedY > mScrollHeight) movedY = mScrollHeight;
if(movedY < mScrollHeight){
scrollBy(0,deY);
downY = moveY;
return true;
}
}
// , View ,
if(deY < 0 && isTop){
movedY += deY;
if(movedY < 0 ) movedY = 0;
if(movedY > 0){
scrollBy(0,deY);
}
downY = moveY;
return true;
}
break;
case MotionEvent.ACTION_UP:
// , 1/4, View ,
if(movedY > mScrollHeight / 4 && !isTop){
mScroller.startScroll(0,getScrollY(),0,(mScrollHeight - getScrollY()));
invalidate();
movedY = mScrollHeight;
isTop = true;
}else {
// ,
mScroller.startScroll(0,getScrollY(),0, -getScrollY());
postInvalidate();
movedY = 0;
isTop = false;
}
break;
}
return super.onTouchEvent(event);
}
@Override
public void computeScroll() {
super.computeScroll();
if(mScroller.computeScrollOffset()){
scrollTo(0,mScroller.getCurrY());
postInvalidate();
}
}
}
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 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에 따라 라이센스가 부여됩니다.