私は、崩壊ツールバー機能を使用するためにCoordinatorLayout
、AppBarLayout
、およびCollapsingToolbarLayout
を使用している1つのAndroidアプリに取り組んでいます。
レイアウトでNestedScrollView
を使用して、同じレイアウトでAppBarLayout
を展開および折りたたみます。画面の中央から上にスクロールしようとすると機能しませんが、画面の右隅から画面を上にスクロールしようとするとスムーズにスクロールします。
以下は私のXMLファイルです
layout.xml
<Android.support.v4.widget.NestedScrollView xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:fillViewport="true"
Android:fitsSystemWindows="true"
Android:paddingBottom="2dp"
Android:paddingLeft="5dp"
Android:paddingRight="5dp"
Android:paddingTop="5dp"
Android:layout_gravity="fill_vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<RelativeLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@color/fragment_back_color"
Android:orientation="vertical">
<LinearLayout
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:orientation="horizontal"
Android:padding="5dp">
<ImageView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:background="@drawable/new_recharge" />
<com.spiceladdoo.views.RobotTextviewRegular
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:layout_marginLeft="10dp"
Android:text="NEW PAYMENT"
Android:textColor="@color/offer_name_text_color" />
</LinearLayout>
<RelativeLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_marginLeft="5dp"
Android:layout_marginRight="5dp"
Android:background="@color/white"
Android:paddingBottom="20dp"
Android:paddingLeft="10dp"
Android:paddingRight="10dp"
Android:paddingTop="20dp">
<HorizontalScrollView
Android:id="@+id/hsv"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:layout_alignParentTop="true"
Android:fillViewport="true"
Android:measureAllChildren="false"
Android:scrollbars="none">
<LinearLayout
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_centerInParent="true"
Android:orientation="horizontal">
<LinearLayout
Android:id="@+id/wallet_layout"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:gravity="center"
Android:orientation="vertical">
<ImageView
Android:id="@+id/wallet_recharge"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:background="@drawable/wallet_recherge" />
<com.spiceladdoo.views.RobotTextviewRegular
Android:layout_width="65dp"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:layout_marginTop="5dp"
Android:gravity="center"
Android:text="WALLET"
Android:textColor="@color/offer_name_text_color"
Android:textSize="12sp" />
>
</LinearLayout>
<View
Android:layout_width="5dp"
Android:layout_height="20dp"
Android:background="@color/white" />
<LinearLayout
Android:id="@+id/prepaid_layout"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:gravity="center"
Android:orientation="vertical">
<ImageView
Android:id="@+id/prepaid_recharge"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:background="@drawable/prepaid_recherge" />
<com.spiceladdoo.views.RobotTextviewRegular
Android:layout_width="65dp"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:layout_marginTop="5dp"
Android:gravity="center"
Android:text="PREPAID"
Android:textColor="@color/offer_name_text_color"
Android:textSize="12sp" />
>
</LinearLayout>
<View
Android:layout_width="5dp"
Android:layout_height="20dp"
Android:background="@color/white" />
<LinearLayout
Android:id="@+id/postpaid_layout"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:gravity="center"
Android:orientation="vertical">
<ImageView
Android:id="@+id/postpaid_recharge"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:background="@drawable/postpaid_recherge" />
<com.spiceladdoo.views.RobotTextviewRegular
Android:layout_width="65dp"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:layout_marginTop="5dp"
Android:gravity="center"
Android:text="POSTPAID"
Android:textColor="@color/offer_name_text_color"
Android:textSize="12sp" />
>
</LinearLayout>
<View
Android:layout_width="5dp"
Android:layout_height="20dp"
Android:background="@color/white" />
<LinearLayout
Android:id="@+id/dth_layout"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:gravity="center"
Android:orientation="vertical">
<ImageView
Android:id="@+id/dth_recharge"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:background="@drawable/dth_recherge" />
<com.spiceladdoo.views.RobotTextviewRegular
Android:layout_width="65dp"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:layout_marginTop="5dp"
Android:gravity="center"
Android:text="DTH"
Android:textColor="@color/offer_name_text_color"
Android:textSize="12sp" />
>
</LinearLayout>
<View
Android:layout_width="5dp"
Android:layout_height="20dp"
Android:background="@color/white" />
<LinearLayout
Android:id="@+id/landline_layout"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:gravity="center"
Android:orientation="vertical">
<ImageView
Android:id="@+id/landline_recharge"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:background="@drawable/landline_recherge" />
<com.spiceladdoo.views.RobotTextviewRegular
Android:layout_width="65dp"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:layout_marginTop="5dp"
Android:gravity="center"
Android:text="LANDLINE"
Android:textColor="@color/offer_name_text_color"
Android:textSize="12sp" />
>
</LinearLayout>
<View
Android:layout_width="5dp"
Android:layout_height="20dp"
Android:background="@color/white" />
<LinearLayout
Android:id="@+id/datacard_layout"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:gravity="center"
Android:orientation="vertical">
<ImageView
Android:id="@+id/datacard_recharge"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:background="@drawable/datacard_recherge" />
<com.spiceladdoo.views.RobotTextviewRegular
Android:layout_width="65dp"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:layout_marginTop="5dp"
Android:gravity="center"
Android:text="DATACARD"
Android:textColor="@color/offer_name_text_color"
Android:textSize="12sp" />
>
</LinearLayout>
</LinearLayout>
</HorizontalScrollView>
</RelativeLayout>
<LinearLayout
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:orientation="horizontal"
Android:paddingBottom="10dp"
Android:paddingLeft="5dp"
Android:paddingRight="5dp"
Android:paddingTop="10dp">
<ImageView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:background="@drawable/recent" />
<com.spiceladdoo.views.RobotTextviewRegular
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:layout_marginLeft="10dp"
Android:text="RECENT"
Android:textColor="@color/offer_name_text_color" />
</LinearLayout>
<ListView
Android:id="@+id/recent_recharge_list"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_marginLeft="5dp"
Android:layout_marginRight="5dp">
</ListView>
</LinearLayout>
<FrameLayout xmlns:tools="http://schemas.Android.com/tools"
Android:id="@+id/recharge_container"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:visibility="visible"
tools:ignore="MergeRootFrame">
</FrameLayout>
</RelativeLayout>
</Android.support.v4.widget.NestedScrollView>
望ましい結果は、画面の中央から上にスクロールしようとすると、モバイルの右隅から上にスクロールするのと同じように機能するはずです。
問題をより明確に見るには、以下のビデオをご覧ください
https://www.dropbox.com/s/gscfc8vfc7kkpxp/device-2015-12-30-160119.mp4?dl=
私はそれを打ち込んだと信じています:
ソースコードを見つけることができますhere -試してみてください。
例として取り上げました google\designlibdemo 。
Activity
は次のようになります。
<?xml version="1.0" encoding="utf-8"?>
<Android.support.v4.widget.DrawerLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:id="@+id/drawer_layout"
Android:layout_height="match_parent"
Android:layout_width="match_parent"
Android:fitsSystemWindows="true">
<include layout="@layout/include_list_viewpager"/>
<Android.support.design.widget.NavigationView
Android:id="@+id/nav_view"
Android:layout_height="match_parent"
Android:layout_width="wrap_content"
Android:layout_gravity="start"
Android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header"
app:menu="@menu/drawer_view"/>
</Android.support.v4.widget.DrawerLayout>
ホストViewPager
:include_list_viewpager.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.support.design.widget.AppBarLayout
Android:id="@+id/appbar"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
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"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginStart="48dp"
app:expandedTitleMarginEnd="64dp"
Android:fitsSystemWindows="true">
<ImageView
Android:id="@+id/image"
Android:src="@drawable/header_image"
Android:layout_width="match_parent"
Android:layout_height="200dp"
Android:scaleType="centerCrop"
Android:fitsSystemWindows="true"
app:layout_collapseMode="parallax"/>
<View
Android:background="#AA50AA00"
Android:layout_width="match_parent"
Android:layout_height="200dp"
app:layout_collapseMode="parallax"/>
<Android.support.v7.widget.Toolbar
Android:id="@+id/toolbar"
Android:layout_width="match_parent"
Android:title=""
Android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin" />
</Android.support.design.widget.CollapsingToolbarLayout>
<Android.support.design.widget.TabLayout
Android:id="@+id/tabs"
Android:background="#50AA00"
app:tabMode="scrollable"
app:tabIndicatorColor="#FFF"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content" />
</Android.support.design.widget.AppBarLayout>
<Android.support.v4.view.ViewPager
Android:id="@+id/viewpager"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</Android.support.design.widget.CoordinatorLayout>
CollapsingToolbarLayout
ホストToolbar
(app:layout_collapseMode="pin"
)以上ImageView
(app:layout_collapseMode="parallax"
)。
ViewPagerフラグメントでホストされるのは、次のレイアウトです。
<?xml version="1.0" encoding="utf-8"?>
<Android.support.v4.widget.NestedScrollView
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:fillViewport="true"
Android:fitsSystemWindows="true"
Android:layout_gravity="fill_vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
Android:orientation="vertical"
Android:background="#DDD"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="horizontal"
Android:padding="16dp">
<ImageView
Android:src="@drawable/mobile"
Android:layout_marginTop="2dp"
Android:layout_width="16dp"
Android:layout_height="16dp" />
<TextView
Android:text="@string/prepaid_recharge"
Android:layout_marginStart="16dp"
Android:layout_gravity="center_vertical"
Android:textColor="#000"
Android:fontFamily="sans-serif-medium"
Android:textSize="14sp"
Android:textAllCaps="true"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content" />
</LinearLayout>
........
<ListView
Android:id="@+id/recent_recharge_list"
Android:layout_width="match_parent"
Android:layout_height="match_parent"/>
</LinearLayout>
</Android.support.v4.widget.NestedScrollView>
したがって、この動作がありますapp:layout_behavior="@string/appbar_scrolling_view_behavior"
およびViewPort
(Android:fillViewport="true"
)
そして、実際に必要なのはそれだけです。 Fragment
クラスは非常に標準的です:
public class RechargeFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.recharge_fragment, container, false);
}
}
Activity
も非常に標準のままです。
繰り返しますが、私のコード例 here を見つけることができます。
NB!エミュレーターでの動作が非常に悪い(まったくスムーズではない)ことがわかりました。
役に立てば幸いです。
試してくださいAndroid:clickable="true"
以下のようなNestedScrollView
の子ビューで:
<Android.support.v4.widget.NestedScrollView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical"
Android:clickable="true">
</LinearLayout>
</Android.support.v4.widget.NestedScrollView>
this の複製のように見えます。 「解決済み」スレッドを指しますが、もう1つはRecyclerViewに関連しています。
私は、RecyclerViewスレッドの Manolo Garcia および Kirill Boyarshinov によって作成されたソリューションに基づいて動作を記述しました。私の場合、onNestedFling()
はフリングジェスチャの作成時に呼び出されなかったため、onNestedPreScroll()
をハッキングしました。私は今日、NestedScrollを使用してViewPager内で作業していますが、別のシナリオで以下のソリューションをテストしていません(1年前にRecyclerViewのために書いた同様のコードに基づいています)。
最初に更新された動作(xmlで_app:layout_behavior="your.package.FlingBehavior">
_を_Android.support.design.widget.AppBarLayout
_として追加):
_public final class FlingBehavior extends AppBarLayout.Behavior {
private static final String TAG = FlingBehavior.class.getName();
private static final int TOP_CHILD_FLING_THRESHOLD = 1;
private static final float OPTIMAL_FLING_VELOCITY = 3500;
private static final float MIN_FLING_VELOCITY = 20;
boolean shouldFling = false;
float flingVelocityY = 0;
public FlingBehavior() {
}
public FlingBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target,
int velocityX, int velocityY, int[] consumed) {
super.onNestedPreScroll(coordinatorLayout, child, target, velocityX, velocityY, consumed);
if (velocityY > MIN_FLING_VELOCITY) {
shouldFling = true;
flingVelocityY = velocityY;
} else {
shouldFling = false;
}
}
@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout abl, View target) {
super.onStopNestedScroll(coordinatorLayout, abl, target);
if (shouldFling) {
Log.d(TAG, "onNestedPreScroll: running nested fling, velocityY is " + flingVelocityY);
onNestedFling(coordinatorLayout, abl, target, 0, flingVelocityY, true);
}
}
@Override
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target,
float velocityX, float velocityY, boolean consumed) {
if (target instanceof RecyclerView && velocityY < 0) {
Log.d(TAG, "onNestedFling: target is recyclerView");
final RecyclerView recyclerView = (RecyclerView) target;
final View firstChild = recyclerView.getChildAt(0);
final int childAdapterPosition = recyclerView.getChildAdapterPosition(firstChild);
consumed = childAdapterPosition > TOP_CHILD_FLING_THRESHOLD;
}
// prevent fling flickering when going up
if (target instanceof NestedScrollView && velocityY > 0) {
consumed = true;
}
if (Math.abs(velocityY) < OPTIMAL_FLING_VELOCITY) {
velocityY = OPTIMAL_FLING_VELOCITY * (velocityY < 0 ? -1 : 1);
}
Log.d(TAG, "onNestedFling: velocityY - " + velocityY + ", consumed - " + consumed);
return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
}
}
_
これでスムーズにスクロールするはずですが、NestedScrollView(およびRecyclerView)のコンテンツはAppBarLayoutが折りたたまれる前にスクロールできるため、見た目が悪くなります。それを解決するには この回答に従ってください 。 fullScroll(ScrollView.FOCUS_UP)
の代わりにscrollTo(0, 0)
メソッドを使用するように少し変更してください。そうしないと、高速スクロール中に小さなちらつきに気付く場合があります。
_AppBarLayout appBarLayout = findViewById(...);
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
shouldScroll = Math.abs(verticalOffset) == appBarLayout.getTotalScrollRange();
}
});
NestedScrollView nestedScrollView = findViewById(...);
nestedScrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
@Override
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
if (!shouldScroll)
nestedScrollView.fullScroll(ScrollView.FOCUS_UP);
}
});
_
その後、私はそれを終了と呼びましたが、Google Playのようにさらにスムーズにスクロールするためにさらに進めたいかもしれません、それについての(未解決だと思う)スレッドがあります here 。
CoordinatorLayout
、AppbarLayout
、およびCollapsingToolbarLayout
を子ビューとして持つNestedScrollView
を操作するとき、私はほとんど同じような問題を抱えていました。
次のコードは、プロジェクトのワークスペースから直接作業したものです。
<?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.support.design.widget.AppBarLayout
Android:id="@+id/appBar"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
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="wrap_content"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
Android:id="@+id/cover_pic"
Android:layout_width="match_parent"
Android:layout_height="256dp"
Android:scaleType="centerCrop"
app:layout_collapseMode="parallax"
Android:src="@drawable/cookin"/>
<Android.support.v7.widget.Toolbar
Android:id="@+id/mToolbar"
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.TabLayout
Android:id="@+id/tabLayout"
Android:layout_width="match_parent"
Android:layout_height="?attr/actionBarSize"
Android:layout_gravity="bottom"
Android:background="?attr/colorPrimary"
app:tabMode="scrollable"/>
</Android.support.design.widget.AppBarLayout>
<Android.support.v4.widget.NestedScrollView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<Android.support.v4.view.ViewPager
Android:id="@+id/tab_viewpager"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</Android.support.v4.widget.NestedScrollView>
<RelativeLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<LinearLayout
Android:layout_alignParentBottom="true"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical">
<Android.support.design.widget.FloatingActionButton
Android:id="@+id/fab_phone"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="bottom|end"
Android:layout_marginRight="@dimen/fab_margin"
Android:visibility="invisible"
app:backgroundTint="@color/colorFAB2"
app:elevation="6dp"
Android:layout_margin="5dp"
app:pressedTranslationZ="12dp"
Android:src="@drawable/ic_phone_white_24dp" />
<Android.support.design.widget.FloatingActionButton
Android:id="@+id/fab_book"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="bottom|end"
Android:layout_margin="5dp"
Android:layout_marginRight="@dimen/fab_margin"
Android:visibility="invisible"
app:elevation="6dp"
app:backgroundTint="@color/colorFAB1"
app:pressedTranslationZ="12dp"
Android:src="@drawable/ic_receipt_white_24dp" />
<Android.support.design.widget.FloatingActionButton
Android:id="@+id/fab_add"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="bottom|end"
app:elevation="6dp"
app:backgroundTint="@color/colorAccent"
app:pressedTranslationZ="12dp"
Android:layout_margin="@dimen/fab_margin"
Android:src="@drawable/ic_add_white_24dp" />
</LinearLayout>
</RelativeLayout>
</Android.support.design.widget.CoordinatorLayout>