I have a RecyclerView embedded within a ScrollView. Here is the complete layout:
<?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:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<fragment
android:name="devarshi.sample.view.ProductPortfolioFragment"
android:id="#+id/fragmentProductPortfolio"
android:layout_width="match_parent"
android:layout_margin="10dp"
android:layout_height="230dp" />
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:text="TextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/textViewProductName" />
<TextView
android:text="TextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/textViewProductDescription" />
<LinearLayout
android:id="#+id/linearLayoutProductDetails"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:text="#string/product_detail_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/textViewProductDetails" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:id="#+id/linearyLayoutOtherProductDetails"
android:layout_height="100dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_weight="0.6"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:id="#+id/linearLayoutPrice"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textViewProductPrice"
android:layout_width="wrap_content"
android:textSize="15sp"
android:textStyle="bold"
android:textColor="#color/colorDiscountedPrice"
android:layout_height="wrap_content"
android:text="1500"/>
<TextView
android:layout_marginLeft="5dp"
android:id="#+id/textViewOldProductPrice"
android:layout_width="wrap_content"
android:textSize="14sp"
android:textColor="#color/colorActualPrice"
android:layout_height="wrap_content"
android:text="200"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textViewQuantity"
android:layout_width="wrap_content"
android:textSize="15sp"
android:textStyle="bold"
android:textColor="#color/colorDiscountedPrice"
android:layout_height="wrap_content"
android:text="Quantity"/>
<TextView
android:layout_marginLeft="5dp"
android:id="#+id/textViewQuantityValue"
android:layout_width="wrap_content"
android:textSize="14sp"
android:textColor="#color/colorActualPrice"
android:layout_height="wrap_content"
android:text="200"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textViewBrand"
android:layout_width="wrap_content"
android:textSize="15sp"
android:textStyle="bold"
android:textColor="#color/colorDiscountedPrice"
android:layout_height="wrap_content"
android:text="Brand"/>
<TextView
android:layout_marginLeft="5dp"
android:id="#+id/textViewBrandValue"
android:layout_width="wrap_content"
android:textSize="14sp"
android:textColor="#color/colorActualPrice"
android:layout_height="wrap_content"
android:text="200"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_weight="0.4"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:id="#+id/linearLayoutFreeShipping"
android:layout_height="wrap_content">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="#drawable/product_detail_free_shipping_icon"
android:id="#+id/imageViewFreeShipping" />
<TextView
android:layout_marginLeft="5dp"
android:id="#+id/textViewFreeShipping"
android:layout_width="wrap_content"
android:textSize="14sp"
android:textColor="#color/colorActualPrice"
android:layout_height="wrap_content"
android:text="#string/product_detail_free_shipping"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:id="#+id/linearLayoutCashOnDelivery"
android:layout_height="wrap_content">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="#drawable/product_detail_cash_on_delivery_icon"
android:id="#+id/imageViewCashOnDelivery" />
<TextView
android:layout_marginLeft="5dp"
android:id="#+id/textViewCashOnDelivery"
android:layout_width="wrap_content"
android:textSize="14sp"
android:textColor="#color/colorActualPrice"
android:layout_height="wrap_content"
android:text="#string/product_detail_cash_on_delivery"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:id="#+id/linearLayoutUnit"
android:layout_height="wrap_content">
<TextView
android:layout_marginLeft="5dp"
android:id="#+id/textViewUnitLabel"
android:layout_width="wrap_content"
android:textSize="14sp"
android:textColor="#color/colorActualPrice"
android:layout_height="wrap_content"
android:text="#string/product_detail_unit"/>
<Button
android:text="-"
android:layout_width="#dimen/product_detail_counter_button_width"
android:layout_height="#dimen/product_detail_counter_button_height"
android:id="#+id/buttonDecrement" />
<TextView
android:id="#+id/textViewUnitValue"
android:layout_width="27dp"
android:textSize="14sp"
android:gravity="center"
android:textColor="#color/colorActualPrice"
android:layout_height="#dimen/product_detail_counter_button_height"
android:text="0"/>
<Button
android:text="+"
android:layout_width="#dimen/product_detail_counter_button_width"
android:layout_height="#dimen/product_detail_counter_button_height"
android:id="#+id/buttonIncrement" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerViewProductDetails"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
</ScrollView>
</LinearLayout>
Problem is -
Though I have set layout_height of RecyclerView as wrap_content its height is partially wrapping the content i.e. ideally after wrap_content its height should be 150dp but it is currently being 70dp.
Another interesting scenario is -
If I move linearyLayoutOtherProductDetails below recyclerViewProductDetails then it shows RecyclerView height accurately as 150dp. Seems like when the RecyclerView is loaded on the layout it is calculating height based on the number of items (within it) currently being visible on the layout i.e. the height is equal to 5 items in place of 9 items.
Any ideas on how can I have a RecyclerView of height completely wrapping its content in first scenario?
Note: I am using com.android.support:recyclerview-v7:25.0.0
Using RecyclerView inside a ScrollView is not a very good practice. You might consider keeping them all inside a NestedScrollView which might serve your purpose. Here's the documentation from developers android.
In your case, you might consider having the linearyLayoutOtherProductDetails as the header of your RecyclerView and this should be the best solution. Get rid of ScrollView or NestedScrollView and add the custom layouts as the header or footer of your RecyclerView.
Check my answer here about how you can add a header/footer in your RecyclerView.
I faced the same problem, and finally I found there maybe a bug in the measure logic of RecyclerView and LinearLayoutManager when using heightMeasureSpec of UNSPECIFIED mode and not zero size.
I have reported this bug to google issuetracker, you can see the details.
NestedScrollView may also lead to the same problem when it's child has not zero vertical margin, because it may pass heightMeasureSpec of UNSPECIFIED mode and not zero size to it's child, then the child may pass similar heightMeasureSpec to RecyclerView. Related code of NestedScrollView:
#Override
protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed,
int parentHeightMeasureSpec, int heightUsed) {
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
getPaddingLeft() + getPaddingRight() + lp.leftMargin + lp.rightMargin
+ widthUsed, lp.width);
final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
lp.topMargin + lp.bottomMargin, MeasureSpec.UNSPECIFIED);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
To fix this bug, you can simplly use the inherited RecyclerView below:
public class FixRecyclerView extends RecyclerView {
public FixRecyclerView(#NonNull Context context) {
super(context);
}
public FixRecyclerView(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
}
public FixRecyclerView(#NonNull Context context, #Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthSpec, int heightSpec) {
if (MeasureSpec.getMode(heightSpec) == MeasureSpec.UNSPECIFIED && MeasureSpec.getSize(heightSpec) != 0) {
super.onMeasure(widthSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
} else {
super.onMeasure(widthSpec, heightSpec);
}
}
}
Make linearlayoutOtherProductdetails header (first item) of recyclerview and remove scrollview. Because scrolling view inside another scrolling view does not work properly.
Another solution is use custom layout manager which set the height of recycler view equals to the height of its content. But this may result in poor scrolling .
Related
I want to achieve something not usual for a AppBarLayout + Recyclerview scrollingviewbehavior effect.
I want to make the recyclerview move with AppBarLayout and go behind AppBarLayout when user scrolls. I need it to be really behind AppBarlayout because the background of AppbarLayout will be half transparent so recyclerview will be visible.
I don't know how to do this.
I did try multiple variants of ScrollViewBehavior.
I did try also setting negative values to SwipeRefreshlayout topMaring and change this value during scroll. Values where provided from AppBarLayout.addOnOffsetChangedListener from given i "vertical scroll offset". The result was that the swipeRefreshLayout flickered during scroll and during going behind AppBarLayout.
Please help me with this. I have no more options left.
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="#+id/clRootMain"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="false"
android:background="#color/backgroundGray">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/srlSwipeRefresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
android:isScrollContainer="true"
app:layout_behavior=".Util.View.ScrollingViewOverlapBehavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:divider="#android:color/transparent"
android:dividerHeight="#dimen/dp5"
android:drawSelectorOnTop="true"
android:fadeScrollbars="true"
android:fadingEdge="none"
android:fadingEdgeLength="#dimen/dp0"
android:gravity="center"
android:isScrollContainer="true"
android:nestedScrollingEnabled="true"
android:overScrollMode="never"
android:paddingLeft="#dimen/list_margin"
android:paddingRight="#dimen/list_margin"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbarSize="#dimen/dp4"
android:scrollbarStyle="outsideOverlay"
android:scrollbars="vertical"
android:smoothScrollbar="false"
app:fastScrollEnabled="true"
app:fastScrollHorizontalThumbDrawable="#drawable/scrollbar_draggable"
app:fastScrollHorizontalTrackDrawable="#drawable/scrollbar_track_line"
app:fastScrollVerticalThumbDrawable="#drawable/scrollbar_draggable"
app:fastScrollVerticalTrackDrawable="#drawable/scrollbar_track_line" />
<TextView
android:id="#+id/tvEmptyListText"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="#dimen/dp20"
android:layout_marginTop="#dimen/dp10"
android:layout_marginRight="#dimen/dp20"
android:alpha="0.5"
android:gravity="center"
android:text="#string/category_product_list_empty"
android:textColor="#color/textGreyDark"
android:visibility="gone" />
</LinearLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/ablMain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#80ffffff"
android:fitsSystemWindows="true"
android:orientation="vertical"
app:liftOnScroll="false">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:orientation="vertical"
app:layout_scrollFlags="scroll|enterAlwaysCollapsed|exitUntilCollapsed">
<LinearLayout
android:id="#+id/llOpenOrderListContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:id="#+id/tvOpenOrdersTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/dp10"
android:layout_marginTop="#dimen/dp15"
android:alpha="0.6"
android:clickable="false"
android:gravity="center|left"
android:singleLine="true"
android:text="#string/current_orders_title"
android:textAllCaps="true"
android:textAppearance="#style/TextAppearance.AppCompat.Body2"
android:textColor="#color/textColor"
android:textSize="#dimen/sp10"
android:textStyle="normal" />
<androidx.viewpager.widget.ViewPager
android:id="#+id/vpOpenOrderList"
android:layout_width="match_parent"
android:layout_height="#dimen/dp75"
android:background="#android:color/transparent"
android:visibility="visible" />
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="#+id/rlTopContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#android:color/white"
app:layout_constraintDimensionRatio="H,16:9"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.viewpager.widget.ViewPager
android:id="#+id/vpBannerPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent" />
<RelativeLayout
android:id="#+id/rlControlContainer"
android:layout_width="#dimen/dp100"
android:layout_height="#dimen/dp30"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="#dimen/dp15"
android:background="#android:color/transparent">
<com.google.android.material.tabs.TabLayout
android:id="#+id/tlBannerDots"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
app:tabBackground="#drawable/tab_selector_images"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
app:tabMinWidth="#dimen/dp3"
app:tabMode="fixed" />
</RelativeLayout>
<ImageView
android:id="#+id/ivHalfCircleBackgroundWithStroke"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_marginTop="#dimen/dp50"
android:scaleType="fitXY"
app:srcCompat="#drawable/ic_bottom_arc"
/>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
<RelativeLayout
android:id="#+id/rlCategoryContainer"
android:layout_width="match_parent"
android:layout_height="#dimen/dp75"
android:background="#android:color/transparent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvCategoryList"
android:layout_width="wrap_content"
android:layout_height="#dimen/dp70"
android:layout_above="#+id/llSeparatorLine"
android:layout_centerHorizontal="true"
android:clipChildren="false"
android:divider="#android:color/white"
android:dividerHeight="#dimen/dp10"
android:drawSelectorOnTop="true"
android:fadeScrollbars="true"
android:fastScrollEnabled="false"
android:gravity="center"
android:isScrollContainer="true"
android:nestedScrollingEnabled="true"
android:overScrollMode="never"
android:scrollIndicators="none"
android:scrollbars="none" />
<LinearLayout
android:id="#+id/llSeparatorLine"
android:layout_width="match_parent"
android:layout_height="#dimen/dp1"
android:layout_alignParentBottom="true"
android:background="#drawable/grey_line_with_fading_edges_light"
android:orientation="horizontal" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/rlBottomDownArcContainer"
android:layout_width="match_parent"
android:layout_height="#dimen/dp40"
android:background="#android:color/transparent">
<TextView
android:id="#+id/tvSectionName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="#android:color/transparent"
android:clickable="false"
android:gravity="center_horizontal|top"
android:singleLine="true"
android:text="KWIATY"
android:textAllCaps="true"
android:textAppearance="#style/TextAppearance.AppCompat.Body1"
android:textColor="#color/textGrey"
android:textSize="#dimen/sp12"
android:textStyle="bold" />
</RelativeLayout>
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fabFilter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginLeft="#dimen/dp5"
android:layout_marginTop="#dimen/dp5"
android:layout_marginRight="#dimen/dp10"
android:layout_marginBottom="#dimen/dp10"
android:elevation="#dimen/dp4"
android:stateListAnimator="#animator/lift_on_touch"
android:visibility="visible"
app:backgroundTint="#android:color/white"
app:borderWidth="0dp"
app:elevation="4dp"
app:fabSize="normal"
app:rippleColor="#color/colorAccent"
app:srcCompat="#drawable/ic_icon_filtr_black" />
<!--</RelativeLayout>-->
</androidx.coordinatorlayout.widget.CoordinatorLayout>
public class ScrollingViewOverlapBehavior extends AppBarLayout.ScrollingViewBehavior {
public ScrollingViewOverlapBehavior() {
super();
}
public ScrollingViewOverlapBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child,
View dependency) {
super.onDependentViewChanged(parent, child, dependency);
child.setTranslationY(dependency.getY());
return false;
}
}
This is what I have achieved so far but it leaves space at the bottom. I am using setTranslationY on my custom ScrollingViewBehavior (ScrollingViewOverlapBehavior).
https://drive.google.com/open?id=12Ri87BGKmAmwNq_rC-wpmCcYZyansmGl
I am confused because in my RecyclerView, some items has their height = 0 (even when they are correctly displayed and visible) and some have their normal height.
How is that possible ?
If I monitor the height with addOnGlobalLayoutListener, 90% of item has their correct height calculated, and 10% still have 0.
Any idea of how android works for this ?
My code is in Kotlin but it doesn’t matter.
init {
var heightItemView = 0
var currentY = itemView.y
var oldY = currentY
itemView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
if (itemView.height > 0) {
heightItemView = itemView.height
itemView.viewTreeObserver.removeOnGlobalLayoutListener(this)
}
I also tried with measuredHeight().
My onCreateViewHolder() from the adapter:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PairMarketAdapter.ViewHolder {
val v = android.view.LayoutInflater.from(parent.context)
.inflate(R.layout.item_pair_market, parent, false)
val holder = PairMarketAdapter.ViewHolder(v)
holder.itemView.setOnClickListener {
listener.onItemAction(holder.adapterPosition)
}
return holder
}
XML of the fragment:
<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/lCoordinatorRoot"
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:orientation="vertical"
>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvPairMarket"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingTop="#dimen/spacing_normal"
tools:listitem="#layout/item_pair_market"
/>
</LinearLayout>
And the item XML:
<LinearLayout
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="wrap_content"
android:background="?selectableItemBackground"
android:paddingBottom="#dimen/spacing_normal"
android:paddingTop="#dimen/spacing_small"
android:paddingEnd="#dimen/spacing_normal"
android:paddingStart="#dimen/spacing_normal"
android:orientation="horizontal"
>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/spacing_small"
android:layout_weight="1.5"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:id="#+id/tvSymbol"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:textAllCaps="true"
android:textColor="?android:attr/textColorPrimary"
android:textSize="#dimen/font_large"
android:textStyle="bold"
tools:text="USD"
/>
<TextView
android:id="#+id/tvSymbolBase"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/spacing_tiny"
android:maxLines="1"
android:textAllCaps="true"
android:textColor="?android:attr/textColorSecondary"
android:textSize="#dimen/font_large"
android:textStyle="bold"
tools:text="BTC"
/>
<View
android:id="#+id/vIsSelected"
android:layout_width="10dp"
android:layout_height="10dp"
android:layout_gravity="center"
android:layout_marginStart="#dimen/spacing_small"
android:background="#drawable/circle_green_dot"
android:visibility="gone"
/>
</LinearLayout>
<TextView
android:id="#+id/tvExchange"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/spacing_tiny"
android:maxLines="1"
android:textColor="?android:attr/textColorSecondary"
android:textSize="#dimen/font_normal"
tools:text="1. Bitfinex"
/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
>
<TextView
android:id="#+id/tvPercent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:textColor="?android:attr/textColorPrimary"
android:textSize="#dimen/font_large"
tools:text="55.5%"
/>
</LinearLayout>
</LinearLayout>
itemView.measuredHeight android will try to measure your view before display try using itemView.height inside addOnGlobalLayoutListener
I'm using a recyclerview inside NestedScrollView and I want to pin my search bar to action bar after scrolling and recyclerview items must show under searchbar, I need to make lazy load for my recyclerview items (load next items from server after scrolling to end) for this I need to check recyclerview scroll change state and I can't do this perfectly when I use recyclerview inside nestedscrollview. I tried using nestedscrollview scroll state change listener and it doesn't give me what I want and doesn't work right.
Nested scroll view is not working if it's placed inside recyclerview. I have lazy load recyclerview but same layout contain other layouts like slider, menus then recyclerview. I want to scroll full layout and when recyclerview ends onscroll then onload execute to get more item from internet and load in recylerview.
Here you see my codes:
my layout xml code
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/main_activity_background">
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="200dp"
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:contentScrim="#color/colorPrimaryDark"
app:expandedTitleTextAppearance="#style/TextAppearance.AppCompat.Headline"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:titleEnabled="false">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="#drawable/bg_gradient"
android:orientation="vertical"
android:gravity="center_horizontal"
android:paddingBottom="5dp"
android:paddingLeft="#dimen/spacing_large"
android:paddingRight="#dimen/spacing_large"
android:paddingTop="#dimen/spacing_mxlarge">
<LinearLayout
android:id="#+id/layout_dots"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_gravity="center"
android:gravity="center"
android:orientation="horizontal" />
</RelativeLayout>
</RelativeLayout>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:contentInsetStartWithNavigation="0dp"
app:layout_collapseMode="pin"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
android:contentInsetLeft="0dp"
android:contentInsetStart="0dp"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
android:contentInsetRight="0dp"
android:contentInsetEnd="0dp"
app:contentInsetRight="0dp"
app:contentInsetEnd="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:focusable="true"
android:focusableInTouchMode="true"
android:background="#drawable/searchbox_stroke_bg"
android:orientation="horizontal">
<EditText
android:layout_width="0dp"
android:layout_weight="0.9"
android:layout_height="40dp"
android:hint="#string/search"
android:textDirection="locale"
android:textAlignment="viewStart"
android:drawablePadding="10dp"
android:layout_gravity="start"
android:paddingStart="15dp"
android:textColor="#color/searchbox_stroke"
android:maxLines="1"
android:singleLine="true"
android:maxLength="25"
android:textSize="17sp"
android:paddingEnd="5dp"
android:background="#android:color/transparent"
android:theme="#style/MainSearchEditTextTheme"
android:drawableStart="#drawable/ic_search"/>
<ImageView
android:layout_width="0dp"
android:layout_weight="0.1"
android:layout_height="16dp"
android:src="#drawable/ic_filter"
android:layout_gravity="center_vertical" />
</LinearLayout>
</android.support.v7.widget.Toolbar>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:id="#+id/main_nested_scrollView"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<RelativeLayout
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:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:scrollingCache="true"
android:nestedScrollingEnabled="false"
android:id="#+id/main_recyclerview"
android:layout_marginBottom="5dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/more_items_progress"
android:visibility="gone">
<ProgressBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/progress_bar"
android:indeterminate="true"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/lyt_progress"
android:layout_centerInParent="true"
android:layout_marginTop="100dp"
android:orientation="vertical">
<com.armanjafari.raimon.widget.ViewLoadingDotsBounce
android:layout_width="50dp"
android:layout_height="40dp"
android:layout_centerHorizontal="true"
android:background="#color/colorAccent">
</com.armanjafari.raimon.widget.ViewLoadingDotsBounce>
</LinearLayout>
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
My code to check scroll state and it didn't work
nested_content.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
#Override
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)
{
if (scrollY < oldScrollY)
{ // up
((MainActivity)getActivity()).animateNavigation(false);
}
if (scrollY > oldScrollY)
{ // down
((MainActivity)getActivity()).animateNavigation(true);
}
if (scrollY == ( v.getChildAt(0).getMeasuredHeight() - v.getMeasuredHeight() ))
{
if (!is_loading)
{
if (current_page < all_pages)
{
//not work right scroll state
}
}
}
}
});
i got the answer, if any one have my problem see below...
for detect nestedscrollview is at end correctly use this code:
nested_content.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
#Override
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)
{
if (scrollY < oldScrollY)
{ // up
((MainActivity)getActivity()).animateNavigation(false);
}
if (scrollY > oldScrollY)
{ // down
((MainActivity)getActivity()).animateNavigation(true);
}
View view = (View) nested_content.getChildAt(nested_content.getChildCount() - 1);
int diff = (view.getBottom() - (nested_content.getHeight() + nested_content
.getScrollY()));
if (diff == 0)
{
if (merchantList.size()>0)
{
if (!is_loading)
{
if(current_page<=all_pages)
{
// nestedscrollview at end
getMerchants(current_page);
}
}
}
}
}
});
This question already has answers here:
Dynamically changing the linearlayout width or height on Android
(4 answers)
Closed 4 years ago.
In my application I want set dynamically weight to LinearLayout and for this I write below codes, but when running application show me Force close error!
Force close message in logCat :
java.lang.ClassCastException: android.widget.LinearLayout$LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams
My XML codes :
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
tools:context=".activity.UpdateActivity">
<!--Header-->
<RelativeLayout
android:id="#+id/dialogEndCount_headerLay"
android:layout_width="match_parent"
android:layout_height="#dimen/size120"
android:background="#color/tabHomeColor">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginTop="#dimen/size40"
android:text="#string/updateDialogTitle"
android:textColor="#color/white"
android:textSize="#dimen/font16" />
<com.airbnb.lottie.LottieAnimationView
android:id="#+id/dialogUpdate_animate"
android:layout_width="#dimen/size150"
android:layout_height="#dimen/size150"
android:layout_alignParentLeft="true"
android:layout_centerInParent="true"
android:layout_marginLeft="#dimen/size20"
app:lottie_autoPlay="true"
app:lottie_colorFilter="#color/white"
app:lottie_fileName="update.json"
app:lottie_loop="true" />
</RelativeLayout>
<!--Content-->
<RelativeLayout
android:id="#+id/dialogEndCount_contentLay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/dialogEndCount_buttonsLay"
android:layout_below="#+id/dialogEndCount_headerLay"
android:layout_marginBottom="#dimen/size10"
android:layout_marginTop="#dimen/size10"
android:background="#drawable/bg_dialog_vip_white">
<!--Type-->
<TextView
android:id="#+id/dialogUpdate_infoTypeTxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginLeft="#dimen/size15"
android:layout_marginRight="#dimen/size15"
android:layout_marginTop="#dimen/size10"
android:gravity="center_vertical"
android:text="نوع بروز رسانی : اجباری"
android:textColor="#color/black"
android:textSize="#dimen/font14" />
<!--Content-->
<ScrollView
android:id="#+id/dialogUpdate_infoContentScrollLay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/dialogUpdate_downloadProgress"
android:layout_alignRight="#+id/dialogUpdate_infoTypeTxt"
android:layout_below="#+id/dialogUpdate_infoTypeTxt"
android:layout_marginLeft="#dimen/size15"
android:layout_marginTop="#dimen/size20">
<RelativeLayout
android:id="#+id/dialogUpdate_infoContentLay"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/dialogUpdate_infoContentTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:gravity="center_vertical"
android:text="#string/updateContent"
android:textColor="#color/black"
android:textSize="#dimen/font14" />
<TextView
android:id="#+id/dialogUpdate_infoContentTxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="#+id/dialogUpdate_infoContentTitle"
android:layout_marginTop="#dimen/size5"
android:gravity="center_vertical"
android:textColor="#color/favColorON"
android:textSize="#dimen/font14" />
</RelativeLayout>
</ScrollView>
<!--Download layout-->
<com.tellfa.colony.view.DownloadProgressView
android:id="#+id/dialogUpdate_downloadProgress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignRight="#+id/dialogUpdate_infoTypeTxt"
android:layout_marginLeft="#dimen/size15"
android:layout_marginTop="#dimen/size10" />
</RelativeLayout>
<!--Buttons-->
<LinearLayout
android:id="#+id/dialogEndCount_buttonsLay"
android:layout_width="match_parent"
android:layout_height="#dimen/size60"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:weightSum="3">
<!--Cancel-->
<android.support.v7.widget.CardView
android:id="#+id/dialogUpdate_cancelBtn"
android:layout_width="#dimen/margin_0dp"
android:layout_height="#dimen/size50"
android:layout_marginBottom="#dimen/size5"
android:layout_marginLeft="#dimen/size5"
android:layout_marginRight="#dimen/size5"
android:layout_marginTop="#dimen/size5"
android:layout_weight="1"
app:cardBackgroundColor="#color/red"
app:cardCornerRadius="#dimen/size3"
app:cardElevation="#dimen/size3">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="#+id/dialogUpdate_cancelBtnImg"
android:layout_width="#dimen/size25"
android:layout_height="#dimen/size25"
android:layout_centerVertical="true"
android:layout_marginLeft="#dimen/size5"
android:src="#drawable/ic_close"
android:tint="#color/white" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_toRightOf="#+id/dialogUpdate_cancelBtnImg"
android:ellipsize="end"
android:gravity="center"
android:singleLine="true"
android:text="#string/updateCancel"
android:textColor="#color/white"
android:textSize="#dimen/font14" />
</RelativeLayout>
</android.support.v7.widget.CardView>
<!--Direct-->
<android.support.v7.widget.CardView
android:id="#+id/dialogUpdate_directBtn"
android:layout_width="#dimen/margin_0dp"
android:layout_height="#dimen/size50"
android:layout_marginBottom="#dimen/size5"
android:layout_marginLeft="#dimen/size5"
android:layout_marginRight="#dimen/size5"
android:layout_marginTop="#dimen/size5"
android:layout_weight="1"
app:cardBackgroundColor="#color/green"
app:cardCornerRadius="#dimen/size3"
app:cardElevation="#dimen/size2">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="#+id/dialogUpdate_directBtnImg"
android:layout_width="#dimen/size25"
android:layout_height="#dimen/size25"
android:layout_centerVertical="true"
android:layout_marginLeft="#dimen/size5"
android:src="#drawable/appro_ic_download_circle"
android:tint="#color/white" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_toRightOf="#+id/dialogUpdate_directBtnImg"
android:ellipsize="end"
android:gravity="center"
android:layout_marginRight="#dimen/size1"
android:singleLine="true"
android:text="#string/updateOK"
android:textColor="#color/white"
android:textSize="#dimen/font12" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
</RelativeLayout>
My JAVA codes:
public class UpdateActivity extends BaseActivity {
#BindView(R.id.dialogEndCount_buttonsLay)
LinearLayout dialogEndCount_buttonsLay;
private Window window;
private Activity activity;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_update);
//Initialize
ButterKnife.bind(this);
activity = this;
window = activity.getWindow();
//Set color to statusBar
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.setStatusBarColor(getResources().getColor(R.color.tabHomeColor));
}
//Set dynamically weight
dialogEndCount_buttonsLay.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
}
}
How can I fix this problem?
If you want set dynamically weightSum just use this code :
dialogEndCount_buttonsLay.setWeightSum(3f);
i hope help you
You're mixing LinearLayout and RelativeLayout. Change your layout to use a LinearLayout then weight is an available property on your LayoutParams.
val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT)
params.weight = 1f
I can make the dynamic UI without problems, but I don't know how to access the view with findviewbyid (R.id._____) I don't know what to put in the blank.
.java code
public class newList extends AppCompatActivity {
Button btnAddItem;
RelativeLayout layout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_list);
// allows the creation of dynamic rows
btnAddItem = (Button) findViewById(R.id.addItem);
btnAddItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
LayoutInflater inflater = getLayoutInflater();
ViewGroup parent = (ViewGroup) findViewById(R.id.linearVert);
inflater.inflate(R.layout.rows, parent);
}
});
}
}
xml that is associated with the java file
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.app.shoppingbuddy.shoppingbuddy.newList">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="300dp"
android:id="#+id/scrollView" >
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:id="#+id/linearVert">
</LinearLayout>
</ScrollView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Subtotal"
android:id="#+id/subtotal"
android:textColor="#ffc800"
android:layout_above="#+id/tax"
android:layout_alignParentStart="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Tax"
android:id="#+id/tax"
android:textColor="#ee00ff"
android:layout_above="#+id/total"
android:layout_alignParentStart="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Total"
android:id="#+id/total"
android:textColor="#ff0000"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:layout_marginBottom="20dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="#+id/subtotalAmount"
android:layout_alignBottom="#+id/subtotal"
android:layout_alignEnd="#+id/scrollView"
android:textColor="#ffc800" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="#+id/taxAmount"
android:layout_above="#+id/total"
android:layout_alignParentEnd="true"
android:textColor="#ee00ff" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="#+id/totalAmount"
android:layout_alignBottom="#+id/total"
android:layout_alignEnd="#+id/taxAmount"
android:textColor="#ff0000" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add Item"
android:id="#+id/addItem"
android:layout_above="#+id/subtotal"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp" />
</RelativeLayout>
xml used to create rows
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:weightSum="1"
android:id="#+id/linearHor">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:id="#+id/itemImage"
android:src="#drawable/box"
android:padding="5dp" />
<EditText
android:layout_width="109dp"
android:layout_height="wrap_content"
android:id="#+id/itemName"
android:hint="Name"
android:layout_weight="0.78" />
<EditText
android:layout_width="100dp"
android:layout_height="wrap_content"
android:inputType="number"
android:ems="10"
android:id="#+id/itemPrice"
android:hint="$ Price" />
</LinearLayout>
</LinearLayout>
There will be no unique R.id value at the activity level. For example, suppose the user taps the button 10 times, so you inflate the R.layout.rows layout 10 times. As a result, there will be 10 R.id.linearHor widgets, 10 R.id.itemPrice widgets, and so on.
Always call findViewById() on something that is guaranteed to give you a unique result. In this case — as with ListView, GridView, RecyclerView, etc. — you need to use other approaches to find the correct row View, then call findViewById() on that View to get at its child widgets.