예를 들어 아래에 더 이상 콘텐츠가 없을 때 NestedScrollView & CollapsingToolbarLayout의 스크롤을 비활성화하는 방법은 무엇입니까?
배경
스크롤 된 콘텐츠에 따라 화면 상단 영역이 축소 및 확장되는 많은 앱에서 볼 수있는 것과 동일한 기능을 추가하려고합니다.
이를 위해 CheeseSquare 샘플 에 표시된대로 Google의 디자인 라이브러리를 사용 합니다.
문제
문제는 NestedScrollView에 얼마나 많은 콘텐츠가 있든 상관없이 콘텐츠의 마지막보기 아래로 스크롤 할 수있게하여 자체 크기가 최소화 된 작업 표시 줄의 최종 상태를 볼 수 있도록합니다.
간단히 말해서 아래로 스크롤 할 때 표시되는 내용입니다 (CheeseSquare 샘플의 수정 된 내용).
이것이 내가 하단으로 스크롤 할 때 갖고 싶은 것입니다 (연락처 앱에서 가져옴) :
또한 하단 시트 내용이 픽 상태 인 경우에도 스크롤이 가능하다는 ThreePhasesBottomSheet 샘플 의 버그를 수정하려고합니다 . 재현하려면 가로로 스크롤 (이 방법으로 스크롤 할 것이 없으므로 아무 작업도하지 않음)을 시작한 다음 세로로 스크롤하면 하단 시트의 내용이 스크롤됩니다.
따라서 "transformView ()"메서드에서 스크롤을 비활성화해야합니다.
이것은 정상적인 사용을 사용하는 방법입니다.
그리고 이것은 스크롤을 차단하지 않는 버그로 작동하는 방법입니다.
내가 시도한 것
" layout_scrollFlags "플래그를 사용하여 높이를 wrap_content로 변경하고 clipToPadding 및 fitsSystemWindows 속성을 제거하려고했습니다.
다음은 여러 개의 cardView가 아닌 하나의 cardView 만 포함하도록 수정 한 샘플 XML 파일입니다.
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="@dimen/detail_backdrop_height"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:fitsSystemWindows="true">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginStart="48dp"
app:expandedTitleMarginEnd="64dp">
<ImageView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:fitsSystemWindows="true"
app:layout_collapseMode="parallax" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="24dp">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/card_margin">
<LinearLayout
style="@style/Widget.CardContent"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Info"
android:textAppearance="@style/TextAppearance.AppCompat.Title" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/cheese_ipsum" />
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.FloatingActionButton
android:layout_height="wrap_content"
android:layout_width="wrap_content"
app:layout_anchor="@id/appbar"
app:layout_anchorGravity="bottom|right|end"
android:src="@drawable/ic_discuss"
android:layout_margin="@dimen/fab_margin"
android:clickable="true"/>
</android.support.design.widget.CoordinatorLayout>
다음 코드도 시도했습니다.
((AppBarLayout.LayoutParams) collapsingToolbar.getLayoutParams()).setScrollFlags(0);
그러나 이것은 여전히 CheeseSquare 예제 에서 NestedScrollView 자체의 스크롤을 허용했으며 ThreePhasesBottomSheet 샘플 에서도 플링을 허용했습니다 .
질문
하단에 더 이상 표시 할 콘텐츠가 없을 때 스크롤을 중지하려면 어떻게해야합니까?
또한 언제든지 NestedScrollView의 스크롤을 비활성화하려면 어떻게해야합니까 ( ThreePhasesBottomSheet 샘플의 경우)? "setEnableScrolling (...)"과 같은 것입니까?
NestedScrollView를 확장하고 ScrollingViewBehavior에서 확장하려고 시도했지만 스크롤을 비활성화하기 위해 수행 할 수있는 작업을 찾지 못했습니다.
변경하는 것은 매우 간단한 것일 수 있지만 무엇을 찾을 수 없습니다.
편집 : 필요한 경우 현재 디자인 및 지원 라이브러리에 사용하는 것입니다.
compile 'com.android.support:appcompat-v7:23.1.0'
compile 'com.android.support:design:23.1.0'
편집 : # 2의 경우, 항상 "false"로 설정된 것처럼 "sheetViewOwnsTouch"변수와 관련된 모든 것을 비활성화하는 BottomSheetLayout.java 파일 내에서 해결 방법을 찾았습니다. 이렇게하면 하단 시트에서 터치 이벤트를 훔칠 수 있습니다. 그러나 이것은 해결 방법 일 뿐이며이 경우에만 해당됩니다. 또한 다른 뷰에서 처리해야하는 일부 터치 이벤트가 발생합니다. 프로그래밍 방식으로 스크롤을 차단하는 방법과 콘텐츠를 표시하기에 충분한 공간이있는 다른 경우에도 여전히 알고 싶습니다.
하단에 더 이상 표시 할 콘텐츠 가 없을 때 스크롤을 중지하려면 어떻게해야 합니까?
첫째, 아래에서 언급했듯이 질문에서 말한 스크롤은 NestedScrollView
. 에 속합니다 CollapsingToolbarLayout
. NestedScrollView
때의 스크롤 이벤트는 발생 CollapsingToolbarLayout
완전히 붕괴, 어떤이 (하단에 도달) 더 많은 콘텐츠 내부에있을 때 때 물론 그것은 스크롤을 중지하지 않습니다. 의 경우 CollapsingToolbarLayout
툴바의 layout_height로 축소됩니다 (xml 파일에서와 같이 "?attr/actionBarSize"
). 다음 이미지는 도구 모음 인 빨간색 직사각형에주의를 기울이는 것을 보여줍니다 (배경 설정).
따라서 # 1에 대한 솔루션을 얻으려면의 높이를 계산해야합니다. NestedScrollView
화면 높이보다 작 으면 도구 모음의 높이를 수정합니다.
간단히 말해 activity_detail.xml
다음과 같이 업데이트 할 수 있습니다 .
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="@dimen/detail_backdrop_height"
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="false"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/card_margin">
<LinearLayout
style="@style/Widget.CardContent"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Info"
android:textAppearance="@style/TextAppearance.AppCompat.Title" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/cheese_ipsum" />
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
그리고 CheeseDetailActivity.java :
public class CheeseDetailActivity extends AppCompatActivity {
public static final String EXTRA_NAME = "cheese_name";
private final Context mContext = this;
private int screenHeight;
private int linearLayoutHeight;
private int toolbarHeight_org;
private int toolbarHeight;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
Intent intent = getIntent();
final String cheeseName = intent.getStringExtra(EXTRA_NAME);
screenHeight = getScreenHeight(this);
TypedValue typedValue = new TypedValue();
getTheme().resolveAttribute(R.attr.colorPrimary, typedValue, true);
final int colorPrimary = typedValue.data;
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
AppBarLayout appbar = (AppBarLayout) findViewById(R.id.appbar);
final CoordinatorLayout.LayoutParams appbarLayoutParams = (CoordinatorLayout.LayoutParams)appbar.getLayoutParams();
final ViewGroup.LayoutParams toolbarLayoutParams = toolbar.getLayoutParams();
if (toolbarLayoutParams != null) {
toolbarHeight_org = toolbarLayoutParams.height;
toolbarHeight = toolbarLayoutParams.height;
}
final CollapsingToolbarLayout collapsingToolbar =
(CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
collapsingToolbar.setTitle(cheeseName);
collapsingToolbar.setContentScrimColor(colorPrimary);
collapsingToolbar.setExpandedTitleTextAppearance(R.style.ExpandedTitleTextAppearance);
//collapsingToolbar.setCollapsedTitleTextAppearance(R.style.CollapsedTitleTextAppearance);
final LinearLayout linearLayout = (LinearLayout) findViewById(R.id.linearLayout1);
ViewTreeObserver observer = linearLayout.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
linearLayoutHeight = linearLayout.getHeight();
if (linearLayoutHeight + toolbarHeight < screenHeight) {
if (toolbarLayoutParams != null) {
toolbarLayoutParams.height = screenHeight - linearLayoutHeight - 20;
if (toolbarLayoutParams.height < toolbarHeight_org) {
toolbarLayoutParams.height = toolbarHeight_org;
}
int extended_text_size = (int) getResources().getDimension(R.dimen.expanded_text_size);
if (appbarLayoutParams.height - toolbarLayoutParams.height <= extended_text_size) {
int value = appbarLayoutParams.height - toolbarLayoutParams.height;
if (value < 0) {
appbarLayoutParams.height = toolbarLayoutParams.height - value + extended_text_size * 3;
} else {
appbarLayoutParams.height = toolbarLayoutParams.height + extended_text_size * 3;
}
if (appbarLayoutParams.height >= screenHeight) {
appbarLayoutParams.height = screenHeight;
}
}
// collapsingToolbar.setContentScrimColor(getResources().getColor(android.R.color.transparent));
if (toolbarLayoutParams.height > toolbarHeight_org) {
collapsingToolbar.setContentScrimColor(ContextCompat.getColor(mContext, android.R.color.transparent));
}
}
}
// Removes the listener if possible
ViewTreeObserver viewTreeObserver = linearLayout.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
linearLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
linearLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
}
});
loadBackdrop();
appbar.setExpanded(true);
}
private int getScreenHeight(Context context) {
int measuredHeight;
Point size = new Point();
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
wm.getDefaultDisplay().getSize(size);
measuredHeight = size.y;
} else {
Display d = wm.getDefaultDisplay();
measuredHeight = d.getHeight();
}
return measuredHeight;
}
private void loadBackdrop() {
final ImageView imageView = (ImageView) findViewById(R.id.backdrop);
Glide.with(this).load(Cheeses.getRandomCheeseDrawable()).centerCrop().into(imageView);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.sample_actions, menu);
return true;
}
}
결과는 다음과 같습니다.
With Cheesesquare sample, I have customized this project and uploaded to My GitHub. I agree that it still has some problems, however, at least it can be a solution for your 1st issue.
Please take a look. Hope it helps!
To disable scrolling, just set both NestedScrollView and it's LinearLayout child height to 'wrap_content'.
That will not work completely as you wish, but at least it will not be scrollable, if content fits on screen completely.
Talking about your Contacts app example, looks like it's not using CoordinatorLayout and other things that come with it.
This behavior can be done in this way:
<ScrollView
android:id="@+id/scroll_adinfo"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="@dimen/image_height"
android:src="@mipmap/ic_launcher"/>
<LinearLayout
android:id="@+id/layout_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/image_height">
<!-- YOUR CONTENT HERE -->
</LinearLayout>
</FrameLayout>
</ScrollView>
And in your code you will move the image on scroll:
final ImageView image = (ImageView) findViewById(R.id.image);
((ScrollView) rootView.findViewById(R.id.scroll_adinfo)).getViewTreeObserver().addOnScrollChangedListener(
new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
int scrollY = ((ScrollView) rootView.findViewById(R.id.scroll_adinfo)).getScrollY();
image.setY(scrollY / 2);
}
});
I have extracted that from one of my projects and edited it so I can miss something.
'Program Tip' 카테고리의 다른 글
외부 primop에 대한 cmm 호출 형식 (integer-gmp 예) (0) | 2020.11.25 |
---|---|
앱 * 및 * 웹 사이트에 대해 OAuth2로 인증 (0) | 2020.11.25 |
systemgroup.com.apple.configurationprofiles 경로에 대한 시스템 그룹 컨테이너 (0) | 2020.11.25 |
와이드 스크린 모니터를 두 개 이상의 가상 모니터로 분할하는 방법이 있습니까? (0) | 2020.11.25 |
GoogleTest vs CppUnit : 사실 (0) | 2020.11.25 |