CoordinatorLayout: onDependentViewChanged not getting called - android

I have a very simple scenario involving a NestedScrollView and LinearLayout where I want the LinearLayout to translate as the NestedScrollView scrolls up. Here is the layout in picture:(the concerned child view is the second last LinearLayout with the Id of linearlayout )
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.snapsboardmainpage.MainActivity"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp">
<android.support.v4.widget.NestedScrollView
android:id="#+id/nested_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/linearLayout3"
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="vertical"
android:layout_gravity="top"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="0dp"
android:layout_marginRight="0dp"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginLeft="0dp"
app:layout_constraintLeft_toLeftOf="parent">
</LinearLayout>
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="0dp"
android:layout_height="112dp"
android:orientation="vertical"
android:background="#android:color/holo_green_light"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/linearLayout3">
</LinearLayout>
<android.support.v4.view.ViewPager
android:id="#+id/id_viewpager_photosvideos_albums"
android:layout_width="0dp"
android:layout_height="1000dp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/linearLayout1">
<android.support.design.widget.TabLayout
android:id="#+id/id_tab_photosvideos_albums"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top">
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.design.widget.TabLayout>
</android.support.v4.view.ViewPager>
</android.support.constraint.ConstraintLayout>
</android.support.v4.widget.NestedScrollView>
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="vertical"
android:layout_gravity="top"
app:layout_behavior="com.example.snaps.TopActionBarBehavior"
android:background="#android:color/holo_blue_light">
</LinearLayout>
<LinearLayout
android:id="#+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="56dp"
android:orientation="vertical"
android:layout_gravity="bottom"
android:background="#android:color/holo_orange_light">
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
And, the concerned behavior(TopActionBarBehavior) as follows:
public class TopActionBarBehavior extends CoordinatorLayout.Behavior<LinearLayout> {
private static final String TAG = "TopActionBarBehavior";
private int thresholdScrollDistance;
private int mNestedScrollViewInitialTop;
public TopActionBarBehavior() {
}
public TopActionBarBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean layoutDependsOn(CoordinatorLayout parent, LinearLayout child, View dependency) {
return dependency instanceof NestedScrollView;
}
#Override
public boolean onDependentViewChanged(CoordinatorLayout parent, LinearLayout child, View dependency) {
// Translate the child view as per the NestedScrollView
int currentNestedScrollViewTop = dependency.getTop();
// Have we scrolled up?
if(currentNestedScrollViewTop > mNestedScrollViewInitialTop){
// Translate the child view by the same distance
child.setTranslationY(currentNestedScrollViewTop - mNestedScrollViewInitialTop);
}
return true;
}
#Override
public boolean onLayoutChild(CoordinatorLayout parent, LinearLayout child, int layoutDirection) {
View topBar = parent.findViewById(R.id.linearLayout);
int topBarHeight = topBar.getHeight();
View nestedScrollView = parent.findViewById(R.id.nested_container);
mNestedScrollViewInitialTop = nestedScrollView.getTop();
View profileBar = parent.findViewById(R.id.linearLayout1);
int profileBarHeight = profileBar.getHeight();
View dummyTopBarUnderlay = parent.findViewById(R.id.linearLayout3);
int dummyTopBarHeight = dummyTopBarUnderlay.getHeight();
View tabLayout = parent.findViewById(R.id.id_tab_photosvideos_albums);
int tabLayoutHeight = tabLayout.getHeight();
thresholdScrollDistance = profileBarHeight + dummyTopBarHeight + tabLayoutHeight;
return super.onLayoutChild(parent, child, layoutDirection);
}
}
I tried debugging and layoutDependsOn() is getting called as it should be but onDependentViewChanged() is getting called only once.

Finally found the answer after countless hours of debugging. My NestedScrollView wasn't actually moving at all; it's content was moving the whole time which didn't trigger this method. For scroll events, we can tap onto the onNested*() methods in the Behavior class. Simple.

Related

Stop scroll of parent (NestedScrollview) When scrolling Child(RecyclerView)

I need behavior similar to this implementation But NestedScrollView would be the parent and RecyclerView would be the child of would NestedScrollView .
Eg: https://medium.com/widgetlabs-engineering/scrollable-nestedscrollviews-inside-recyclerview-ca65050d828a
I am not sure whether it can be achieved.Tried disabling the of parent(NSV) while child(RV)is scrolling But scroll on child scrolls the entire view including parent.
I'v implemented Marc Knaup solution and all works correct event if NestedScrollView would be the parent and the result was shown below
btw, i put what i'v done
CustomRecycleView
package com.example.nested_scroll_test;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import androidx.core.view.NestedScrollingParent;
import androidx.recyclerview.widget.RecyclerView;
public class CustomRecycleView extends RecyclerView implements NestedScrollingParent {
private View nestedScrollTarget = null;
private boolean nestedScrollTargetIsBeingDragged = false;
private boolean nestedScrollTargetWasUnableToScroll = false;
private boolean skipsTouchInterception = false;
public CustomRecycleView(Context context) {
super(context);
}
public CustomRecycleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomRecycleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean temporarilySkipsInterception = nestedScrollTarget != null;
if (temporarilySkipsInterception) {
// If a descendent view is scrolling we set a flag to temporarily skip our onInterceptTouchEvent implementation
skipsTouchInterception = true;
}
// First dispatch, potentially skipping our onInterceptTouchEvent
boolean handled = super.dispatchTouchEvent(ev);
if (temporarilySkipsInterception) {
skipsTouchInterception = false;
// If the first dispatch yielded no result or we noticed that the descendent view is unable to scroll in the
// direction the user is scrolling, we dispatch once more but without skipping our onInterceptTouchEvent.
// Note that RecyclerView automatically cancels active touches of all its descendents once it starts scrolling
// so we don't have to do that.
if (!handled || nestedScrollTargetWasUnableToScroll) {
handled = super.dispatchTouchEvent(ev);
}
}
return handled;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent e) {
return !skipsTouchInterception && super.onInterceptTouchEvent(e);
}
#Override
public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
if (dyConsumed != 0) {
// The descendent was actually scrolled, so we won't bother it any longer.
// It will receive all future events until it finished scrolling.
nestedScrollTargetIsBeingDragged = true;
nestedScrollTargetWasUnableToScroll = false;
} else if (dyConsumed == 0 && dyUnconsumed != 0) {
// The descendent tried scrolling in response to touch movements but was not able to do so.
// We remember that in order to allow RecyclerView to take over scrolling.
nestedScrollTargetWasUnableToScroll = true;
if (target.getParent() != null)
target.getParent().requestDisallowInterceptTouchEvent(false);
}
}
#Override
public void onNestedScrollAccepted(View child, View target, int axes) {
if (axes != 0 && View.SCROLL_AXIS_VERTICAL != 0) {
// A descendent started scrolling, so we'll observe it.
nestedScrollTarget = target;
nestedScrollTargetIsBeingDragged = false;
nestedScrollTargetWasUnableToScroll = false;
}
super.onNestedScrollAccepted(child, target, axes);
}
#Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
return nestedScrollAxes != 0 && View.SCROLL_AXIS_VERTICAL != 0;
}
#Override
public void onStopNestedScroll(View child) {
nestedScrollTarget = null;
nestedScrollTargetIsBeingDragged = false;
nestedScrollTargetWasUnableToScroll = false;
}
}
content_main.xml
<?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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="#layout/activity_main">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorAccent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="#FFFFFF"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAlignment="center"
android:text="Top Section"/>
</LinearLayout>
<com.example.nested_scroll_test.CustomRecycleView
android:id="#+id/rw"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#color/colorPrimary"
android:nestedScrollingEnabled="true"
android:orientation="vertical">
</com.example.nested_scroll_test.CustomRecycleView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="#FFFFFF"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAlignment="center"
android:text="Bottom Section"/>
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
RecycleViewItem.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/nsw"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="vertical">
<TextView
android:id="#+id/textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:background="#CCCC"
android:gravity="center"
android:nestedScrollingEnabled="false"
android:orientation="vertical"
android:padding="2dp"
android:textColor="#FFFFFF" />
</androidx.core.widget.NestedScrollView>
#Rockin use overscrollmode bro:)
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:fillViewport="true"
android:overScrollMode="always"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/color_white"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/activity_insight_recyclerview_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="#dimen/_20sdp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="#layout/raw_insight" />
post entire thing what you have tried so far.
your xml should be ,
<android.support.v4.widget.NestedScrollView
android:id="#+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View > <!-- upper content -->
<!-- set recycler view with with wrap_content -->
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
set scrolling behaviour inside onCreateView() / onCreate() method.
requires Api 21+ .
RecyclerView v = (RecyclerView) findViewById(...);
v.setNestedScrollingEnabled(false);
or
android:nestedScrollingEnabled="false" // inside recycler view in xml file
This is demo for what you want look, In MainActivity.xml file :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
tools:context="MainActivity">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:orientation="vertical">
<ImageView
android:id="#+id/top_seller"
android:layout_width="match_parent"
android:layout_height="200sp"
android:background="#color/colorAccent"
android:contentDescription="#string/app_name"
android:adjustViewBounds="true"
android:src="#drawable/background"
android:scaleType="fitXY"/>
<ImageView
android:id="#+id/top_seller1"
android:layout_width="match_parent"
android:layout_height="200sp"
android:background="#color/colorAccent"
android:contentDescription="#string/app_name"
android:adjustViewBounds="true"
android:src="#drawable/background"
android:scaleType="fitXY"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/product_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:scrollbars="none" />
<ImageView
android:id="#+id/top_seller2"
android:layout_width="match_parent"
android:layout_height="200sp"
android:background="#color/colorAccent"
android:contentDescription="#string/app_name"
android:adjustViewBounds="true"
android:src="#drawable/background"
android:scaleType="fitXY"/>
<ImageView
android:id="#+id/top_seller3"
android:layout_width="match_parent"
android:layout_height="200sp"
android:background="#color/colorAccent"
android:contentDescription="#string/app_name"
android:adjustViewBounds="true"
android:src="#drawable/background"
android:scaleType="fitXY"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
In your MainActivity.java class onCreate method:
RecyclerView bestRecyclerView = findViewById(R.id.product_list);
GridLayoutManager mGrid = new GridLayoutManager(this, 2);
bestRecyclerView.setLayoutManager(mGrid);
bestRecyclerView.setHasFixedSize(true);
bestRecyclerView.setNestedScrollingEnabled(false);
// Create ProductAdapter for RecyclerView data
ProductAdapter mAdapter = new ProductAdapter(MainActivity4.this,getProductTestData());
bestRecyclerView.setAdapter(mAdapter);
I hope It'll help you...!
In general simple trick works for me. When attaching OnTouchListener to child View, in onTouch() just disable touch interrupts. Something like this:
RecyclerView rv = findViewById(...);
rv.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
...
v.getParent().requestDisallowInterceptTouchEvent(true);
Have you try subclass the RV and override onInterceptTouchEvent?
override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
when (event!!.action and MotionEvent.ACTION_MASK) {
MotionEvent.ACTION_DOWN -> {
// WE INTERACT WITH THIS RV. PREVENT PARENT TO INTERCEPT
parent.requestDisallowInterceptTouchEvent(true)
}
MotionEvent.ACTION_MOVE, MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> {
// THIS SEEMS LIKE IT WILL HAVE "DEFAULT" BEHAVIOUR BUT SINCE WE CURRENTLY DRAGGING THE RV THEN IT WONT SCROLL THE PARENT
parent.requestDisallowInterceptTouchEvent(false)
}
}
return false
}

Scrolling fragment comes on top of Activity cause below activity view to scroll

I have an activity which has CoordinatorLayout as a root layout. Inside that, there's a FrameLayout layout which is hidden and programmatically has been set a fragment which is revealed from the bottom on a button click. That fragment consists of a grid RecyclerView which is scrollable.
refer to this
If you focus on the toolbar you can see behind view gets scroll down and shows the behind view image when the grid view scroll content is over.
This is the layout of my activity
Activity Layout
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
android:id="#+id/coordinator_layout"
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:fitsSystemWindows="true"
android:focusableInTouchMode="true"
tools:context=".activities.hotels.HotelDetailActivity">
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar"
android:layout_width="match_parent"
android:layout_height="#dimen/app_bar_height"
android:fitsSystemWindows="true"
android:theme="#style/AppTheme.AppBarOverlay"
app:layout_behavior="android.support.design.widget.AppBarLayout$Behavior">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:toolbarId="#+id/toolbar"
app:expandedTitleTextAppearance="#style/TransparentText"
app:collapsedTitleTextAppearance="#style/ExpandedAppBar"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:titleEnabled="true">
<ImageView
android:id="#+id/main_hotel_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:fitsSystemWindows="true"
android:src="#drawable/temp_hotel"
app:layout_collapseMode="parallax" />
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="#style/AppTheme.PopupOverlay"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tool_bar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/roboto_medium"
android:text="Hotel Name"
android:singleLine="true"
android:textColor="#android:color/white"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/tool_bar_sub_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Thu, 10 Jan 2019 - Sat, 12 Jan 2019"
android:textColor="#color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tool_bar_title" />
</android.support.constraint.ConstraintLayout>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_scrolling" />
<FrameLayout
android:id="#+id/more_detail_fragment_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:visibility="gone"
android:layout_gravity="center"
android:gravity="center"
android:layout_marginTop="56dp"
android:layout_marginBottom="56dp"
android:clickable="true"/>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/fab_margin"
android:src="#drawable/ic_photo_library"
app:backgroundTint="#color/white"
app:fabSize="mini"
app:layout_anchor="#id/app_bar"
app:layout_anchorGravity="bottom|end" />
<android.support.constraint.ConstraintLayout
android:id="#+id/bottom_message_container"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="#drawable/clickable_bottom_bar_background"
android:layout_gravity="bottom"
android:gravity="bottom">
<android.support.constraint.ConstraintLayout
android:id="#+id/bottom_message_container_child"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/price_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginBottom="8dp"
android:fontFamily="#font/roboto_regular"
android:text="LKR 0"
android:textColor="#android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:id="#+id/detail_titel_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginStart="8dp"
android:fontFamily="#font/roboto_light"
android:text="Starting From"
android:textColor="#android:color/white"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<FrameLayout
android:id="#+id/continue_button"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginTop="8dp"
android:background="#drawable/secondary_button_background"
android:clickable="true"
android:paddingEnd="8dp"
android:paddingStart="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="#+id/button_color"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="#font/roboto_medium"
android:text="Continue"
android:textColor="#android:color/white"
android:textSize="16sp" />
</FrameLayout>
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
</android.support.design.widget.CoordinatorLayout>
Fragment Layout
<LinearLayout 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"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".fragments.hotels.AllHotelAmenitiesFragment"
android:orientation="vertical"
android:background="#color/white"
android:clickable="true">
<TextView
android:id="#+id/hotel_amenities_title_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:fontFamily="#font/roboto_medium"
android:text="Hotel Amenities"
android:textColor="#color/textColorPrimary"
android:textSize="14sp"
android:layout_marginStart="16dp" />
<View
android:id="#+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="8dp"
android:background="#color/divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/recycler_view_expand_layout"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/main_hotel_amenities_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:clickable="true"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"/>
</LinearLayout>
HotelDetailActivity
public class HotelDetailActivityEdit extends AppCompatActivity{
#BindView(R.id.toolbar)
Toolbar toolbar;
#BindView(R.id.more_detail_fragment_holder)
FrameLayout allHotelAmenityHolder;
#BindView(R.id.app_bar)
AppBarLayout appBarLayout;
#BindView(R.id.recycler_view_expand_layout)
FrameLayout recyclerViewExpandLayout;
private boolean allAmenitiesFragmentIsHidden;
private Animation revealFromBottom;
private Animation unRevealFromBottom;
private AllHotelAmenitiesFragment allHotelAmenitiesFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hotel_detail);
ButterKnife.bind(this);
initialization();
onClickHotelAmenityExpandContainer();
}
private void initialization() {
revealFromBottom = AnimationUtils.loadAnimation(this, R.anim.slide_in_bottom);
unRevealFromBottom = AnimationUtils.loadAnimation(this, R.anim.slide_out_bottom);
allAmenitiesFragmentIsHidden = true;
allHotelAmenitiesFragment = new AllHotelAmenitiesFragment();
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map_fragment);
}
private void onClickHotelAmenityExpandContainer() {
recyclerViewExpandLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (allAmenitiesFragmentIsHidden) {
allHotelAmenityHolder.startAnimation(revealFromBottom);
allHotelAmenityHolder.setVisibility(View.VISIBLE);
appBarLayout.setExpanded(false);
allAmenitiesFragmentIsHidden = false;
invalidateOptionsMenu();
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!allAmenitiesFragmentIsHidden)
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_action_close);
else {
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_action_arrow_back);
}
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
break;
}
return true;
}
#Override
public void onBackPressed() {
if (!allAmenitiesFragmentIsHidden) {
allHotelAmenityHolder.startAnimation(unRevealFromBottom);
allHotelAmenityHolder.setVisibility(View.GONE);
appBarLayout.setExpanded(true);
allAmenitiesFragmentIsHidden = true;
invalidateOptionsMenu();
} else {
finish();
}
}
}
AllHotelAmenitiesFragment
public class AllHotelAmenitiesFragment extends Fragment {
#BindView(R.id.main_hotel_amenities_recycler_view)
RecyclerView mainHotelAmenitiesRecyclerView;
private MainHotelAmenitiesListAdapter mainHotelAmenitiesListAdapter;
public AllHotelAmenitiesFragment() {
// Required empty public constructor
}
public void setArguments(ArrayList<HotelAmenitiesImageObject> hotelAmenitiesWithImages) {
Bundle args = new Bundle();
args.putParcelableArrayList("hotel_amenities", hotelAmenitiesWithImages);
this.setArguments(args);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_all_hotel_amenities, container, false);
ButterKnife.bind(this, view);
initialization();
return view;
}
private void initialization() {
ArrayList<HotelAmenitiesImageObject> mainHotelAmenities = getArguments().getParcelableArrayList("hotel_amenities");
mainHotelAmenitiesListAdapter = new MainHotelAmenitiesListAdapter(mainHotelAmenities);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), 4);
GridRecyclerViewDivider gridRecyclerItemDecorator = new GridRecyclerViewDivider(4, 16, true, 0);
mainHotelAmenitiesRecyclerView.addItemDecoration(gridRecyclerItemDecorator);
mainHotelAmenitiesRecyclerView.setLayoutManager(gridLayoutManager);
mainHotelAmenitiesRecyclerView.setAdapter(mainHotelAmenitiesListAdapter);
}
}
As you can see I have set android:clickable="true" to the root layout of the fragment which is what usually do to stop registering clicks on behind layout. It seems when it's come to scroll it does not work like that.
I don't want my activity view behind my fragment to react to the scroll when my fragment visible. Please give me a suggestion to fix this bug.
Here are my solution
I have run a demo, this works! It is the Gif links
If this solution help you, please Accept this answer.
code block one
disable the AppBarLayout scroll event to expand or collapse
code block two
disable the recyclerview scroll event to expand or collapse AppBarLayout
you can use scroll flag to disable it too, which i have comment, but this way will expand the AppBarLayout first
You can use these two code block to get what you want.
You should modified these code for your project
when fragment visible, ViewCompat.setNestedScrollingEnabled(mRecyclerView, false) to disable your fragment's recyclerview not your content_scrolling layout recyclerview.
private int state = STATE_APPBAR;
private static final int STATE_APPBAR = 1;
private static final int STATE_CONTENT = 2;
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
params.setBehavior(new AppBarLayout.Behavior());
AppBarLayout.Behavior appBarBehavior = (AppBarLayout.Behavior) params.getBehavior();
//code block one
if (appBarBehavior != null) {
appBarBehavior.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
#Override
public boolean canDrag(#NonNull AppBarLayout appBarLayout) {
return state == STATE_APPBAR;
}
});
}
//code block two
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (state == STATE_APPBAR) {
state = STATE_CONTENT;
//setAppbarLayoutScrollFlag(AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP);
ViewCompat.setNestedScrollingEnabled(mRecyclerView, false);
} else {
state = STATE_APPBAR;
//setAppbarLayoutScrollFlag(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED);
ViewCompat.setNestedScrollingEnabled(mRecyclerView, true);
}
}
});
private void setAppbarLayoutScrollFlag(int flags) {
AppBarLayout.LayoutParams lp = (AppBarLayout.LayoutParams) mToolbarLayout.getLayoutParams();
lp.setScrollFlags(flags);
mToolbarLayout.setLayoutParams(lp);
}
Apply the code in your project
add a method in AllHotelAmenitiesFragment to get recyclerview
public class AllHotelAmenitiesFragment extends Fragment {
#BindView(R.id.main_hotel_amenities_recycler_view)
RecyclerView mainHotelAmenitiesRecyclerView;
private MainHotelAmenitiesListAdapter mainHotelAmenitiesListAdapter;
public AllHotelAmenitiesFragment() {
// Required empty public constructor
}
public RecyclerView getRecyclerView() {
return mainHotelAmenitiesRecyclerView;
}
In your HotelDetailActivityEdit add block logic
private void onClickHotelAmenityExpandContainer() {
recyclerViewExpandLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (allAmenitiesFragmentIsHidden) {
allHotelAmenityHolder.startAnimation(revealFromBottom);
allHotelAmenityHolder.setVisibility(View.VISIBLE);
appBarLayout.setExpanded(false);
allAmenitiesFragmentIsHidden = false;
invalidateOptionsMenu();
//add block logic
RecyclerView recyclerview = allHotelAmenitiesFragment.getRecyclerView();
ViewCompat.setNestedScrollingEnabled(recyclerview, false);
}
}
});
}
For the collapsing toolbar and scrolling behaviour to work properly in CoordinatorLayout, you need to define the layout_behaviour in the content layout.
You have an <include/> layout directly above your frame, I suspect this will have the correct layout attributes, so your frame layout is sort of "floating" in no-man's land.
<include layout="#layout/content_scrolling" />
<FrameLayout
android:id="#+id/more_detail_fragment_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:visibility="gone"
android:layout_gravity="center"
android:gravity="center"
android:layout_marginTop="56dp"
android:layout_marginBottom="56dp"
android:clickable="true"/>
You probably want the frame layout sitting inside a <NestedScrollView>, and then I guess you may not be using the include so just delete that. Something like this:
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<FrameLayout
android:id="#+id/more_detail_fragment_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:visibility="gone"
android:layout_gravity="center"
android:gravity="center"
android:layout_marginTop="56dp"
android:layout_marginBottom="56dp"
android:clickable="true"/>
</android.support.v4.widget.NestedScrollView>

HorizontalScrollView inside a ScrollView android

I have a HorizontalScrollView inside a VerticalScrollView. If I scroll Horizontally , the scrolling is smooth. But if I scroll Vertically , the scroll is not smooth, it is getting scrolled horizontally sometimes. How to make the vertical scroll smooth ?
Here is my xml ,
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.sasank.calendarview.MainActivity"
android:background="#android:color/white">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="500dp"
android:layout_marginLeft="200dp"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/chapter_list"
android:layout_width="150dp"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
<HorizontalScrollView
android:id="#+id/horizontal_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="#id/chapter_list"
android:scrollbars="horizontal">
<android.support.v7.widget.RecyclerView
android:id="#+id/calendar"
android:layout_width="wrap_content"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</HorizontalScrollView>
</RelativeLayout>
</ScrollView>
</RelativeLayout>
</RelativeLayout>
Im using a Vertical LinearLayoutManager for Chapter_list Recyclerview and GridLayoutManager for Calendar RecyclerView
android:nestedScrollingEnabled="true"
You can try this, but still problems connected to the nested scrolling and so on are actually common. People have had the same problems here on StackOverflow, take a look, i hope it can help you: Problems with Nested Scrolling
I have vertical scrollview and horizontal recycleview photo gallery in one of my projects and it works fine. Here's the code:
fragment/activity layout:
<ScrollView 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"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
...
<android.support.v7.widget.RecyclerView
android:id="#+id/horizontal_recycler_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginBottom="15dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:horizontalSpacing="10dp"
android:isScrollContainer="false"
android:stretchMode="columnWidth"
android:verticalSpacing="10dp"
/>
...
</LinearLayout>
</ScrollView>
item:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/horizontal_item_view_image"
android:layout_marginRight="10dp"
android:layout_width="109dp"
android:layout_height="109dp" />
</LinearLayout>
adapter:
public class HorizontalPhotosAdapter extends RecyclerView.Adapter<HorizontalPhotosAdapter.MyViewHolder> {
private Context context;
private LayoutInflater inflater;
private ArrayList<Bitmap> bitmapList;
public class MyViewHolder extends RecyclerView.ViewHolder {
private ImageView riv;
public MyViewHolder(View view) {
super(view);
riv = (ImageView) view.findViewById(R.id.horizontal_item_view_image);
}
}
public HorizontalPhotosAdapter(Context context, ArrayList<Bitmap> bitmapList, String[] imageUrls) {
this.context = context;
this.bitmapList = bitmapList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.horizontal_item_view, parent, false);
if (itemView.getLayoutParams ().width == RecyclerView.LayoutParams.MATCH_PARENT)
itemView.getLayoutParams ().width = RecyclerView.LayoutParams.WRAP_CONTENT;
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.riv.setImageBitmap(bitmapList.get(position));
}
#Override
public int getItemCount() {
return bitmapList.size();
}
}
implementation in fragment/activity:
horizontalAdapter=new HorizontalPhotosAdapter(getContext(), bitmapList);
horizontal_recycler_view.setAdapter(horizontalAdapter);
horizontalAdapter.notifyDataSetChanged();
LinearLayoutManager horizontalLayoutManagaer = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
horizontal_recycler_view.setLayoutManager(horizontalLayoutManagaer);
horizontal_recycler_view.setAdapter(horizontalAdapter);

Fixed view in ViewPager's content layout, under CoordinatorLayout

My app has an Activity with TabLayout, and 3 Fragments. In Activity's layout, I have CoordinatorLayout with ViewPager. I need to animate toolbar as well.
Now In Fragments layout, I need to put a fixed TextView at the bottom.
Given below is the XML of activity and fragment.
I am facing the problem that this fixed TextView in Fragment's
layout is going under the bottom navigation bar and is scrolling also,
that I don't want.
How can achieve this ?
activity.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"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/clMain"
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/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="#style/AppTheme.PopupOverlay">
<TextView
android:id="#+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/toolbar"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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/colorWhite"
android:orientation="vertical">
<android.support.v4.widget.NestedScrollView
android:id="#+id/rlParent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
android:layout_weight="1"
android:fitsSystemWindows="true"
android:orientation="vertical">
</android.support.v4.widget.NestedScrollView>
<TextView
android:id="#+id/tvConfirmOrder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorDarkGreen"
android:gravity="center"
android:padding="10dp"
android:text="#string/confirm_order"
android:textColor="#color/colorWhite"
android:textSize="18sp"
android:textStyle="bold"></TextView>
</LinearLayout>
As you want this bottom fixed TextView for each fragment, it can be solved by transferring your TextView to activity.xml and adding a custom behavior to it.
So, firstly, create a class that represents custom behavior:
public class FixedBottomViewBehavior extends CoordinatorLayout.Behavior<View> {
public FixedBottomViewBehavior() {
}
public FixedBottomViewBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
//making our bottom view depends on ViewPager (or whatever that have appbar_scrolling_view_behavior behavior)
return dependency instanceof ViewPager;
}
#Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
if (ViewCompat.isLaidOut(parent)) {
//attach our bottom view to the bottom of CoordinatorLayout
child.setY(parent.getBottom() - child.getHeight());
//set bottom padding to the dependency view to prevent bottom view from covering it
dependency.setPadding(dependency.getPaddingLeft(), dependency.getPaddingTop(),
dependency.getPaddingRight(), child.getHeight());
}
return false;
}
}
There is no magic here, we're just making our bottom view dependent on some view with appbar_scrolling_view_behavior (in our case it's ViewPager) and then attaching it to the bottom of CoordinatorLayout and setting some padding to dependency.
Secondly, change your activity.xml, by adding your TextView there:
<?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/clMain"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="#style/AppTheme.PopupOverlay">
<TextView
android:id="#+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/toolbar"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<TextView
android:id="#+id/tvConfirmOrder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#color/colorDarkGreen"
android:gravity="center"
android:padding="10dp"
android:text="#string/confirm_order"
android:textColor="#color/colorWhite"
android:textSize="18sp"
android:textStyle="bold"
app:layout_behavior="your.package.name.FixedBottomViewBehavior" />
</android.support.design.widget.CoordinatorLayout>
Make sure you've removed your TextView from fragment.xml. Don't forget also to change your.package.name.FixedBottomViewBehavior to your package name exactly.
Voila! That should work like a charm with proper toolbar animation and fixed view at the bottom.
In addition: if you don't know how to pass your OnClick event to your fragments you can follow this way in your Activity:
public interface OnConfirmOrderClickListener {
void onConfirmOrderClick(View v);
}
public Fragment getActiveFragment() {
String name = makeFragmentName(pager.getId(), pager.getCurrentItem());
return getSupportFragmentManager().findFragmentByTag(name);
}
public String makeFragmentName(int viewId, int index) {
return "android:switcher:" + viewId + ":" + index;
}
tvConfirmOrder.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment current = getActiveFragment();
if (current instanceof OnConfirmOrderClickListener)
((OnConfirmOrderClickListener) current).onConfirmOrderClick(v);
}
});
Don't forget to make your fragments implements OnConfirmOrderClickListener. Hope that helps!
For those who want the button to appear only in one fragment, it's possible to use onPageChangeListener of ViewPager to make the button scroll with the ViewPager
viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
updateButtonPosition(position, positionOffsetPixels);
}
});
//Move the button according to the tab you want it to be fixed.
//Here is the 3rd tab of a 3 tab viewPager, for instance
private void updateButtonPosition(int position, int positionOffsetPixels) {
int fixedRewardXPos;
if (position == 0) {
fixedRewardXPos = viewPager.getWidth() * 2 - positionOffsetPixels;
} else if (position == 1) {
fixedRewardXPos = viewPager.getWidth() - positionOffsetPixels;
} else {
fixedRewardXPos = -positionOffsetPixels;
}
//Add getLeft() to keep the button to its former position in it's fragment
aButton.setX(fixedRewardXPos + aButton.getLeft());
}

CardView contents not respecting match_parent

I am trying to create something very simple: a CardView that stretches to screen height and has a TextView inside it which should stretch to the card width. I have made the card fill the screen vertically with android:height="match_parent" on the CardView. However, now the CardView contents, like a simple TextView will not stretch across the whole card horizontally when setting android:height="match_parent" on the TextView. It just looks like wrap_content instead.
Note that this CardView is being placed inside a RecyclerView with a horizontal LinearLayoutManager.
Note that setting android:layout_width="match_parent" on the card does not actually stretch it out to the screen width when using a horizontal LinearLayoutManager, and the opposite is true if using a vertical LinearLayoutManager! I think this has something to do with my problem.
Here is the CardView xml:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/card_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="6dp"
card_view:contentPadding="8dp"
card_view:cardElevation="8dp"
card_view:cardCornerRadius="4dp"
card_view:cardUseCompatPadding="true" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/imageView_video_thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop" />
<TextView
android:id="#+id/textView_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:padding="2sp"
android:background="#80000000"
android:gravity="center"
android:textColor="#android:color/white"
android:textSize="16sp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<Button
android:id="#+id/textView_preview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:background="#80000000"
style="?android:attr/buttonBarButtonStyle"
android:text="Preview"/>
<Button
android:id="#+id/textView_set"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#80000000"
android:gravity="center"
style="?android:attr/buttonBarButtonStyle"
android:text="Set"/>
</LinearLayout>
</RelativeLayout>
Here is the RecyclerView xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:gravity="center"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/activity_wallpapers" tools:context=".WallpapersActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/cardList"
android:layout_width="match_parent"
android:layout_height="match_parent" />
I fixed this by placing the CardView inside a RelativeLayout as the outer-most layout:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
style="#style/CardLayout">
...
I guess you have problem with your inflater.
I had similar problem and changed my inflater from:
inflater.inflate(R.layout.services_card_list_item, null);
to this:
inflater.inflate(R.layout.services_card_list_item, parent, false);
This is working code. please try it.
public class MyRecyclerAdapter extends RecyclerView.Adapter<FeedListRowHolder> {
private List<FeedItem> feedItemList;
private Context mContext;
public MyRecyclerAdapter(Context context, List<FeedItem> feedItemList) {
this.feedItemList = feedItemList;
this.mContext = context;
}
#Override
public FeedListRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_row,viewGroup, false);
FeedListRowHolder mh = new FeedListRowHolder(v);
return mh;
}
#Override
public void onBindViewHolder(FeedListRowHolder feedListRowHolder, int i) {
// feedListRowHolder.title.setText("set data");
}
#Override
public int getItemCount() {
return 10;
}
}
OR
Replace with your code.
LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.card_listitem, viewGroup, false);
This was actually a bug in an early version of the RecylerView library. I forget exactly in which version it was fixed, but I think it was somewhere around support:recyclerview-v7:23.1.0 where it was fixed.

Categories

Resources