是否可以触摸 CollapsingToolbarLayout 中的 ImageView 并滚动它?
Is it possible to touch the ImageView inside CollapsingToolbarLayout and scroll it?
我正在尝试获得全屏 CollapsingToolbar
但是当我将 match_parent
设置为 AppBarLayout
的高度时,我无法滚动 ImageView
在 CollapsingToolbarLayout
内。我必须留下一些 space 以便我可以触摸 activity 的 "white" (在 AppBarLayout 中我添加了 android:layout-marginBottom:"16dp " ) 只有这样,在我触摸它之后,我才能滚动 ImageView,否则我不能。
每次我 运行 应用程序并第一次触摸布局时都会发生这种情况。所以我必须先触摸白色,然后滚动图像。
你能帮帮我吗?
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/drawer">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="16dp"
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|exitUntilCollapsed"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginStart="48dp"
app:expandedTitleMarginEnd="64dp">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:fitsSystemWindows="true"
app:layout_collapseMode="parallax"
android:contentDescription="@null"
android:src="@drawable/background" />
<android.support.v7.widget.Toolbar
android:layout_height="?attr/actionBarSize"
android:layout_width="match_parent"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin"
app:theme="@style/ToolbarTheme"
android:id="@+id/toolbar"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
</FrameLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
<com.myapplication.ScrimInsetsFrameLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="304dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:insetForeground="#4000"
android:clickable="true"
android:background="#ffffff">
...
</com.myapplication.ScrimInsetsFrameLayout>
</android.support.v4.widget.DrawerLayout>
编辑 @PPartisan 我已经按照你说的做了,但这是我得到的:
尝试添加一个小边距,这样下面的白色 space 几乎看不见(您可能还想将白色更改为强调色,这样 space 就不会可见)
另一种方法是通过获取屏幕高度来动态设置应用栏布局的高度。
编辑:
这可能是一个焦点问题,尝试在您的主要内容中添加虚拟布局,它将自动聚焦
<LinearLayout
android:layout_width="0px"
android:layout_height="0px"
android:focusable="true"
android:focusableInTouchMode="true" />
甚至只是将这些属性添加到您的内容布局中
android:focusable="true"
android:focusableInTouchMode="true"
这不是一个很好的解决方案,但它确实适用于我的测试设备。它通过显式地将触摸侦听器分配给触发嵌套滚动的 AppBar 来启动滚动过程。
首先,创建一个扩展 NestedScrollView
的自定义 class 并添加以下方法,使其看起来像这样:
public class CustomNestedScrollView extends NestedScrollView {
private int y;
public CustomNestedScrollView(Context context) {
super(context);
}
public CustomNestedScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public boolean dispatchHandlerScroll(MotionEvent e) {
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
y = (int) e.getY();
startNestedScroll(2);
break;
case MotionEvent.ACTION_MOVE:
int dY = y - ((int)e.getY());
dispatchNestedPreScroll(0, dY, null, null);
dispatchNestedScroll(0, 0, 0, dY, null);
break;
case MotionEvent.ACTION_UP:
stopNestedScroll();
break;
}
return true;
}
}
然后,在您的 Activity
class 中,将 TouchListener
分配给您的 AppBarLayout
:
appBarLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return customNestedScrollView.dispatchHandlerScroll(event);
}
});
并在 AppBar 第一次完全折叠时将其删除:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (Math.abs(appBarLayout.getY()) == appBarLayout.getTotalScrollRange()) {
appBarLayout.setOnTouchListener(null);
}
return super.dispatchTouchEvent(ev);
}
编辑
按照以下步骤把它弄起来运行:
将 xml
(android.support.v4.widget.NestedScrollView
) 中的 NestedScrollView
替换为 CustomNestedScrollView
(将采用 com.something.somethingelse.CustomNestedScrollView
的形式,取决于它在项目中的位置)。
将其分配给您的 Activity
onCreate()
(即 CustomScrollView customScrollView = (CustomScrollView) findViewById(R.id.custom_scroll_view_id);
)
中的变量
在您的 appBarLayout
上设置 TouchListener
,就像您在编辑中所做的那样。现在,当您调用 dispatchHandlerScroll()
时,它将在您的 customNestedScrollView
实例上。
dispatchTouchEvent()
是您在 Activity
class 中覆盖的方法,因此它应该在 TouchListener
[ 之外=64=]
因此,例如:
public class MainActivity extends AppCompatActivity {
private AppBarLayout appBarLayout;
private CustomNestedScrollView customNestedScrollView;
//...
@Override
protected void onCreate(Bundle savedInstanceState) {
//...
customNestedScrollView = (CustomNestedScrollView) findViewById(R.id.scroll);
appBarLayout = (AppBarLayout) findViewById(R.id.app_bar_layout);
appBarLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return customNestedScrollView.dispatchHandlerScroll(event);
}
});
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (Math.abs(appBarLayout.getY()) == appBarLayout.getTotalScrollRange()) {
appBarLayout.setOnTouchListener(null);
}
return super.dispatchTouchEvent(ev);
}
}
希望事情已经解决了。
我正在尝试获得全屏 CollapsingToolbar
但是当我将 match_parent
设置为 AppBarLayout
的高度时,我无法滚动 ImageView
在 CollapsingToolbarLayout
内。我必须留下一些 space 以便我可以触摸 activity 的 "white" (在 AppBarLayout 中我添加了 android:layout-marginBottom:"16dp " ) 只有这样,在我触摸它之后,我才能滚动 ImageView,否则我不能。
每次我 运行 应用程序并第一次触摸布局时都会发生这种情况。所以我必须先触摸白色,然后滚动图像。
你能帮帮我吗?
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/drawer">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="16dp"
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|exitUntilCollapsed"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginStart="48dp"
app:expandedTitleMarginEnd="64dp">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:fitsSystemWindows="true"
app:layout_collapseMode="parallax"
android:contentDescription="@null"
android:src="@drawable/background" />
<android.support.v7.widget.Toolbar
android:layout_height="?attr/actionBarSize"
android:layout_width="match_parent"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin"
app:theme="@style/ToolbarTheme"
android:id="@+id/toolbar"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
</FrameLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
<com.myapplication.ScrimInsetsFrameLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="304dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:insetForeground="#4000"
android:clickable="true"
android:background="#ffffff">
...
</com.myapplication.ScrimInsetsFrameLayout>
</android.support.v4.widget.DrawerLayout>
编辑 @PPartisan 我已经按照你说的做了,但这是我得到的:
尝试添加一个小边距,这样下面的白色 space 几乎看不见(您可能还想将白色更改为强调色,这样 space 就不会可见)
另一种方法是通过获取屏幕高度来动态设置应用栏布局的高度。
编辑: 这可能是一个焦点问题,尝试在您的主要内容中添加虚拟布局,它将自动聚焦
<LinearLayout
android:layout_width="0px"
android:layout_height="0px"
android:focusable="true"
android:focusableInTouchMode="true" />
甚至只是将这些属性添加到您的内容布局中
android:focusable="true"
android:focusableInTouchMode="true"
这不是一个很好的解决方案,但它确实适用于我的测试设备。它通过显式地将触摸侦听器分配给触发嵌套滚动的 AppBar 来启动滚动过程。
首先,创建一个扩展 NestedScrollView
的自定义 class 并添加以下方法,使其看起来像这样:
public class CustomNestedScrollView extends NestedScrollView {
private int y;
public CustomNestedScrollView(Context context) {
super(context);
}
public CustomNestedScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public boolean dispatchHandlerScroll(MotionEvent e) {
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
y = (int) e.getY();
startNestedScroll(2);
break;
case MotionEvent.ACTION_MOVE:
int dY = y - ((int)e.getY());
dispatchNestedPreScroll(0, dY, null, null);
dispatchNestedScroll(0, 0, 0, dY, null);
break;
case MotionEvent.ACTION_UP:
stopNestedScroll();
break;
}
return true;
}
}
然后,在您的 Activity
class 中,将 TouchListener
分配给您的 AppBarLayout
:
appBarLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return customNestedScrollView.dispatchHandlerScroll(event);
}
});
并在 AppBar 第一次完全折叠时将其删除:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (Math.abs(appBarLayout.getY()) == appBarLayout.getTotalScrollRange()) {
appBarLayout.setOnTouchListener(null);
}
return super.dispatchTouchEvent(ev);
}
编辑
按照以下步骤把它弄起来运行:
将
xml
(android.support.v4.widget.NestedScrollView
) 中的NestedScrollView
替换为CustomNestedScrollView
(将采用com.something.somethingelse.CustomNestedScrollView
的形式,取决于它在项目中的位置)。将其分配给您的
Activity
onCreate()
(即CustomScrollView customScrollView = (CustomScrollView) findViewById(R.id.custom_scroll_view_id);
) 中的变量
在您的
appBarLayout
上设置TouchListener
,就像您在编辑中所做的那样。现在,当您调用dispatchHandlerScroll()
时,它将在您的customNestedScrollView
实例上。
[ 之外=64=]dispatchTouchEvent()
是您在Activity
class 中覆盖的方法,因此它应该在TouchListener
因此,例如:
public class MainActivity extends AppCompatActivity {
private AppBarLayout appBarLayout;
private CustomNestedScrollView customNestedScrollView;
//...
@Override
protected void onCreate(Bundle savedInstanceState) {
//...
customNestedScrollView = (CustomNestedScrollView) findViewById(R.id.scroll);
appBarLayout = (AppBarLayout) findViewById(R.id.app_bar_layout);
appBarLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return customNestedScrollView.dispatchHandlerScroll(event);
}
});
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (Math.abs(appBarLayout.getY()) == appBarLayout.getTotalScrollRange()) {
appBarLayout.setOnTouchListener(null);
}
return super.dispatchTouchEvent(ev);
}
}
希望事情已经解决了。