Android 는 ViewDragHelper 를 사용 하여 QQQ6.X 최신 버 전 사 이 드 슬라이드 인터페이스 효과 인 스 턴 스 코드 를 구현 합 니 다.
29506 단어 androidqq옆으로 미끄러지다viewdraghelper
이틀 동안 QQ 는 중대 한 업데이트(6.X)를 진 행 했 습 니 다.특히 UI 스타일 에서 이전 파란색 에서 흰색 으로 바 뀌 었 고 사 이 드 스 케 이 트 효과 도 약간 바 뀌 었 습 니 다.그러면 QQ6.X 버 전의 사 이 드 스 케 이 트 인터페이스 효 과 를 모방 해 보 겠 습 니 다.오늘 도 우 리 는 신기 뷰 드 래 곤 헬 퍼 로 이 루어 진다.
이번 인 스 턴 스 의 구체 적 인 코드 는 아래 항목 에 올 라 왔 습 니 다.star 와 fork 에 오신 것 을 환영 합 니 다.
https://github.com/jiangqqlmj/DragHelper4QQ
FastDev4Android 프레임 워 크 항목 주소:https://github.com/jiangqqlmj/FastDev4Android
(2).ViewGragHelper 의 기본 사용
앞에서 우 리 는 ViewGragHelper 의 기본 적 인 사용 방법 을 배 웠 고 안에 있 는 몇 가지 방법의 용도 도 알 게 되 었 습 니 다.다음은 기본 적 인 사용 절 차 를 복습 하 겠 습 니 다.ViewGragHelper 를 사용 하여 하위 View 드래그 이동 을 실현 하 는 절 차 는 다음 과 같 습 니 다.
ViewGragHelper 인 스 턴 스 만 들 기(Callback 에 전송)
이벤트 차단 처리 방법 재 작성 onInterceptTouch 와 onTouch Event
Callback 을 실현 하고 그 중의 관련 방법 try Capture View 와 수평 또는 수직 방향 으로 이동 하 는 거리 방법 을 실현 합 니 다.
좀 더 구체 적 으로 분석 하면 앞의 블 로 그 를 보 거나 오늘 은 구체 적 인 사례 를 통 해 설명 하 겠 습 니 다.
(3).QQQ5.X 측면 미끄럼 효과 에 대한 분석:
본 격 버 전 QQ 의 사 이 드 스 케 이 트 효 과 는 다음 과 같 습 니 다.
위 를 살 펴 보면 우 리 는 두 개의 View 로 이해 할 수 있 습 니 다.하 나 는 바닥 이 왼쪽 기능 View 에 해당 하고 다른 하 나 는 상층 의 주요 기능 내용 View 입 니 다.우리 가 위 에서 상층 View 를 끌 거나 좌우 로 미 끄 러 질 때 상층 과 하층부의 View 는 상응 하 게 미 끄 러 지고 View 의 큰 변 화 를 하 는 동시에 관련 애니메이션 도 추가 합 니 다.물론 상부 의 View 를 클릭 하면 사 이 드 메뉴 를 열거 나 닫 을 수 있 습 니 다.
(4).측면 미끄럼 효과 사용자 정의 구성 요소 구현
1.우선 FrameLayout 에 통합 하여 사용자 정의 View DragLayout 를 만 듭 니 다.내부 에서 정 의 된 변 수 는 다음 과 같 습 니 다.(주로 설정 류,제스처,ViewDragHelper 인 스 턴 스,화면 너비,끌 어 당 기 는 하위 보기 View 등 을 포함 합 니 다)
//
private boolean isShowShadow = true;
//
private GestureDetectorCompat gestureDetector;
//
private ViewDragHelper dragHelper;
//
private DragListener dragListener;
//
private int range;
//
private int width;
//
private int height;
//main ViewGroup
private int mainLeft;
private Context context;
private ImageView iv_shadow;
//
private RelativeLayout vg_left;
// ( )
private CustomRelativeLayout vg_main;
그 다음 에 내부 에서 리 셋 인터페이스 가 끌 어 당 기 는 과정 에서 일부 페이지 가 열 리 고 닫 히 며 미 끄 러 지 는 이벤트 리 셋 을 처리 하 는 것 을 정의 했다.
/**
*
*/
public interface DragListener {
//
public void onOpen();
//
public void onClose();
//
public void onDrag(float percent);
}
2.ViewDragHelper 인 스 턴 스 를 만 들 기 시 작 했 습 니 다.사용자 정의 View DragLayout 를 초기 화 할 때 만 들 고 ViewGragHelper 의 정적 방법 을 사용 합 니 다.
public DragLayout(Context context,AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
gestureDetector = new GestureDetectorCompat(context, new YScrollDetector());
dragHelper =ViewDragHelper.create(this, dragHelperCallback);
}
그 중에서 create()방법 을 만 들 때 dragHelperCallBack 리 셋 클래스 가 들 어 왔 습 니 다.네 번 째 시 에 말씀 드 리 겠 습 니 다.3.이 어 ViewGroup 의 이벤트 방법 을 다시 써 서 터치 사건 을 차단 하여 ViewGragHelper 내부 에 처리 하여 이동 서브 View 보 기 를 끌 어 당 기 는 목적 을 달성 해 야 합 니 다.
/**
*
* @param ev
* @return
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return dragHelper.shouldInterceptTouchEvent(ev) &&gestureDetector.onTouchEvent(ev);
}
/**
* ViewDragHelper
* @param e
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent e){
try {
dragHelper.processTouchEvent(e);
} catch (Exception ex) {
ex.printStackTrace();
}
return false;
}
여기 서 우 리 는 onInterceptTouchEvent 에서 이 벤트 를 부모 컨트롤 에서 하위 View 로 이동 시 킨 다음 에 onTouchEvent 방법 에서 ViewDragHelper 가 소비 처 리 를 하도록 차단 합 니 다.4.View DragHelper.Callback 을 만 드 는 인 스 턴 스 를 사용자 정의 하기 시작 합 니 다.dragHelper Callback 은 추상 적 인 방법 try Capture View 를 실현 하고 다음 과 같은 몇 가지 방법 을 다시 써 서 사 이 드 스 케 이 트 기능 을 실현 합 니 다.다음은 하나씩 살 펴 보 겠 습 니 다.
/**
* View
* @param child Child the user is attempting to capture
* @param pointerId ID of the pointer attempting the capture
* @return
*/
@Override
public boolean tryCaptureView(Viewchild, int pointerId) {
return true;
}
뷰 그룹(이 예:DragLayout)의 모든 하위 뷰 를 차단 하고 트 루 로 돌아 가 모든 하위 뷰 를 드래그 하여 이동 할 수 있 음 을 표시 합 니 다.
/**
*
* @param child Child view beingdragged
* @param left Attempted motion alongthe X axis
* @param dx Proposed change inposition for left
* @return
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
if (mainLeft + dx < 0) {
return 0;
} else if (mainLeft + dx >range) {
return range;
} else {
return left;
}
}
이 방법 을 실현 하 는 것 은 수평 방향 이 미 끄 러 지 는 것 을 나타 내 는 동시에 방법 에서 경계 값 을 판단 할 것 이다.예 를 들 어 위의 main view 가 왼쪽 으로 경 계 를 이동 한 것 을 제외 하고 바로 0 으로 돌아 가 왼쪽 가장 왼쪽 에 x=0 만 있 음 을 나타 낸다.그리고 오른쪽으로 이동 하면 오른쪽으로 가장 거리 가 range 로 변 하 는 것 으로 판단 되 며,range 의 초기 화 이후 에 말씀 드 리 겠 습 니 다.이 두 가지 상황 을 제외 하고 바로 left 로 돌아 가면 된다.
/**
*
*@param child Child view to check
* @return
*/
@Override
public int getViewHorizontalDragRange(View child) {
return width;
}
이 방법 은 Callback 내부 에서 기본적으로 0 으로 되 돌아 가기 때문에 이 방법 이 필요 합 니 다.즉,view 의 click 이벤트 가 true 라면 전체 하위 View 가 끌 어 당 겨 이동 할 수 없 는 상황 이 발생 할 수 있 습 니 다.그러면 여 기 는 left view 너비 로 바로 돌아 가 수평 방향 으로 미 끄 러 지 는 가장 먼 거 리 를 나타 낸다.
/**
* View, ,
* @param releasedChild
* @param xvel
* @param yvel
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild,xvel, yvel);
if (xvel > 0) {
open();
} else if (xvel < 0) {
close();
} else if (releasedChild == vg_main&& mainLeft > range * 0.3) {
open();
} else if (releasedChild == vg_left&& mainLeft > range * 0.7) {
open();
} else {
close();
}
}
이 방법 은 드래그 자 View 가 손가락 을 움 직 여 놓 을 때 호출 됩 니 다.이것 은 왼쪽으로 이동 하고 오른쪽으로 이동 하 는 의 도 를 판단 하여 man view(상부 보기)를 열거 나 닫 습 니 다.다음은 실현 의 마지막 방법:onView Position Changed
/**
* View
* @param changedView View whoseposition changed
* @param left New X coordinate of theleft edge of the view
* @param top New Y coordinate of thetop edge of the view
* @param dx Change in X position fromthe last call
* @param dy Change in Y position fromthe last call
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
if (changedView == vg_main) {
mainLeft = left;
} else {
mainLeft = mainLeft + left;
}
if (mainLeft < 0) {
mainLeft = 0;
} else if (mainLeft > range) {
mainLeft = range;
}
if (isShowShadow) {
iv_shadow.layout(mainLeft, 0,mainLeft + width, height);
}
if (changedView == vg_left) {
vg_left.layout(0, 0, width,height);
vg_main.layout(mainLeft, 0,mainLeft + width, height);
}
dispatchDragEvent(mainLeft);
}
};
이 방법 은 이동 서브 뷰 를 끌 어 당 기 는 과정 에서 리 셋 을 하고 이동 좌표 위치 에 따라 left view 와 main view 를 다시 정의 하 는 것 입 니 다.dispathDragEvent()방법 을 동시에 호출 하여 드래그 이벤트 관련 처 리 를 하고 배포 하 는 동시에 상태 에 따라 인 터 페 이 스 를 되 돌려 줍 니 다.
/**
*
* @param mainLeft
*/
private void dispatchDragEvent(int mainLeft) {
if (dragListener == null) {
return;
}
float percent = mainLeft / (float)range;
//
animateView(percent);
//
dragListener.onDrag(percent);
Status lastStatus = status;
if (lastStatus != getStatus()&& status == Status.Close) {
dragListener.onClose();
} else if (lastStatus != getStatus()&& status == Status.Open) {
dragListener.onOpen();
}
}
이 방법 에는 float percent=mainLeft/(float)range 코드 가 있 습 니 다.1 퍼센트 까지 계산 해서 나중에 쓸 게 요.5.하위 View 레이아웃 의 초기 화 및 너비 와 수평 미끄럼 거리의 크기 설정 방법:
/**
*
*
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
if (isShowShadow) {
iv_shadow = new ImageView(context);
iv_shadow.setImageResource(R.mipmap.shadow);
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
addView(iv_shadow, 1, lp);
}
//
vg_left = (RelativeLayout)getChildAt(0);
// ( )
vg_main = (CustomRelativeLayout)getChildAt(isShowShadow ? 2 : 1);
vg_main.setDragLayout(this);
vg_left.setClickable(true);
vg_main.setClickable(true);
}
그리고 컨트롤 크기 가 바 뀌 는 방법:
@Override
protected void onSizeChanged(int w, int h,int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = vg_left.getMeasuredWidth();
height = vg_left.getMeasuredHeight();
// 80%
range = (int) (width *0.8f);
}
이 방법 에서 우 리 는 실시 간 으로 너비 와 높이,그리고 수평 거 리 를 끌 어 당 길 수 있다.6.위의 모든 핵심 코드 는 View DragHelper 를 사용 하여 하위 컨트롤 View 드래그 이동 을 실현 하 는 방법 입 니 다.그러나 우리 의 측면 미끄럼 효과 에 따라 애니메이션 과 미끄럼 과정 에서 View 의 크기 조정 효 과 를 실현 해 야 하기 때문에 우 리 는 애니메이션 오픈 소스 라 이브 러 리 를 도입 하 였 습 니 다.
그리고 앞 에 계 산 된 백분율 에 따라 View 보기 크기 를 조정 합 니 다.
/**
* ,
* @param percent
*/
private void animateView(float percent) {
float f1 = 1 - percent * 0.5f;
ViewHelper.setTranslationX(vg_left,-vg_left.getWidth() / 2.5f + vg_left.getWidth() / 2.5f * percent);
if (isShowShadow) {
//
ViewHelper.setScaleX(iv_shadow, f1* 1.2f * (1 - percent * 0.10f));
ViewHelper.setScaleY(iv_shadow, f1* 1.85f * (1 - percent * 0.10f));
}
}
7.물론 위 에 있 는 것 외 에 한 가지 효과 가 부족 하 다.우리 가 미 끄 러 지 는 과정 에서 손가락 이 풀 리 면 상식 적 으로 view 는 이동 하지 않 을 것 이다.그러면 여기 서 우 리 는 가속도 가 필요 하 다.우리 가 풀 린 후에 도 일정한 속 도 를 유지 할 수 있다.어떻게 실현 해 야 할 까?정 답 은 컴퓨터 스크롤()을 실현 하 는 방법 이다.
/**
* , ,
*/
@Override
public void computeScroll() {
if (dragHelper.continueSettling(true)){
ViewCompat.postInvalidateOnAnimation(this);
}
}
OK 위 에 있 는 DragLayout 에 대한 핵심 코드 는 많 지 않 습 니 다.다음은 DragLayout 류 를 사용 하여 사 이 드 스 케 이 트 효 과 를 실현 합 니 다!(5).측면 미끄럼 효과 구성 요소 사용
1.먼저 사용 한 레이아웃 파일 은 다음 과 같 습 니 다.
<com.chinaztt.widget.DragLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
>
<!-- -->
<includelayoutincludelayout="@layout/left_view_layout"/>
<!-- -->
<com.chinaztt.widget.CustomRelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<RelativeLayout
android:id="@+id/rl_title"
android:layout_width="match_parent"
android:layout_height="49dp"
android:gravity="bottom"
android:background="@android:color/holo_orange_light"
>
<includelayoutincludelayout="@layout/common_top_bar_layout"/>
</RelativeLayout>
<!-- Fragment-->
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<fragment
android:id="@+id/main_info_fragment"
class="com.chinaztt.fragment.OneFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</FrameLayout>
</LinearLayout>
</com.chinaztt.widget.CustomRelativeLayout>
</com.chinaztt.widget.DragLayout>
이 레이아웃 파일 의 부모 층 View 는 DragLayout 입 니 다.그리고 내부 에 두 개의 RelativeLayout 레이아웃 이 있 습 니 다.각각 다음 레이아웃 과 윗 층 의 메 인 레이아웃 을 충당 합 니 다.2.아래 메뉴 레이아웃 을 살 펴 보 겠 습 니 다.여 기 는 제 가 left 라 고 적 었 습 니 다.view_layot.xml 파일 은 주로 세 조각 으로 나 뉘 는데 첫 번 째 상단 은 이미지 개인 기본 정보 레이아웃 이 고 중간 은 기능 입구 목록 이 며 아래쪽 은 설정 등 기능 입 니 다.구체 적 인 레이아웃 코드 는 다음 과 같 습 니 다.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="70dp"
android:background="@drawable/sidebar_bg"
>
<LinearLayout
android:id="@+id/ll1"
android:paddingLeft="30dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- , -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="70dp"
android:orientation="horizontal"
android:gravity="center_vertical"
>
<com.chinaztt.widget.RoundAngleImageView
android:id="@+id/iv_bottom"
android:layout_width="50dp"
android:layout_height="50dp"
android:scaleType="fitXY"
android:src="@drawable/icon_logo"
app:roundWidth="25dp"
app:roundHeight="25dp"/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_gravity="center_vertical"
android:orientation="vertical">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="15dp"
android:text=" :jiangqqlmj"
android:textColor="@android:color/black"
android:textSize="15sp" />
<ImageButton
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="100dp"
android:layout_width="22dp"
android:layout_height="22dp"
android:background="@drawable/qrcode_selector"/>
</RelativeLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="15dp"
android:text="QQ:781931404"
android:textColor="@android:color/black"
android:textSize="13sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="17dp"
android:layout_height="17dp"
android:scaleType="fitXY"
android:src="@drawable/sidebar_signature_nor"/>
<TextView
android:layout_marginLeft="5dp"
android:textSize="13sp"
android:textColor="#676767"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=" !"/>
</LinearLayout>
</LinearLayout>
<!-- -->
<includelayoutincludelayout="@layout/left_view_bottom_layout"
android:id="@+id/bottom_view"
/>
<!-- -->
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/bottom_view"
android:layout_below="@id/ll1"
android:layout_marginBottom="30dp"
android:layout_marginTop="70dp"
android:cacheColorHint="#00000000"
android:listSelector="@drawable/lv_click_selector"
android:divider="@null"
android:scrollbars="none"
android:textColor="#ffffff"/>
</RelativeLayout>
이 레이아웃 은 비교적 간단 합 니 다.상부 의 주요 내용 레이아웃 에 대해 이쪽 에 상단 네 비게 이 션 표시 줄 과 중의 Fragment 내용 정 보 를 놓 고 후기 에 여러분 의 기능 확장 을 남 겨 두 면 됩 니 다.3.메 인 액 티 비 티 는 다음 과 같이 사용 합 니 다.
public class MainActivity extends BaseActivity {
private DragLayout dl;
private ListView lv;
private ImageView iv_icon, iv_bottom;
private QuickAdapter<ItemBean> quickAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setStatusBar();
initDragLayout();
initView();
}
private void initDragLayout() {
dl = (DragLayout) findViewById(R.id.dl);
dl.setDragListener(new DragLayout.DragListener() {
//
@Override
public void onOpen() {
}
//
@Override
public void onClose() {
}
//
@Override
public void onDrag(float percent) {
ViewHelper.setAlpha(iv_icon, 1 - percent);
}
});
}
private void initView() {
iv_icon = (ImageView) findViewById(R.id.iv_icon);
iv_bottom = (ImageView) findViewById(R.id.iv_bottom);
lv = (ListView) findViewById(R.id.lv);
lv.setAdapter(quickAdapter=new QuickAdapter<ItemBean>(this,R.layout.item_left_layout, ItemDataUtils.getItemBeans()) {
@Override
protected void convert(BaseAdapterHelper helper, ItemBean item) {
helper.setImageResource(R.id.item_img,item.getImg())
.setText(R.id.item_tv,item.getTitle());
}
});
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
Toast.makeText(MainActivity.this,"Click Item "+position,Toast.LENGTH_SHORT).show();
}
});
iv_icon.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
dl.open();
}
});
}
}
컨트롤 을 초기 화하 고 미끄럼 모니터 를 설정 하 며 왼쪽 메뉴 기능 목록 설정 을 하면 됩 니 다.하지만 위 에 서 는 QuickAdapter 의 사용 을 보 셔 야 합 니 다.BaseAdapter Helper 프레임 워 크 에 사용 해 야 합 니 다.프로젝트 build.gradle 에서 다음 과 같은 설정 을 해 야 합 니 다.BaseAdapter 사용 에 대한 구체 적 인 설명 블 로그 주 소 는 다음 과 같 습 니 다.
4.정식 운행 효 과 는 다음 과 같다.
5.여기 밑 에 ViewDragHelper 클래스 가 필요 하기 때문에 여러분 이 사용 할 때 V4 패 키 지 를 가 져 와 야 합 니 다.그런데 저 는 ViewGragHelper 클래스 의 소스 코드 를 프로젝트 에 직접 복사 합 니 다.
(6).dragLayout 소스 코드 설명
위 에 서 는 주로 DragLayout 의 구체 적 인 실현 을 분 석 했 습 니 다.하지만 저도 DragLayout 에 주석 이 있 는 모든 소스 코드 를 붙 여서 DragLayout 의 구체 적 인 실현 코드 를 잘 알 수 있 도록 하 겠 습 니 다.
/**
* ViewRragHelper
*/
publicclass DragLayout extends FrameLayout {
private boolean isShowShadow = true;
//
private GestureDetectorCompat gestureDetector;
//
private ViewDragHelper dragHelper;
//
private DragListener dragListener;
//
private int range;
//
private int width;
//
private int height;
//main ViewGroup
private int mainLeft;
private Context context;
private ImageView iv_shadow;
//
private RelativeLayout vg_left;
// ( )
private CustomRelativeLayout vg_main;
//
private Status status = Status.Close;
public DragLayout(Context context) {
this(context, null);
}
public DragLayout(Context context,AttributeSet attrs) {
this(context, attrs, 0);
this.context = context;
}
public DragLayout(Context context,AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
gestureDetector = new GestureDetectorCompat(context, new YScrollDetector());
dragHelper =ViewDragHelper.create(this, dragHelperCallback);
}
class YScrollDetector extends SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1,MotionEvent e2, float dx, float dy) {
return Math.abs(dy) <=Math.abs(dx);
}
}
/**
* View , Callback
*/
private ViewDragHelper.Callback dragHelperCallback = new ViewDragHelper.Callback() {
/**
*
* @param child Child view beingdragged
* @param left Attempted motion alongthe X axis
* @param dx Proposed change inposition for left
* @return
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
if (mainLeft + dx < 0) {
return 0;
} else if (mainLeft + dx >range) {
return range;
} else {
return left;
}
}
/**
* View
* @param child Child the user isattempting to capture
* @param pointerId ID of the pointerattempting the capture
* @return
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return true;
}
/**
*
*@param child Child view to check
* @return
*/
@Override
public int getViewHorizontalDragRange(View child) {
return width;
}
/**
* View, ,
* @param releasedChild
* @param xvel
* @param yvel
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild,xvel, yvel);
if (xvel > 0) {
open();
} else if (xvel < 0) {
close();
} else if (releasedChild == vg_main&& mainLeft > range * 0.3) {
open();
} else if (releasedChild == vg_left&& mainLeft > range * 0.7) {
open();
} else {
close();
}
}
/**
* View
* @param changedView View whoseposition changed
* @param left New X coordinate of theleft edge of the view
* @param top New Y coordinate of thetop edge of the view
* @param dx Change in X position fromthe last call
* @param dy Change in Y position fromthe last call
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
if (changedView == vg_main) {
mainLeft = left;
} else {
mainLeft = mainLeft + left;
}
if (mainLeft < 0) {
mainLeft = 0;
} else if (mainLeft > range) {
mainLeft = range;
}
if (isShowShadow) {
iv_shadow.layout(mainLeft, 0,mainLeft + width, height);
}
if (changedView == vg_left) {
vg_left.layout(0, 0, width,height);
vg_main.layout(mainLeft, 0,mainLeft + width, height);
}
dispatchDragEvent(mainLeft);
}
};
/**
*
*/
public interface DragListener {
//
public void onOpen();
//
public void onClose();
//
public void onDrag(float percent);
}
public void setDragListener(DragListener dragListener) {
this.dragListener = dragListener;
}
/**
*
*
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
if (isShowShadow) {
iv_shadow = new ImageView(context);
iv_shadow.setImageResource(R.mipmap.shadow);
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
addView(iv_shadow, 1, lp);
}
//
vg_left = (RelativeLayout)getChildAt(0);
// ( )
vg_main = (CustomRelativeLayout)getChildAt(isShowShadow ? 2 : 1);
vg_main.setDragLayout(this);
vg_left.setClickable(true);
vg_main.setClickable(true);
}
public ViewGroup getVg_main() {
return vg_main;
}
public ViewGroup getVg_left() {
return vg_left;
}
@Override
protected void onSizeChanged(int w, int h,int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = vg_left.getMeasuredWidth();
height = vg_left.getMeasuredHeight();
// 80%
range = (int) (width * 0.8f);
}
/**
* left main
* @param changed
* @param left
* @param top
* @param right
* @param bottom
*/
@Override
protected void onLayout(boolean changed,int left, int top, int right, int bottom) {
vg_left.layout(0, 0, width, height);
vg_main.layout(mainLeft, 0, mainLeft +width, height);
}
/**
*
* @param ev
* @return
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
returndragHelper.shouldInterceptTouchEvent(ev) &&gestureDetector.onTouchEvent(ev);
}
/**
* ViewDragHelper
* @param e
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent e){
try {
dragHelper.processTouchEvent(e);
} catch (Exception ex) {
ex.printStackTrace();
}
return false;
}
/**
*
* @param mainLeft
*/
private void dispatchDragEvent(intmainLeft) {
if (dragListener == null) {
return;
}
float percent = mainLeft / (float)range;
//
animateView(percent);
//
dragListener.onDrag(percent);
Status lastStatus = status;
if (lastStatus != getStatus()&& status == Status.Close) {
dragListener.onClose();
} else if (lastStatus != getStatus()&& status == Status.Open) {
dragListener.onOpen();
}
}
/**
* ,
* @param percent
*/
private void animateView(float percent) {
float f1 = 1 - percent * 0.5f;
ViewHelper.setTranslationX(vg_left,-vg_left.getWidth() / 2.5f + vg_left.getWidth() / 2.5f * percent);
if (isShowShadow) {
//
ViewHelper.setScaleX(iv_shadow, f1* 1.2f * (1 - percent * 0.10f));
ViewHelper.setScaleY(iv_shadow, f1* 1.85f * (1 - percent * 0.10f));
}
}
/**
* , ,
*/
@Override
public void computeScroll() {
if (dragHelper.continueSettling(true)){
ViewCompat.postInvalidateOnAnimation(this);
}
}
/**
* ( , , )
*/
public enum Status {
Drag, Open, Close
}
/**
*
* @return
*/
public Status getStatus() {
if (mainLeft == 0) {
status = Status.Close;
} else if (mainLeft == range) {
status = Status.Open;
} else {
status = Status.Drag;
}
return status;
}
public void open() {
open(true);
}
public void open(boolean animate) {
if (animate) {
//
if(dragHelper.smoothSlideViewTo(vg_main, range, 0)) {
ViewCompat.postInvalidateOnAnimation(this);
}
} else {
vg_main.layout(range, 0, range * 2,height);
dispatchDragEvent(range);
}
}
public void close() {
close(true);
}
public void close(boolean animate) {
if (animate) {
//
if(dragHelper.smoothSlideViewTo(vg_main, 0, 0)) {
ViewCompat.postInvalidateOnAnimation(this);
}
} else {
vg_main.layout(0, 0, width,height);
dispatchDragEvent(0);
}
}
}
(7).최종 총화오늘 우 리 는 QQ 최신 버 전 QQ6.X 효 과 를 실현 하 는 동시에 View DragHelper,BaseAdapter Helper 의 활용 을 사 용 했 습 니 다.구체 적 인 이 지식 점 의 사용 방법 은 제 블 로그 에 설명 한 글 을 업데이트 하 였 습 니 다.여러분 이 보 시 는 것 을 환영 합 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.