GoogleのDesign Support Libraryの最近のリリースで、いくつかのクールな新しいビューが導入されました。新しいコンポーネントの一部(CoordinatorLayoutなど)を使用すると、スクロール動作を実現できる可能性があります(!).
組み込みのスクロール動作を試してみましたが、何も機能しません。
レイアウトにFloatingActionButtonの代わりにボトムバー(LinearLayout)があります
ここで私が欲しいもの。
これを達成するための組み込みメカニズムはありますか?またはJavaコードを書く必要がありますか?
これが私のコードです:
main_activty.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:layout_width="match_parent"
Android:layout_height="match_parent"
Android:fitsSystemWindows="true">
<Android.support.design.widget.AppBarLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:fitsSystemWindows="true"
Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<include layout="@layout/toolbar_srp" />
<Android.support.design.widget.TabLayout
Android:id="@+id/tabs"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:elevation="5dp"
app:tabGravity="fill"
app:tabIndicatorColor="@Android:color/white"
app:tabMode="fixed" />
</Android.support.design.widget.AppBarLayout>
<!-- All Scrollable Views -->
<Android.support.v4.view.ViewPager
Android:id="@+id/viewpager"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<!-- Bottom bar-->
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_gravity="bottom"
Android:background="#a0000000"
Android:orientation="horizontal"
Android:paddingBottom="@dimen/padding_small"
Android:paddingTop="@dimen/padding_small">
<TextView
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="0.33"
Android:gravity="center"
Android:paddingBottom="@dimen/padding_small"
Android:paddingTop="@dimen/padding_small"
Android:text="AC"
Android:textColor="@color/white" />
<TextView
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="0.33"
Android:gravity="center"
Android:paddingBottom="@dimen/padding_small"
Android:paddingTop="@dimen/padding_small"
Android:text="Sleeper"
Android:textColor="@color/white" />
<TextView
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="0.33"
Android:gravity="center"
Android:paddingBottom="@dimen/padding_small"
Android:paddingTop="@dimen/padding_small"
Android:text="Premium"
Android:textColor="@color/white" />
</LinearLayout>
</Android.support.design.widget.CoordinatorLayout>
fragment.xml(ここでは、recyclerviewコードを入力しました)
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@color/white"
Android:orientation="vertical">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="horizontal"
Android:paddingBottom="@dimen/padding_small"
Android:paddingTop="@dimen/padding_small"
Android:weightSum="1">
<TextView
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="0.33"
Android:background="@drawable/bg_srp_sorter"
Android:clickable="true"
Android:gravity="center"
Android:paddingBottom="@dimen/padding_small"
Android:paddingTop="@dimen/padding_small"
Android:text="Departure" />
<TextView
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="0.33"
Android:background="@drawable/bg_srp_sorter"
Android:gravity="center"
Android:paddingBottom="@dimen/padding_small"
Android:paddingTop="@dimen/padding_small"
Android:text="Duration" />
<TextView
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="0.33"
Android:gravity="center"
Android:paddingBottom="@dimen/padding_small"
Android:paddingTop="@dimen/padding_small"
Android:text="Price" />
</LinearLayout>
<View
Android:layout_width="match_parent"
Android:layout_height="1dp"
Android:background="@color/lite_gray"></View>
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical"
Android:weightSum="1">
<Android.support.v7.widget.RecyclerView
Android:id="@+id/bus_list_recycler_view"
Android:layout_width="match_parent"
Android:layout_height="0dp"
Android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
toolbar.xml
<?xml version="1.0" encoding="utf-8"?>
<Android.support.v7.widget.Toolbar
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:id="@+id/toolbar"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:background="@color/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
Android:minHeight="?attr/actionBarSize">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:weightSum="1">
<LinearLayout
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="0.10">
<ImageView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:src="@drawable/abc_ic_ab_back_mtrl_am_alpha" />
</LinearLayout>
<LinearLayout
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="0.78"
Android:orientation="vertical">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="horizontal"
Android:weightSum="1">
<TextView
Android:id="@+id/toolbar_title_source"
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="0.47"
Android:ellipsize="end"
Android:singleLine="true"
Android:text="Thiruvananthapuram "
Android:textColor="@color/white"
Android:textSize="@dimen/label_text_size_large" />
<TextView
Android:id="@+id/toolbar_title_arrow"
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="0.08"
Android:text="@string/char_right"
Android:textColor="@color/white"
Android:textSize="@dimen/label_text_size_large"
Android:textStyle="bold" />
<TextView
Android:id="@+id/toolbar_title_destination"
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="0.47"
Android:ellipsize="end"
Android:singleLine="true"
Android:text=" Cochin"
Android:textColor="@color/white"
Android:textSize="@dimen/label_text_size_large" />
</LinearLayout>
<TextView
Android:id="@+id/toolbar_sub_title"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="2 Seat(s)"
Android:textColor="@color/lite_gray"
Android:textSize="@dimen/label_text_size_normal" />
</LinearLayout>
<LinearLayout
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="0.13">
<ImageView
Android:layout_width="30dp"
Android:layout_height="30dp"
Android:scaleType="fitCenter"
Android:src="@drawable/filter" />
</LinearLayout>
</LinearLayout>
</Android.support.v7.widget.Toolbar>
CoordinatorLayout
を使用しているので、以下の例に従って、要求したものを実現できるカスタムBehaviour
を作成できます。create
extends CoordinatorLayout.Behavior<View>
以下の例に従ってください:
public class QuickReturnFloaterBehavior extends CoordinatorLayout.Behavior<View> {
private int distance;
public QuickReturnFloaterBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
}
@Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) {
if (dy > 0 && distance < 0 || dy < 0 && distance > 0) {
child.animate().cancel();
distance = 0;
}
distance += dy;
final int height = child.getHeight() > 0 ? (child.getHeight()) : 600/*update this accordingly*/;
if (distance > height && child.isShown()) {
hide(child);
} else if (distance < 0 && !child.isShown()) {
show(child);
}
}
private void hide(View view) {
view.setVisibility(View.GONE);// use animate.translateY(height); instead
}
private void show(View view) {
view.setVisibility(View.VISIBLE);// use animate.translateY(-height); instead
}
}
これを適用するにはbehaviour
これをレイアウトに追加します
app:layout_behavior="com.example.QuickReturnFloaterBehavior"
これは私がやった方法です:
mRecylerView.addOnScrollListener(new HideShowScrollListener() {
@Override
public void onHide() {
//fab.animate().setInterpolator(new AccelerateDecelerateInterpolator()).scaleX(0).scaleY(0);
// do your hiding animation here
}
@Override
public void onShow() {
// fab.animate().setInterpolator(new AccelerateDecelerateInterpolator()).scaleX(1).scaleY(1);
// do your showing animation here
}
});
HideShowScrollListener.classが必要になります
/**
* This class is a ScrollListener for RecyclerView that allows to show/hide
* views when list is scrolled.
* */
public abstract class HideShowScrollListener extends RecyclerView.OnScrollListener {
private static final int HIDE_THRESHOLD = 20;
private int scrolledDistance = 0;
private boolean controlsVisible = true;
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (scrolledDistance > HIDE_THRESHOLD && controlsVisible) {
onHide();
controlsVisible = false;
scrolledDistance = 0;
} else if (scrolledDistance < -HIDE_THRESHOLD && !controlsVisible) {
onShow();
controlsVisible = true;
scrolledDistance = 0;
}
if((controlsVisible && dy>0) || (!controlsVisible && dy<0)) {
scrolledDistance += dy;
}
}
public abstract void onHide();
public abstract void onShow();
}
public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator();
private boolean mIsAnimatingOut = false;
public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
super();
}
@Override
public boolean onStartNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child,
final View directTargetChild, final View target, final int nestedScrollAxes) {
// Ensure we react to vertical scrolling
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
|| super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
}
@Override
public void onNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child,
final View target, final int dxConsumed, final int dyConsumed,
final int dxUnconsumed, final int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
if (dyConsumed > 0 && !this.mIsAnimatingOut && child.getVisibility() == View.VISIBLE) {
// User scrolled down and the FAB is currently visible -> hide the FAB
animateOut(child);
} else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
// User scrolled up and the FAB is currently not visible -> show the FAB
animateIn(child);
}
}
// Same animation that FloatingActionButton.Behavior uses to hide the FAB when the AppBarLayout exits
private void animateOut(final FloatingActionButton button) {
if (Build.VERSION.SDK_INT >= 14) {
ViewCompat.animate(button).scaleX(0.0F).scaleY(0.0F).alpha(0.0F).setInterpolator(INTERPOLATOR).withLayer()
.setListener(new ViewPropertyAnimatorListener() {
public void onAnimationStart(View view) {
ScrollAwareFABBehavior.this.mIsAnimatingOut = true;
}
public void onAnimationCancel(View view) {
ScrollAwareFABBehavior.this.mIsAnimatingOut = false;
}
public void onAnimationEnd(View view) {
ScrollAwareFABBehavior.this.mIsAnimatingOut = false;
view.setVisibility(View.GONE);
}
}).start();
} else {
Animation anim = AnimationUtils.loadAnimation(button.getContext(), R.anim.fab_out);
anim.setInterpolator(INTERPOLATOR);
anim.setDuration(200L);
anim.setAnimationListener(new Animation.AnimationListener() {
public void onAnimationStart(Animation animation) {
ScrollAwareFABBehavior.this.mIsAnimatingOut = true;
}
public void onAnimationEnd(Animation animation) {
ScrollAwareFABBehavior.this.mIsAnimatingOut = false;
button.setVisibility(View.GONE);
}
@Override
public void onAnimationRepeat(final Animation animation) {
}
});
button.startAnimation(anim);
}
}
// Same animation that FloatingActionButton.Behavior uses to show the FAB when the AppBarLayout enters
private void animateIn(FloatingActionButton button) {
button.setVisibility(View.VISIBLE);
if (Build.VERSION.SDK_INT >= 14) {
ViewCompat.animate(button).scaleX(1.0F).scaleY(1.0F).alpha(1.0F)
.setInterpolator(INTERPOLATOR).withLayer().setListener(null)
.start();
} else {
Animation anim = AnimationUtils.loadAnimation(button.getContext(), R.anim.fab_in);
anim.setDuration(200L);
anim.setInterpolator(INTERPOLATOR);
button.startAnimation(anim);
}
}
}
xml app:layout_behaviorのように設定します。
<Android.support.design.widget.FloatingActionButton
Android:id="@+id/fab"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="end|bottom"
Android:layout_margin="16dp"
app:fabSize="mini"
Android:src="@drawable/ic_action_edit"
app:layout_behavior="com.package.name.ScrollAwareFABBehavior"/>
package com.keshav.hideactionbarandfooterexample;
import Android.os.Bundle;
import Android.support.v7.app.AppCompatActivity;
import Android.support.v7.widget.LinearLayoutManager;
import Android.support.v7.widget.RecyclerView;
import Android.support.v7.widget.Toolbar;
import Android.util.Log;
import Android.view.View;
import Android.view.animation.AccelerateInterpolator;
import Android.view.animation.DecelerateInterpolator;
import Android.widget.FrameLayout;
import Android.widget.ImageButton;
import Java.util.ArrayList;
import Java.util.List;
import adapters.RecyclerAdapter;
import listners.HidingScrollListener;
public class MainActivity extends AppCompatActivity {
private Toolbar mToolbar;
private Toolbar toolbar_bottom;
private ImageButton mFabButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.AppThemeRed);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e("keshav", "MainActivity called");
initToolbar();
mFabButton = (ImageButton) findViewById(R.id.fabButton);
initRecyclerView();
}
private void initToolbar() {
mToolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar_bottom = (Toolbar) findViewById(R.id.toolbar_bottom);
setSupportActionBar(mToolbar);
setSupportActionBar(toolbar_bottom);
setTitle(getString(R.string.app_name));
mToolbar.setTitleTextColor(getResources().getColor(Android.R.color.white));
toolbar_bottom.setTitleTextColor(getResources().getColor(Android.R.color.white));
toolbar_bottom.setVisibility(View.GONE);
}
private void initRecyclerView() {
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
RecyclerAdapter recyclerAdapter = new RecyclerAdapter(createItemList());
recyclerView.setAdapter(recyclerAdapter);
recyclerView.addOnScrollListener(new HidingScrollListener() {
@Override
public void onHide() {
hideViews();
}
@Override
public void onShow() {
showViews();
}
});
}
private void hideViews() {
// TODO (-mToolbar) plus means 2 view above ho jaye or not visible to user
mToolbar.animate().translationY(-mToolbar.getHeight()).setInterpolator(new AccelerateInterpolator(2));
// TODO uncomment this Hide Footer in Android when Scrolling
// TODO (+mToolbar) plus means 2 view forward ho jaye or not visible to user
toolbar_bottom.animate().translationY(+toolbar_bottom.getHeight()).setInterpolator(new AccelerateInterpolator(2));
// TODO keshav Hide Also Floatng Button In Android
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mFabButton.getLayoutParams();
int fabBottomMargin = lp.bottomMargin;
mFabButton.animate().translationY(mFabButton.getHeight() + fabBottomMargin).setInterpolator(new AccelerateInterpolator(2)).start();
// TODO keshav Hide Also Floatng Button In Android
}
private void showViews() {
mToolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2));
// TODO uncomment this Hide Footer in Android when Scrolling
toolbar_bottom.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2));
mFabButton.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)).start();
}
private List<String> createItemList() {
List<String> itemList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
itemList.add("Item " + i);
}
return itemList;
}
}
=============================================
RecyclerAdapter
=============================================
package adapters;
import Android.content.Context;
import Android.support.v7.widget.RecyclerView;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;
import com.keshav.hideactionbarandfooterexample.R;
import Java.util.List;
/*
* RecyclerView Adapter that allows to add a header view.
* */
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_HEADER = 2;
private static final int TYPE_ITEM = 1;
private List<String> mItemList;
public RecyclerAdapter(List<String> itemList) {
mItemList = itemList;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
if (viewType == TYPE_ITEM) {
final View view = LayoutInflater.from(context).inflate(R.layout.recycler_item, parent, false);
return RecyclerItemViewHolder.newInstance(view);
} else if (viewType == TYPE_HEADER) {
final View view = LayoutInflater.from(context).inflate(R.layout.recycler_header, parent, false);
return new RecyclerHeaderViewHolder(view);
}
throw new RuntimeException("There is no type that matches the type " + viewType + " + make sure your using types correctly");
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
if (!isPositionHeader(position)) {
RecyclerItemViewHolder holder = (RecyclerItemViewHolder) viewHolder;
String itemText = mItemList.get(position - 1); // header
holder.setItemText(itemText);
}
}
public int getBasicItemCount() {
return mItemList == null ? 0 : mItemList.size();
}
@Override
public int getItemViewType(int position) {
if (isPositionHeader(position)) {
return TYPE_HEADER;
}
return TYPE_ITEM;
}
@Override
public int getItemCount() {
return getBasicItemCount() + 1; // header
}
private boolean isPositionHeader(int position) {
return position == 0;
}
}
=====================================================
RecyclerHeaderViewHolder
=====================================================
package adapters;
import Android.support.v7.widget.RecyclerView;
import Android.view.View;
public class RecyclerHeaderViewHolder extends RecyclerView.ViewHolder {
public RecyclerHeaderViewHolder(View itemView) {
super(itemView);
}
}
=====================================================
RecyclerItemViewHolder
=====================================================
package adapters;
import Android.support.v7.widget.RecyclerView;
import Android.view.View;
import Android.widget.TextView;
import com.keshav.hideactionbarandfooterexample.R;
public class RecyclerItemViewHolder extends RecyclerView.ViewHolder {
private final TextView mItemTextView;
public RecyclerItemViewHolder(final View parent, TextView itemTextView) {
super(parent);
mItemTextView = itemTextView;
}
public static RecyclerItemViewHolder newInstance(View parent) {
TextView itemTextView = (TextView) parent.findViewById(R.id.itemTextView);
return new RecyclerItemViewHolder(parent, itemTextView);
}
public void setItemText(CharSequence text) {
mItemTextView.setText(text);
}
}
===================================================
activity_main.xml
===================================================
<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<Android.support.v7.widget.RecyclerView
Android:id="@+id/recyclerView"
Android:layout_width="match_parent"
Android:layout_height="match_parent"/>
<Android.support.v7.widget.Toolbar
Android:id="@+id/toolbar"
Android:layout_width="match_parent"
Android:layout_height="?attr/actionBarSize"
Android:background="?attr/colorPrimary"/>
<ImageButton
Android:id="@+id/fabButton"
Android:layout_width="56dp"
Android:layout_height="56dp"
Android:layout_gravity="bottom|right"
Android:layout_marginBottom="16dp"
Android:layout_marginRight="16dp"
Android:background="@drawable/fab_bcg"
Android:src="@drawable/ic_favorite_outline_white_24dp"
Android:contentDescription="@string/fab_description"/>
<RelativeLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<Android.support.v7.widget.Toolbar
Android:id="@+id/toolbar_bottom"
Android:layout_width="match_parent"
Android:layout_alignParentBottom="true"
Android:layout_height="?attr/actionBarSize"
Android:background="?attr/colorPrimary"/>
</RelativeLayout>
</FrameLayout>
==================================================
recycle_header.xml in layout folder
==================================================
<?xml version="1.0" encoding="utf-8"?>
<View xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="?attr/actionBarSize"/>
==================================================
recycle_item.xml in layout folder
==================================================
<?xml version="1.0" encoding="utf-8"?>
<Android.support.v7.widget.CardView xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:card_view="http://schemas.Android.com/apk/res-auto"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:layout_margin="8dp"
card_view:cardCornerRadius="4dp">
<TextView
Android:id="@+id/itemTextView"
Android:layout_width="match_parent"
Android:layout_height="?attr/listPreferredItemHeight"
Android:gravity="center_vertical"
Android:padding="8dp"
style="@style/Base.TextAppearance.AppCompat.Body2"/>
</Android.support.v7.widget.CardView>
=================================================
styles.xml
=================================================
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
</style>
<style name="AppThemeRed" parent="AppTheme">
<item name="colorPrimary">@color/color_primary_red</item>
<item name="colorPrimaryDark">@color/color_primary_red_dark</item>
</style>
<style name="AppThemeGreen" parent="AppTheme">
<item name="colorPrimary">@color/color_primary_green</item>
<item name="colorPrimaryDark">@color/color_primary_green_dark</item>
</style>
<style name="AppThemeBlue" parent="AppTheme">
<item name="colorPrimary">@color/color_primary_blue</item>
<item name="colorPrimaryDark">@color/color_primary_blue_dark</item>
<item name="colorAccent">@color/color_accent_pink</item>
</style>
</resources>
build.gradle依存関係
compile 'com.Android.support:appcompat-v7:25.3.1'
compile 'com.Android.support:recyclerview-v7:25.3.1'
compile 'com.Android.support:cardview-v7:25.3.1'
compile 'com.Android.support:design:25.3.1'
@ k0shの QuickReturnFloaterBehavior は機能しますが、わずかなスクロールが聞こえないことがあります。
NestedScrollView
にコンテンツがあり、下部バーとしてLinearLayout
があり、リサイクラービューがありませんでした。そのため、他の推奨される回答は使用できません。
同じ状況の人は、この投稿のBottomNavigationBehavior
ボトムナビゲーションの動作 を使用できます。それは完全に機能し、便利です。
現在のトップレベルビューにコンテンツがスクロールしている場合、下部のナビゲーションは、下にスクロールすると非表示になり、コンテンツを上にスクロールすると元に戻ります。このためには、スクロールの方向に注意する必要があります。 VerticalScrollingBehavior は、スクロール方向のイベントをディスパッチするCoordinatorLayout.Behaviorの拡張である、一般的なレイアウト動作です。
bottomNavigationBehaviorのソースコード- https://Gist.github.com/NikolaDespotoski/1d6fef4949eb9be05a46#file-bottomnavigationbehavior-Java
BottomNavigationBehavior
からのスニペット
@Override
public void onDirectionNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed, @ScrollDirection int scrollDirection) {
handleDirection(child, scrollDirection);
}
@Override
protected boolean onNestedDirectionFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY, @ScrollDirection int scrollDirection) {
handleDirection(child, scrollDirection);
return true;
}
private void handleDirection(V child, @ScrollDirection int scrollDirection) {
if (!scrollingEnabled) return;
if (scrollDirection == ScrollDirection.SCROLL_DIRECTION_DOWN && hidden) {
hidden = false;
animateOffset(child, 0);
} else if (scrollDirection == ScrollDirection.SCROLL_DIRECTION_UP && !hidden) {
hidden = true;
animateOffset(child, child.getHeight());
}
}
フラグメントの可視性とアニメーションによる非表示:
recyclerView.addOnScrollListener(new HideShowScrollListener() {
final Fragment parentFragment = getParentFragment();
@Override
public void onHide() {
bottomLayout.animate().setDuration(200).translationYBy(-bottomLayout.getHeight()).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
bottomLayout.setVisibility(View.GONE);
}
});
}
@Override
public void onShow() {
bottomLayout.animate().setDuration(200).translationY(0).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
bottomLayout.setVisibility(View.VISIBLE);
}
});
}
@Override
public void onScrolled() {
// To load more data
}
});
HideShowScrollListener.Java
public abstract class HideShowScrollListener extends RecyclerView.OnScrollListener {
private static final int HIDE_THRESHOLD = 20;
private int scrolledDistance = 0;
private boolean controlsVisible = true;
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
onScrolled();
if (scrolledDistance > HIDE_THRESHOLD && controlsVisible) {
onHide();
controlsVisible = false;
scrolledDistance = 0;
} else if (scrolledDistance < -HIDE_THRESHOLD && !controlsVisible) {
onShow();
controlsVisible = true;
scrolledDistance = 0;
}
if((controlsVisible && dy>0) || (!controlsVisible && dy<0)) {
scrolledDistance += dy;
}
}
public abstract void onHide();
public abstract void onShow();
public abstract void onScrolled();
}
@ k0shは良い解決策を与えました。レイアウトを表示したり非表示にしたりして、アニメーションをスムーズにするために更新したいと思います。 onNestedPreScroll()内の完全なコードを以下のコードで置き換えます。
if (dy > 0) {
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) child.getLayoutParams();
int viewBottomMargin = layoutParams.bottomMargin;
child.animate().translationY(child.getHeight() + viewBottomMargin).setInterpolator(new LinearInterpolator()).start();
} else if (dy < 0) {
child.animate().translationY(0).setInterpolator(new LinearInterpolator()).start();
}