I have one of the new MapFragments in a ScrollView. Actually it's a SupportMapFragment, but anyway. It works, but there are two problems:
When scrolled, it leaves a black mask behind. The black covers exactly the area where the map was, except for a hole where the +/- zoom buttons were. See screenshot below. This is on Android 4.0.
The view doesn't use requestDisallowInterceptTouchEvent() when the user interacts with the map to prevent the ScrollView intercepting touches, so if you try to pan vertically in the map, it just scrolls the containing ScrollView. I could theoretically derive a view class MapView and add that functionality, but how can I get MapFragment to use my customised MapView instead of the standard one?
Applying a transparent image over the mapview fragment seems to resolve the issue. It's not the prettiest, but it seems to work. Here's an XML snippet that shows this:
<RelativeLayout
android:id="#+id/relativeLayout1"
android:layout_width="match_parent"
android:layout_height="300dp" >
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<ImageView
android:id="#+id/imageView123"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/temp_transparent" />
</RelativeLayout>
For me adding a transparent ImageView did not help remove the black mask completely. The top and bottom parts of map still showed the black mask while scrolling.
So the solution for it, I found in this answer with a small change.
I added,
android:layout_marginTop="-100dp"
android:layout_marginBottom="-100dp"
to my map fragment since it was vertical scrollview. So my layout now looked this way:
<RelativeLayout
android:id="#+id/map_layout"
android:layout_width="match_parent"
android:layout_height="300dp">
<fragment
android:id="#+id/mapview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="-100dp"
android:layout_marginBottom="-100dp"
android:name="com.google.android.gms.maps.MapFragment"/>
<ImageView
android:id="#+id/transparent_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#color/transparent" />
</RelativeLayout>
To solve the second part of the question I set requestDisallowInterceptTouchEvent(true) for my main ScrollView. When the user touched the transparent image and moved I disabled the touch on the transparent image for MotionEvent.ACTION_DOWN and MotionEvent.ACTION_MOVE so that map fragment can take Touch Events.
ScrollView mainScrollView = (ScrollView) findViewById(R.id.main_scrollview);
ImageView transparentImageView = (ImageView) findViewById(R.id.transparent_image);
transparentImageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// Disallow ScrollView to intercept touch events.
mainScrollView.requestDisallowInterceptTouchEvent(true);
// Disable touch on transparent view
return false;
case MotionEvent.ACTION_UP:
// Allow ScrollView to intercept touch events.
mainScrollView.requestDisallowInterceptTouchEvent(false);
return true;
case MotionEvent.ACTION_MOVE:
mainScrollView.requestDisallowInterceptTouchEvent(true);
return false;
default:
return true;
}
}
});
This worked for me. Hope it helps you..
This probably has its roots in the same place at causes the problem in this question. The solution there is to use a transparent frame, which is a little lighter weight than a transparent image.
Done after lots of R&D:
fragment_one.xml should looks like:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/scrollViewParent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="400dip" >
<com.google.android.gms.maps.MapView
android:id="#+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<View
android:id="#+id/customView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#android:color/transparent" />
</RelativeLayout>
<!-- Your other elements are here -->
</LinearLayout>
</ScrollView>
Your Java class of FragmentOne.java looks like:
private GoogleMap mMap;
private MapView mapView;
private UiSettings mUiSettings;
private View customView
onCreateView
mapView = (MapView) rootView.findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
if (mapView != null) {
mMap = mapView.getMap();
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
mUiSettings = mMap.getUiSettings();
mMap.setMyLocationEnabled(true);
mUiSettings.setCompassEnabled(true);
mUiSettings.setMyLocationButtonEnabled(false);
}
scrollViewParent = (ScrollView)rootView.findViewById(R.id.scrollViewParent);
customView = (View)rootView.findViewById(R.id.customView);
customView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// Disallow ScrollView to intercept touch events.
scrollViewParent.requestDisallowInterceptTouchEvent(true);
// Disable touch on transparent view
return false;
case MotionEvent.ACTION_UP:
// Allow ScrollView to intercept touch events.
scrollViewParent.requestDisallowInterceptTouchEvent(false);
return true;
case MotionEvent.ACTION_MOVE:
scrollViewParent.requestDisallowInterceptTouchEvent(true);
return false;
default:
return true;
}
}
});
I used this structures and I overcame the problem.
I used a container view for maps fragment.
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:text="Another elements in scroll view1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.erolsoftware.views.MyMapFragmentContainer
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="250dp">
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/eventMap"
tools:context="com.erolsoftware.eventapp.EventDetails"
android:name="com.google.android.gms.maps.SupportMapFragment"/>
</com.erolsoftware.views.MyMapFragmentContainer>
<TextView
android:text="Another elements in scroll view2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>
The container class:
public class MyMapFragmentContainer extends LinearLayout {
#Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN)
{
ViewParent p = getParent();
if (p != null)
p.requestDisallowInterceptTouchEvent(true);
}
return false;
}
public MyMapFragmentContainer(Context context) {
super(context);
}
public MyMapFragmentContainer(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyMapFragmentContainer(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
No need to struggle with customScrollViews and transparent layout files. simply use lighter version of google map and your issue will be resolved.
map:liteMode="true"
add above property inside map fragment in your layout file. and issue will be fixed.
For the second part of the question - you can derive a fragment class from SupportMapFragment, and use that in your layout instead. You can then override Fragment#onCreateView, and instantiate your custom MapView there.
If that does not work, you can always create your own fragment - then you just need to take care of calling all the lifecycle methods yourself (onCreate, onResume, etc). This answer has some more details.
<ScrollView
android:layout_width="match_parent"
::
::
::
<FrameLayout
android:id="#+id/map_add_business_one_rl"
android:layout_width="match_parent"
android:layout_height="100dp"
>
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="-100dp"
android:layout_marginBottom="-100dp"
/>
</FrameLayout>
::
::
::
</ScrollView>
Related
I have a viewpager with left and right padding for showing the previews of left and right pages of viewpager.
viewPager.setPadding(30,0,30,0);
The content of the viewpager is a zoomlayout borrowed from here.
So the issue is, whenever I zoom the layout from the viewpager, the only visible zoom is at top and bottom. Zooming is not visible to the left and right due to padding.
Screenshot before zooming
Screenshot after zooming
The zoomed view is limited inside the viewpager padding. I need the view to zoom fullscreen without any padding or boundaries.
These are the code snippets I was trying
activity_reader.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ViewPager
android:id="#+id/reader_pager"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#000"/>
</FrameLayout>
each_page.xml
<?xml version="1.0" encoding="utf-8"?>
<com.test.poc.widgets.ZoomLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/zoom_layout">
<RelativeLayout
android:id="#+id/img_holder"
android:transitionName="pager"
android:background="#FFF"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical">
<ImageView
android:id="#+id/page_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:srcCompat="#drawable/a_four"
android:layout_weight="1"
android:scaleType="fitXY"
/>
</RelativeLayout>
</com.test.poc.widgets.ZoomLayout>
After zooming the view, when I release the finger, the view should move smoothly to a fullscreen viewpager.
Tried setting clipToPadding as false, but still one side of padding still exist while zooming
Did you try putting zoomview beside viewpager in framelayout (not in each page) so it is on top of viewpager.
Try this, it's worked for me using this :https://gist.github.com/atermenji/3781644
public class ImageZoomViewPager extends ViewPager {
public ImageZoomViewPager(Context context) {
super(context);
}
public ImageZoomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
if (v instanceof ImageViewTouch) {
return ((ImageViewTouch) v).canScroll(dx);
} else {
return super.canScroll(v, checkV, dx, x, y);
}
}}
I have a view and I want to show it when I click on button/layout and hide it when I touch somewhere else. How can I do it?
I wrote some code in dispatchTouchEvent(Motion Event) and it's working. But, I think there must be another way to do it.
You can fill the outside of your RecyclerView with another clickable view and implement setOnTouchListener method for that view. Here's an example:
Let's say we have got RecyclerView at the top of our RelativeLayout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="300dp"
android:scrollbars="vertical" />
<!--View below is just to fill the remaining space. We will use this view to catch outside touch-->
<View
android:id="#+id/outside_detector"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/recyclerView"
android:clickable="true"
android:focusable="true"/>
</RelativeLayout>
And we want to hide and show our recyclerview when we click outside of RecyclerView:
((View) findViewById(R.id.outside_detector)).setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
if(arg1.getAction() == MotionEvent.ACTION_DOWN){
if(recyclerView.getVisibility() == View.VISIBLE){
recyclerView.setVisibility(View.INVISIBLE);
}else{
recyclerView.setVisibility(View.VISIBLE);
}
}
return true;
}
});
If you want to show recyclerview on button click, then just write recyclerView.setVisibility(View.VISIBLE) method inside button ClickListener!
Hope this helps!
I have a layout with custom ScrollView that can be switched off. There are some fragments loading into this ScrollView.
Today I added RecycleView to the new fragment and noticed a strange behaviour. When RecycleView has android:height="match_parent" it expands to full its height inside ScrollView.
Is there any way to disable this (I want RecycleView to scroll internally and to be screen_height size) ?
Main content xml (located inside CoordinatorLayout)
<xxx.SwitchableScrollView
android:id="#+id/main_scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:id="#+id/fragment_holder"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="ScrollViewSize"/>
</xxx.SwitchableScrollView>
Fragment layout:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/appeals_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="visible"/>
<LinearLayout
android:id="#+id/loading_progress"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<ProgressBar
android:layout_width="#dimen/big_progress_diameter"
android:layout_height="#dimen/big_progress_diameter"
android:indeterminate="true"
android:indeterminateDrawable="#drawable/custom_progress_bar_primary"/>
</LinearLayout>
</FrameLayout>
Extended ScrollView:
public class SwitchableScrollView extends ScrollView {
boolean allowScroll = true;
public boolean isAllowScroll() {
return allowScroll;
}
public void setAllowScroll(boolean allowScroll) {
this.allowScroll = allowScroll;
}
// .... constructors skipped
#Override
public boolean onTouchEvent(MotionEvent ev) {
return allowScroll && super.onTouchEvent(ev);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return allowScroll && super.onInterceptTouchEvent(ev);
}
}
RecycleView init:
listView = (NestedRecyclerView) v.findViewById(R.id.appeals_list);
listView.setHorizontalScrollBarEnabled(false);
listView.setVerticalScrollBarEnabled(true);
listView.setNestedScrollingEnabled(true);
adapter = new AppealListAdapter(appealList);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
listView.setLayoutManager(layoutManager);
listView.setAdapter(adapter);
new GetAppeals().execute();
I'm using support library 23.2.1 (also tried 23.2.0). ListView and GridView works good in another fragments.
Finally I found an answer. I spent 6 hours(!) to add this one line to code:
layoutManager.setAutoMeasureEnabled(false);
They should be crazy to enable such thing by default...
I have a RecyclerView inside a ViewPager that only occupies the bottom half of the screen, and what I want to do is have the entire screen scroll if the RecyclerViews received a vertical scroll event.
UI hierarchy in a nutshell:
CoordinatorLayout
--- AppBarLayout
--- Toolbar
--- Bunch of static LinearLayouts, occupy most of screen
--- TabLayout
--- ViewPager
--- Fragments with RecyclerView
What I have:
To my understanding, a RecyclerView is memory-efficient and tries to fit itself in whatever space is available in the screen. In my app, I have a ViewPager hosting multiple tabs, each of which have a RecyclerView to display different things.
Could you please give me some ideas of what I could do to make the whole screen scroll? I'm guessing the best shot is to add a CollapsingToolbarLayout with parallax to the static content in the middle of the screen. I even tried to do this, but the UI was completely broken. It's difficult since I only want the content in the middle of the screen to scroll out, not the toolbars on top. I didn't have much luck with a NestedScrollView either, apparently its compatibility with ViewPager and CoordinatorLayout is not straight-forward..
What I want:
Main Activity Layout:
<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.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
>
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar_contributor"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:focusableInTouchMode="true">
<android.support.v7.widget.SearchView
android:id="#+id/searchview_contributor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:icon="#drawable/ic_search_white_24dp"
app:defaultQueryHint="Bla bla"
app:iconifiedByDefault="false"/>
<ImageButton
android:layout_width="24dp"
android:layout_height="24dp"
android:background="#android:color/transparent"
android:src="#drawable/ic_person_outline_black_24dp"/>
</android.support.v7.widget.Toolbar>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:text="La Bla"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:text="Bla Bla"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
>
<!-- Bunch of stuff, but irrelevant -->
<android.support.design.widget.TabLayout
android:id="#+id/tablayout_profile"
android:layout_width="match_parent"
android:layout_height="40dp"/>
</LinearLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager_profile"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
The fragment inside the Viewpager:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview_photos"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
Thanks in advance!
Update: The responses I received here (for which I am thankful) came a bit too late. If anyone knows which is the correct answer, please let me know!
public class CustomRecyclerView extends RecyclerView {
public CustomRecyclerView(Context context) {
super(context);
}
public CustomRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
int lastEvent = -1;
boolean isLastEventIntercepted = false;
private float xDistance, yDistance, lastX, lastY;
#Override
public boolean onInterceptTouchEvent(MotionEvent e) {
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
xDistance = yDistance = 0f;
lastX = e.getX();
lastY = e.getY();
break;
case MotionEvent.ACTION_MOVE:
final float curX = e.getX();
final float curY = e.getY();
xDistance += Math.abs(curX - lastX);
yDistance += Math.abs(curY - lastY);
lastX = curX;
lastY = curY;
if (isLastEventIntercepted && lastEvent == MotionEvent.ACTION_MOVE) {
return false;
}
if (xDistance > yDistance) {
isLastEventIntercepted = true;
lastEvent = MotionEvent.ACTION_MOVE;
return false;
}
}
lastEvent = e.getAction();
isLastEventIntercepted = false;
return super.onInterceptTouchEvent(e);
}
}
Just change your recyclerview by this .
I've done something very similar to this with a CollapsingToolbarLayout.
The trick here is to have two toolbars, one at the top with the searchview and another that is the toolbar dedicated to the collapsing layout.
Your searchview toolbar will have app:collapseMode="pin".
Your button bar will have app:collapseMode="pin".
Your LinearLayout below the button bar will have the default collapse mode so it will scroll. You can even give it a parallax effect with app:collapseMode="parallax".
Your TabLayout will have app:collapseMode="pin" so it scrolls up under the button bar and pins there.
Your ViewPager should be outside the CollapsingToolbarLayout and have the attribute app:layout_behavior="#string/appbar_scrolling_view_behavior".
The CollapsingToolbarLayout will want to display a title. Just call setTitle(null) on the collapsing toolbar and set your real title on the searchview toolbar.
You can put your navigation and menus on either the searchview toolbar and the collapsing toolbar and they should work as expected.
I will post some XML later; I just wanted to get this answer started.
It looks like you simply miss the app:layout_scrollFlags attribute. You should add it both to the Toolbar and your linear header layouts. For example, you could use: app:layout_scrollFlags="scroll|enterAlways"
As I see, your ViewPager already has app:layout_behavior="#string/appbar_scrolling_view_behavior", sou it should work right after you specify the scrollFlags
I'm trying to get a fullscreen CollapsingToolbar but when I set match_parent to the height of AppBarLayout I'm not able to scroll the ImageView which is inside CollapsingToolbarLayout. I have to leave some space so that I can touch the "white" of the activity (in AppBarLayout I added android:layout-marginBottom:"16dp" ) and only then, after I touched it, I can scroll the ImageView otherwise I can't.
This happens everytime I run the app and touch the layout for the first time. So I have to touch the white first and then scroll the image.
Could you help me?
<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>
EDIT #PPartisan I've done what you said but here's what I got:
This isn't a nice solution, but it does work on my test device. It kick starts the scrolling process by explicitly assigning a touch listener to the AppBar that triggers a nested scroll.
First, create a custom class that extends NestedScrollView and add the following method so it look something like this:
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;
}
}
Then, inside your Activity class, assign a TouchListener to your AppBarLayout:
appBarLayout.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return customNestedScrollView.dispatchHandlerScroll(event);
}
});
and remove it when the AppBar collapses fully for the first time:
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (Math.abs(appBarLayout.getY()) == appBarLayout.getTotalScrollRange()) {
appBarLayout.setOnTouchListener(null);
}
return super.dispatchTouchEvent(ev);
}
Edit
Take the following steps to get it up and running:
Replace the NestedScrollView in your xml(android.support.v4.widget.NestedScrollView) with the CustomNestedScrollView (which will take the form of com.something.somethingelse.CustomNestedScrollView, depending on where it is in your project).
Assign it to a variable in your Activity onCreate()(i.e. CustomScrollView customScrollView = (CustomScrollView) findViewById(R.id.custom_scroll_view_id);)
Set up the TouchListener on your appBarLayout as you have done in your edit. Now when you call dispatchHandlerScroll(), it will be on your customNestedScrollView instance.
dispatchTouchEvent() is a method you override in your Activity class, so it should be outside the TouchListener
So, for example:
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);
}
}
Hope that's cleared things up.
Try to add a tiny margin so the white space below will be almost invisible (you might also want to change white to accent color so the space will not be visible)
Another approach is to set the height of app bar layout dynamically by getting the height of the screen.
EDIT:
This might be a focus problem, try to add dummy layout to your main content, that will be focused automatically
<LinearLayout
android:layout_width="0px"
android:layout_height="0px"
android:focusable="true"
android:focusableInTouchMode="true" />
or even just add these attributes to your content layout
android:focusable="true"
android:focusableInTouchMode="true"