Scroll a hidden view/layout from bottom - android

This is what I want to achieve :
I wanted to use AbsoluteLayout but it is deprecated.
So I made a RelativeLayout beneath the blue view in the image above, and then put everything inside a ScrollView, but the hidden view is still 'on' the blue view, and not below it. Also, the screen scrolls, but the hidden part is just cut , and instead I see the my app's default background..
Any ideas?
EDIT :
my current try :
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:fillViewport="true"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#drawable/imageView" />
<LinearLayout
android:id="#+id/centerHolder"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical" >
.....
.....
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="1000dp"
android:layout_below="#id/main_holder"
android:background="#color/black_color">
</RelativeLayout>
</RelativeLayout>
</ScrollView>

I am taking this from a project of mine which displays a RecyclerView where you can add data if you click on a row - because the click "opens" the bottom sheet.
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/rl_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.fragment.BlockFragment">
<include
android:id="#+id/ll_header"
layout="#layout/layout_header_names" />
<include
android:id="#+id/divider_header"
layout="#layout/layout_divider_horizontal"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="#+id/ll_header" />
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_block"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/divider_footer"
android:layout_below="#+id/divider_header" />
<include
android:id="#+id/divider_footer"
layout="#layout/layout_divider_horizontal"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#767676"
android:layout_above="#+id/ll_footer" />
<include
android:id="#+id/ll_footer"
layout="#layout/layout_footer_score"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
<!-- Here comes my bottom sheet.
It is wrapped inside a FrameLayout, because an include cannot
have a behaviour. The included layout is every layout you
can imagine - mine is a RelativeLayout with two EditTexts
for example. The layout_behaviour is the second important line. -->
<FrameLayout
android:id="#+id/container_bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#e3e3e3"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<include layout="#layout/layout_bottom_sheet"/>
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>
For the behaviour itself, you'll need to get the FrameLayout (the View with the app:layout_behavior="android.support.design.widget.BottomSheetBehavior").
private BottomSheetBehavior bottomSheetBehavior;
bottomSheetBehavior = BottomSheetBehavior.from((FrameLayout)findViewById(R.id.container_bottom_sheet);
//for the sheet to "peek":
bottomSheetBehavior.setPeekHeight(200);
//now you can set the states:
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
It is also possible to set a BottomSheetCallback() in which you can get all the state changes and also the slideOffset!
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
switch (newState) {
case BottomSheetBehavior.STATE_DRAGGING:
case BottomSheetBehavior.STATE_EXPANDED:
break;
case BottomSheetBehavior.STATE_COLLAPSED:
default:
}
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
}
});

I think you should just use LinearLayout to wrap the ImageView and other layouts.
Edited the answer based on comments.
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:fillViewport="true"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/centerHolder"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical" >
.....
.....
</LinearLayout>
<ImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#drawable/imageView"
android:layout_alignParentTop="true" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="1000dp"
android:layout_below="#+id/centerHolder"
android:background="#color/black_color">
</RelativeLayout>
</RelativeLayout>
</ScrollView>

Just replace your ScrollView with NestedScrollView
Example:
<android.support.v4.widget.NestedScrollView
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"
app:layout_behavior="#string/appbar_scrolling_view_behavior">

I realized you need something like this, just tested it out , just copy two files and see how it works.
import android.animation.ObjectAnimator;
import android.content.Context;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ScrollView;
public class MainActivity extends AppCompatActivity {
LinearLayout movableLL;
boolean mDragLockGained;
float initialTouchPoint;
// int cutoffElevation;
boolean inAnimation;
ScrollView scrollView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scrollView = (ScrollView) findViewById(R.id.scrollView);
movableLL = (LinearLayout) findViewById(R.id.mobileLL);
movableLL.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (inAnimation) return true;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mDragLockGained = true;
initialTouchPoint = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
performTranslation(event);
initialTouchPoint = event.getRawY();
break;
case MotionEvent.ACTION_UP:
mDragLockGained = false;
performSettlingAnimation();
break;
}
return true;
}
});
}
private void performTranslation(MotionEvent event) {
float newDelta = event.getRawY() - initialTouchPoint;
float currentY = movableLL.getTranslationY();
if (currentY + newDelta > 0) {
movableLL.setTranslationY(currentY + newDelta);
if (scrollView.getTranslationY() + newDelta < 0){
}
scrollView.setTranslationY(scrollView.getTranslationY() + newDelta);
} else {
movableLL.setTranslationY(currentY);
scrollView.setTranslationY(scrollView.getTranslationY());
}
}
final int SETTLE_ANIMATION_DURATION = 300;
private void performSettlingAnimation() {
ObjectAnimator animLl = ObjectAnimator.ofFloat(movableLL, "translationY",
movableLL.getTranslationY(), convertDpToPixels(this, 150));
inAnimation = true;
animLl.setDuration(SETTLE_ANIMATION_DURATION);
animLl.start();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
inAnimation = false;
}
}, SETTLE_ANIMATION_DURATION);//use animationListener here as a best practice and toggle values in
//on animation start and cancel/finish
ObjectAnimator animSv = ObjectAnimator.ofFloat(scrollView, "translationY", scrollView.getTranslationY()
, 0);
animSv.setDuration(SETTLE_ANIMATION_DURATION);
animSv.start();
}
public static int convertDpToPixels(Context context, int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics()
);
}
}
and the xml......
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:text="Hello There" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:text="Hello Again" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:text="WhatsUp" />
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:text="See ya" />
</LinearLayout>
</ScrollView>
<LinearLayout
android:id="#+id/mobileLL"
android:layout_width="match_parent"
android:layout_height="300dp"
android:translationY="150dp"
android:layout_gravity="bottom"
android:background="#android:color/white"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#99ff0000" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#990000ff" />
</LinearLayout>
Please let me know if I missed something.

For this purposes the best way is to use BottomSheet from Design Support Library from my point of view.
<?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">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="1000dp"
android:background="#android:color/white">
<!-- other layout -->
</RelativeLayout>
</RelativeLayout>
</ScrollView>
<FrameLayout
android:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:behavior_peekHeight="120dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<View
android:layout_width="match_parent"
android:layout_height="240dp"
android:background="#android:color/darker_gray" />
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>
It also possible to combine it with your own a CoordinatorLayout Behavior to change scroll position for your scroll view, if needed.

Related

incomprehensible behavior of attribute app:elevation

I wonder why such a strange behavior in the app attribute: elevation = "0dp" and how to solve the problem. I use the androidx library. The toolbar is transparent. Shadow remains. When I write an app: elevation = "0dp", the shadow disappears, but the toolbar buttons, including the "back" buttons, stop responding.
I tried to solve it in other ways: android: elevation = "0dp"
programmatically set getSupportActionBar (). setElevation (0); Does not help.
layout:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/back_gray">
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="200dp"/>
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/transparent"
android:theme="#style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="wrap_content"
android:layout_height="?attr/actionBarSize"
android:background="#color/transparent"
app:popupTheme="#style/AppTheme.PopupOverlay">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageButton
android:id="#+id/iv_like"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="#android:color/transparent"
android:src="#drawable/heart_outline"
android:visibility="visible"/>
<ImageButton
android:id="#+id/iv_shared"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="#android:color/transparent"
android:src="#drawable/shared"
android:visibility="visible" />
</LinearLayout>
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
.....>
<TextView
........./>
<TextView
........../>
</RelativeLayout>
</LinearLayout>
</ScrollView>
</FrameLayout>
fragment.java:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate( R.layout.fragment_data, container, false );
toolbar = (Toolbar) rootView.findViewById( R.id.toolbar );
MainActivity activity = (MainActivity) getActivity();
if ( activity != null ) {
activity.setSupportActionBar( toolbar );
// activity.getSupportActionBar().setElevation(0);
activity.getSupportActionBar().setDisplayHomeAsUpEnabled( true );
activity.getSupportActionBar().setHomeButtonEnabled( true );
activity.getSupportActionBar().setDisplayShowTitleEnabled( false );
toolbar.setNavigationOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View v) {
getActivity().onBackPressed();
}
} );
}
}
Try the below code snippet instead of toolbar.setNavigationOnClickListener
#Override public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == android.R.id.home){
getActivity().onBackPressed();
}
return super.onOptionsItemSelected(item);
}
hope this will solve your problem.
thanks
This is just because you have used FrameLayout as a parent - and also removed elevation from AppBarLayout, and due to this, Your ScrollView is overlapping your AppBarLayout as it is written below AppBarLayout. change your root to something else, for eg.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/transparent"
android:theme="#style/AppTheme.AppBarOverlay">
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/appBarLayout">
</ScrollView>
</RelativeLayout>

NestedScrollView + CoodinatorLayout scrollBy() scrollTo() methods do nothing

I have a NestedScrollView being used with CoordinatorLayout + AppBarLayout + CollapsingToolbarLayout with parallax effect similar to this tutorial
I need to scroll the content programmatically (preferably a smooth scroll, i.e. animated), however calling the scroll methods (scrollBy(), scrollTo(), smoothScrollTo(), smoothScrollBy()) do nothing.
Note that I am using app:layout_behavior="#string/appbar_scrolling_view_behavior" <-- Not sure if the issue is related to this.
I'm calling nsv_form.smoothScrollBy(0, 300) in Kotlin when a button is clicked by the user, but nothing happens :(
(Also tried scrollTo(), scrollBy(), +- 300, all sorts of different variations)
UPDATE: I dug into source code and it seems like the *scroll*() methods expect the content of the layout to be larger than the parent view (makes sense). In my case, the content is smaller, so I suspect that's why the scrolling methods do not work. Perhaps I need something different instead of scroll?
The NestedScrollView's position starts partially off the screen with an image above it in a CollapsingToolbarLayout, like this, so it seems like I need to programmatically move the position of the NestedScrollView AND trigger the CoordinatorLayout's scrolling behavior. -- How do I do this?
Here's my layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="#+id/iv_image"
android:layout_width="match_parent"
android:layout_height="#dimen/image_height"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"
tools:src="#drawable/some_image" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:id="#+id/nsv_form"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:orientation="vertical">
[... child views...]
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
TLDR: How do I scroll like this programmatically?
How do I scroll like this programmatically?
For that scrolling behavior you need collapse or expand CollapsingToolbarLayout no need to scroll your the NestedScrollView
Here is the sample code for that
Try this Make some below changes in your Layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:id="#+id/rootView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="#+id/iv_image"
android:layout_width="match_parent"
android:layout_height="250dp"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:src="#drawable/goku"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.7" />
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
app:contentInsetStartWithNavigation="0dp"
app:titleTextAppearance="#style/AppTheme.Toolbar.Title"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#color/Boxcolordiabled"
app:layout_anchor="#id/app_bar"
app:layout_anchorGravity="bottom|end"
app:srcCompat="#drawable/ic_favorite" />
<androidx.core.widget.NestedScrollView
android:id="#+id/nsv_form"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_blue_light"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="#string/demo" />
<Button
android:id="#+id/btnColl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="Expand " />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="#string/demo" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="#string/demo" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="#string/demo" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="#string/demo" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="#string/demo" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="#string/demo" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="#string/demo" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Activity code
import android.animation.ValueAnimator;
import android.os.Bundle;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.Button;
import android.widget.Toast;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import neel.com.bottomappbar.R;
public class MainActivity extends AppCompatActivity {
Toolbar toolbar;
AppBarLayout app_bar;
Button btnColl;
FloatingActionButton fab;
CoordinatorLayout rootView;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle("Stack Demo");
app_bar = findViewById(R.id.app_bar);
btnColl = findViewById(R.id.btnColl);
fab = findViewById(R.id.fab);
rootView = findViewById(R.id.rootView);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, "Collapse FAB Clicked", Toast.LENGTH_SHORT).show();
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) app_bar.getLayoutParams();
final AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
if (behavior != null) {
ValueAnimator valueAnimator = ValueAnimator.ofInt();
valueAnimator.setInterpolator(new DecelerateInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
behavior.setTopAndBottomOffset((Integer) animation.getAnimatedValue());
app_bar.requestLayout();
}
});
valueAnimator.setIntValues(0, -900);
valueAnimator.setDuration(1000);
valueAnimator.start();
}
}
});
btnColl.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, "Expand btnColl Clicked", Toast.LENGTH_SHORT).show();
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) app_bar.getLayoutParams();
final AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
if (behavior != null) {
ValueAnimator valueAnimator = ValueAnimator.ofInt();
valueAnimator.setInterpolator(new DecelerateInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
behavior.setTopAndBottomOffset((Integer) animation.getAnimatedValue());
app_bar.requestLayout();
}
});
valueAnimator.setIntValues(-900, 0);
valueAnimator.setDuration(400);
valueAnimator.start();
}
}
});
}
}
OUTPUT
https://www.youtube.com/watch?v=nZY1zPxjRt0
Scrolls (scrollBy()/scrollTo()/smoothScrollTo()/smoothScrollBy()) needs to be called from UI thread.
In Kotlin, you can use
Handler().post {
nsv_form.scrollBy(0, 300)
}

Android Bottom Sheet with Listview not working

I'm trying to use a Bottom Sheet with a ListView inside it, but I'm facing two problem, 1st. the ListView doesn't occupy all the space from the Bottom Sheet, the match-parent isn't working, 2nd. scrolling through the list view doesn't really work, if I try to scroll down it only scrolls a little instead of a normal scroll and if I scroll up, the Bottom Sheet closes instead of scrolling the list first.
Gif of the problem
Here's the 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">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.abili.agriexport2.MapsActivity" />
<android.support.v4.widget.NestedScrollView
android:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="350dp"
android:background="?android:attr/windowBackground"
android:clipToPadding="true"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary"
android:orientation="horizontal">
<TextView
android:id="#+id/textView11"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:padding="16dp"
android:text="Direções"
android:textColor="#color/colorWhite"
android:textSize="24sp" />
<ImageButton
android:id="#+id/closeBottomSheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="5"
android:background="#null"
app:srcCompat="#drawable/mr_ic_close_dark" />
</LinearLayout>
<ListView
android:id="#+id/listaDirecoes"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
Appreciate any help :)
try to add
android:fillViewport="true"
to your NestedScrollView
For the other problem, I used this way once:
yourLV.setOnScrollListener(new ListView.OnScrollListener() {
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
#Override
public void onScrollStateChanged(AbsListView arg0, int arg1) {
if (listIsAtTop(yourLV)) {
yourLV.setOnTouchListener(null);
} else {
yourLV.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// Disallow the touch request for parent scroll on touch of child view
v.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
}
}
});
And
public static boolean listIsAtTop(ListView listView) {
if(listView.getChildCount() == 0) return true;
return listView.getChildAt(0).getTop() == 0;
}

Android: How to disable user scroll for the CoordinatorLayout

I have this simple layout:
<RelativeLayout 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.CoordinatorLayout
android:id="#+id/root"
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/ActionBarThemeOverlay">
<include layout="#layout/include_toolbar_actionbar"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/theme_primary"
android:padding="#dimen/keyline_1">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/bg_search_view"
android:focusable="true"
android:focusableInTouchMode="true">
<com.xxxx.ui.widget.CustomSearchView
android:id="#+id/search_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:withBackButton="true" />
</FrameLayout>
</FrameLayout>
</android.support.design.widget.AppBarLayout>
<RelativeLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/background"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"/>
<LinearLayout
android:id="#+id/methods_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="#dimen/keyline_5">
<com.xxx.ui.widget.ButtonSearchBy
android:id="#+id/search_by_categories"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="#string/search_by_categories"
app:icon="#drawable/ic_by_categories"
app:iconFillColor="#color/grey"
android:visibility="gone"/>
<com.xxx.ui.widget.ButtonSearchBy
android:id="#+id/search_by_recents"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="#string/search_by_recents"
app:icon="#drawable/ic_by_recents"
app:iconFillColor="#color/grey"
android:visibility="gone"/>
</LinearLayout>
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
</RelativeLayout>
In my Activity, I added this code to disable user scroll on directly CoordinatorLayout:
if (mAppBarLayout.getLayoutParams() != null) {
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
AppBarLayout.Behavior appBarLayoutBehaviour = new AppBarLayout.Behavior();
appBarLayoutBehaviour.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
#Override
public boolean canDrag(#NonNull AppBarLayout appBarLayout) {
return false;
}
});
layoutParams.setBehavior(appBarLayoutBehaviour);
}
This code works correctly, BUT in the "fragment_container" (FrameLayout), I add a RecyclerView, and if the user scrolls into this list then the Coordinator scrolls too...
I want collapse or expand automatically my CoordinatorLayout, and not to have a link with the RecyclerView scrolling.
I tried this too, but it doesn't work properly:
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
if (mFragmentContainer.getVisibility() == View.VISIBLE &&
event.getAction() == MotionEvent.ACTION_MOVE) {
Rect fragContainerRect = new Rect();
mFragmentContainer.getHitRect(fragContainerRect);
if (fragContainerRect.contains((int) event.getX(), (int) event.getY())) {
LogUtils.LOGD("XXXX", "move");
mFragmentContainer.dispatchTouchEvent(event);
return true;
}
}
return super.dispatchTouchEvent(event);
}
So how can I do to disable the CoordinatorLayout scrolling when the list scrolls?
Thank you very much guys!

BottomSheetBehaviour with NestedScrollView

I used Nestedscrollview as Bottomsheetbehaviour but when it changes its state from normal to expanded some of space from toolbar left but when second time state changed from normal to expanded it works fine..
It looks as it leaves space exactly twice of the margin I provide to the sheet in xml. My code looks like this...
MyLayoutFile.xml
<android.support.design.widget.CoordinatorLayout
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:id="#+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
tools:context=".fragments.StoreLocationDetailsFragment">
<include layout="#layout/toolbar"/>
<FrameLayout
android:id="#+id/mapHolder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?android:attr/actionBarSize"/>
<include android:id="#+id/nested_scroll_view"
layout="#layout/store_details_scroll_view"/>
</android.support.design.widget.CoordinatorLayout>
store_details_scroll_view.xml
<android.support.v4.widget.NestedScrollView
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:layout_marginTop="?android:attr/actionBarSize"
android:background="#color/colorLightGrey"
android:clipToPadding="true"
app:behavior_peekHeight="0dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingTop="#dimen/activity_horizontal_margin">
<TextView
android:id="#+id/tvStoreName"
style="#style/styleOswaldBold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/activity_horizontal_margin"
android:text="Adidas Shoes"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Title"/>
<TextView
android:id="#+id/tvAddress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/sub_title"
android:textAlignment="center"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="#dimen/activity_horizontal_margin"
android:background="#color/colorDarkGrey"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
and code in onClick Function in java file looks like
View bottomSheet = rootLayout.findViewById(R.id.nested_scroll_view);
behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setPeekHeight(new ScreenDimensions(getActivity())
.getHeightWithGivenPercentage(60));
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
switch (newState) {
case BottomSheetBehavior.STATE_DRAGGING:
break;
case BottomSheetBehavior.STATE_COLLAPSED:
behavior.setPeekHeight(0);
break;
case BottomSheetBehavior.STATE_EXPANDED:
break;
}
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
}
});
Here rootlayout is my Coordinator layout. Can anyone suggest me solution of the above problem. Thanks in advance.

Categories

Resources