안 드 로 이 드 모방
Demo 는 MVVM 모드 를 기반 으로 작 성 된 것 으로 비판 과 지적 을 환영 합 니 다.
그 중에서 도 Banner 의 무한 윤 방 은 PageSnapHelper 를 사 용 했 고 후속 Recycle View 도 ViewPage 와 유사 한 효 과 를 더 많이 실현 할 수 있 게 되 었 다.
페이지 는 대략 이 몇 부분 으로 나 눌 수 있 음 을 알 수 있다.
1.맨 위 에 번갈아 가 는 배 너
2.중간 에 다른 기능 목록 이 있 을 수 있 음
3.마지막 으로 Tab 페이지(여 기 는 신선 한 것 과 근처 의 두 목록)
OK,이런 레이아웃 요 구 를 볼 때 두 가지 생각 이 있 을 수 있 습 니 다.
1.전체적으로 RefreshLayout 레이아웃 입 니 다.RecycleView 가 내장 되 어 있 고 Banner 페이지,다른 기능 목록 과 TabLayout 는 모두 RecycleView 의 머리 로 RecycleView 에 가입 합 니 다.TabLayout 아래 는 진정한 목록 항목 입 니 다.
2.전체적으로 RefreshLayout 레이아웃 입 니 다.내 부 는 Nest ScrollView,Banner 페이지,다른 기능 목록 입 니 다.TabLayout 는 Nest ScrollView 에 순서대로 배치 한 다음 에 맨 아래 에 FrameLayout 를 배치 하고 TabLayout 를 전환 할 때 서로 다른 Fragment 를 전환 합 니 다.
데모 에 서 는 첫 번 째 방식 을 사용 합 니 다.두 번 째 방식 은 Swipe RefreshLayout 와 내부 FrameLayout 의 미끄럼 이 충돌 할 수 있 음 을 고려 하여 나중에 다시 작성 을 시도 합 니 다.
다음 에 고려 해 야 할 문 제 를 고려 하 다.
TabLayout 는 상단 까지 고정 해 야 합 니 다
먼저 레이아웃 입 니 다.레이아웃 이 간단 합 니 다.Swipe Refresh Layout 에 FrameLayout 를 포함 하고 FrameLayout 에 Recycle View 를 포함 합 니 다.
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/layout_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</android.support.v4.widget.SwipeRefreshLayout>
이제 Sticky Head 가 어떻게 실현 되 는 지 살 펴 보 겠 습 니 다.
// TabLayout
private TabLayout mTabLayout;
// TabLayout ( )
private TabLayout mStickyTabLayout;
// Y ( )
private int mStickyPositionY;
//
private RecyclerView mHomeList;
이것 은 변수의 정의 입 니 다.아래 의 이 종 류 는 제 가 페이지 논리 와 관련 된 변 수 를 추출 하 는 것 입 니 다.
public class HomeEntity extends BaseObservable {
// 0: 1:
public static final int LIST_TYPE_FRESH = 0;
public static final int LIST_TYPE_NEAR = 1;
private int bannerCount;
private int listType = LIST_TYPE_FRESH;
// loading
private boolean refreshLoading;
private boolean nearLoading;
//
private boolean refreshing;
// View ( TabLayout ,LoadingMore )
private int refreshMoreStatus;
private int nearMoreStatus;
//
private int loadingMoreStatus;
}
이것 은 변수의 정의 입 니 다.그리고 두 개의 TabLayout 를 초기 화 합 니 다.주로 TabLayout 의 전환 을 감청 해 야 합 니 다.
mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
int position = tab.getPosition();
// TabLayout Tab
if (!mStickyTabLayout.getTabAt(position).isSelected()) {
mStickyTabLayout.getTabAt(position).select();
mViewModel.changeHomeData(position);
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
mStickyTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
int position = tab.getPosition();
if (!mTabLayout.getTabAt(position).isSelected()) {
mTabLayout.getTabAt(position).select();
mHomeList.stopScroll();
//mAdapter.setEnableLoadMore(false);
mViewModel.changeHomeData(position);
......
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
이 단락 의 논 리 는 비교적 간단 하 다.바로 TabLayout 전환 상 태 를 유지 하 는 통일 을 실현 한 것 이다.TabLayout 전환 을 할 때 Sticky TabLayout 가 선택 한 Tab 도 설정 해 야 한다mViewModel.changeHomeData(position)
이 말 은 데 이 터 를 전환 하기 위해 서 이다.다음은 분석 할 것 이다.다음은 Sticky Head 의 중요 한 코드 입 니 다.
mHomeList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
int[] location = new int[2];
mTabLayout.getLocationInWindow(location);
int count = mViewContainer.getChildCount();
if (location[1] <= mStickyPositionY) {
if (count == 1) {
mViewContainer.addView(mStickyTabLayout);
mBinding.layoutRefresh.setEnabled(false);
}
} else {
if (count > 1) {
mViewContainer.removeView(mStickyTabLayout);
//mOffsetY = DisplayUtil.dip2px(mContainer.getContext(), 46);
//mRefreshPosition = mAdapter.getHeaderLayoutCount();
//mNearPosition = mAdapter.getHeaderLayoutCount();
mBinding.layoutRefresh.setEnabled(true);
}
}
//if (mInitPositionY == -1) {
//mInitPositionY = location[1];
//}
//mHomeListPositionY = location[1];
}
});
주요 논 리 는 TabLayout 이 창 에 있 는 위 치 를 먼저 가 져 오 는 것 입 니 다.Y 좌표 가 머리 를 붙 여 넣 은 Y 좌표 보다 작 으 면 머리 를 붙 여 넣 고 표시 합 니 다.그렇지 않 으 면 머리 를 붙 여 넣 은 포석 에서 제거 합 니 다.count 이 값 을 판단 하 는 것 은 중복 추가 와 중복 제거 스티커 레이아웃 을 방지 하기 위해 서 입 니 다.4
mBinding.layoutRefresh.setEnabled(true/false)
머리 가 꼭대기 에 붙 어 있 을 때 바깥쪽 Swipe RefreshLayout 의 드 롭 다운 새로 고침 오 류 를 제거 하기 위해 서 입 니 다.주석 이 떨 어 진 코드 는 아래 에서 다시 말씀 드 리 겠 습 니 다.위 에 있 는 이렇게 많은 코드 하나만 있 으 면 Sticky Head 가 실 현 됩 니 다.테스트 할 때 작은 문제 가 발생 했 습 니 다.바로 초점 리 셋 으로 인 한 Recycle View 가 초기 위치 로 다시 돌아 가 는 오류 입 니 다.다음은 일시적인 해결 방안 입 니 다.
LinearLayoutManager manager = new LinearLayoutManager(mContainer.getContext()) {
@Override
public boolean onRequestChildFocus(RecyclerView parent, RecyclerView.State state, View child, View focused) {
//TODO View
return true;
}
};
신선 하거나 가 까 운 데 이 터 를 처음 불 러 올 때 나타 나 는 대기 페이지 를 간단히 말 하 겠 습 니 다.주 된 사고방식 은 이렇다
1.이 기다 리 는 LoadingView 는 RecycleView 의 머리 로 TabLayout 뒤에 추 가 된 것 입 니 다.데이터 로드 가 완료 되면 이 LoadingView 는 보이 지 않 는 것 으로 설정 합 니 다.
2.TabLayout 가 전환 되 어 RecycleView 의 데이터 가 다시 그 려 지고 RecyView 가 초기 위치 로 돌아 가기 때문에 RecycleView 가 있 는 위 치 를 기록 한 다음 에 기 록 된 위치 로 수 동 으로 미 끄 러 집 니 다.
구체 적 으로 코드 를 보 겠 습 니 다.
private int mHomeListPositionY;// RecycleView
private int mInitPositionY = -1;// RecycleView Y
// RecycleView , RecycleView , mTabLayout
mHomeList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
int[] location = new int[2];
mTabLayout.getLocationInWindow(location);
int count = mViewContainer.getChildCount();
if (mInitPositionY == -1) {
mInitPositionY = location[1];
}
mHomeListPositionY = location[1];
}
});
// RecycleView
private void setLoadingView(boolean visible, int type) {
int position;
if (type == HomeEntity.LIST_TYPE_FRESH) {
position = mRefreshPosition;
} else {
position = mNearPosition;
}
if (visible) {
mLoadingView.setVisibility(View.VISIBLE);
if (mStickyTabLayout.getVisibility() == View.VISIBLE) {
LinearLayoutManager layoutManager = (LinearLayoutManager) mHomeList.getLayoutManager();
layoutManager.scrollToPositionWithOffset(0, mHomeListPositionY - mInitPositionY);
}
} else {
mLoadingView.setVisibility(View.GONE);
LinearLayoutManager layoutManager = (LinearLayoutManager) mHomeList.getLayoutManager();
if (mViewContainer.getChildCount() > 1) {
layoutManager.scrollToPositionWithOffset(position, mStickyTabLayout.getHeight());
} else {
layoutManager.scrollToPositionWithOffset(0, mHomeListPositionY - mInitPositionY);
}
}
}
마지막 으로 신선 한 것 과 가 까 운 것 을 더 많이 불 러 올 때 페이지 의 실현 을 살 펴 보 겠 습 니 다.여기 Adapter 는 제3자 BRVAH 를 사 용 했 기 때문에 Loading More 의 상태 에 비해 BRVAH 가 봉 해 주 었 습 니 다.하나의 List 이지 만 사실은 두 개의 목록 이 하나의 List 를 재 활용 한 것 이기 때문에 여기 Loading More 상 태 는 두 개 를 기록 해 야 합 니 다.전환 하기 편리 할 때 표 의 Loading More 상 태 는 정확 합 니 다.다음은 주요 코드 를 보 겠 습 니 다.
if (propertyId == BR.refreshLoading) {
if (HomeEntity.LIST_TYPE_FRESH != entity.getListType()) {
return;
}
if (mLoadingView.getVisibility() == View.GONE) {
mAdapter.setEnableLoadMore(true);
}
} else if (propertyId == BR.nearLoading) {
if (HomeEntity.LIST_TYPE_NEAR != entity.getListType()) {
return;
}
if (mLoadingView.getVisibility() == View.GONE) {
mAdapter.setEnableLoadMore(true);
}
} else if (propertyId == BR.loadingMoreStatus) {
int status = entity.getLoadingMoreStatus();
mAdapter.setEnableLoadMore(true);
if (LoadMoreView.STATUS_DEFAULT == status) {
mAdapter.loadMoreComplete();
} else if (LoadMoreView.STATUS_END == status) {
mAdapter.loadMoreEnd();
} else if (LoadMoreView.STATUS_FAIL == status) {
mAdapter.loadMoreFail();
}
}
4.567914.와 4.567914.모두 감청 첫 로드 입 니 다.여기
if (mLoadingView.getVisibility() == View.GONE) {
mAdapter.setEnableLoadMore(true);
}
이것 은 첫 번 째 로 딩 을 방지 하기 위해 Loading 페이지 를 표시 할 때 Loading More 레이아웃 을 표시 합 니 다.BR.refreshLoading
이것 이 바로 Loading More 의 상 태 를 감청 하여 List 를 업데이트 하 는 Adapter 입 니 다.다른 주요 뷰 모델 코드 는 홈 뷰 모델 에 있 습 니 다.
주요 한 몇 가지 점
4.567917.붙 여 넣 기 헤드 레이아웃 의 논리
로 컬 다운로드:여 기 를 클릭 하 세 요.
총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.