im using this metod LINK for generated a recyclerview with GridLayoutManager to autospan columns but i fail to make a square dummy layout for holderview, My intention is to imitate a gallery using recyclerview,
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#color/white"
android:orientation="vertical"
android:padding="1dp">
<ImageView
android:id="#+id/txt"
android:layout_width="match_parent"
android:layout_height="100dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_gravity="center_horizontal|bottom"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true">
<TextView
android:id="#+id/card_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:ellipsize="end"
android:singleLine="true"
android:text="folder"
android:textSize="12dp"
android:textStyle="bold"/>
</FrameLayout>
Check out this answer, but basically you can create a custom SquareRelativeLayout and then override the onMeasure method so that it's always square like this:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Set a square layout.
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
Related
I need my Dialog width and height fill 70% of screen space. I'm using ConstraintLayout as root layout and tried to achieve this by using app:layout_constraintWidth_percent but it's not working.
It would be great to achieve this in XML without Java code.
Here is my code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#drawable/dialog_background_shape"
android:padding="#dimen/app_padding">
<TextView
android:id="#+id/textView13"
style="#style/text_plain3"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:text="#string/add_member_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/button_add_member_close"
style="#style/text_title2"
android:textStyle="bold"
android:layout_width="28dp"
android:layout_height="28dp"
android:background="#drawable/button_dialog_close"
android:gravity="center"
android:text="X"
android:textColor="#color/text_plain3"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/add_member_group_id"
style="#style/text_group_id"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="64dp"
android:layout_marginEnd="32dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView13" />
<TextView
android:id="#+id/textView17"
style="#style/text_card"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="#string/add_member_annotation"
app:layout_constraintStart_toStartOf="#+id/add_member_group_id"
app:layout_constraintTop_toBottomOf="#+id/add_member_group_id"/>
<EditText
android:id="#+id/add_member_user_id"
android:layout_width="248dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:ems="10"
android:hint="#string/add_member_hint_id"
android:importantForAutofill="no"
android:inputType="textPersonName"
android:maxLength="28"
app:layout_constraintEnd_toEndOf="#+id/add_member_group_id"
app:layout_constraintStart_toStartOf="#+id/add_member_group_id"
app:layout_constraintTop_toBottomOf="#+id/textView17" />
<Button
android:id="#+id/button_add_member"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="48dp"
android:layout_marginBottom="48dp"
android:text="#string/add_member_button_add"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="#+id/add_member_group_id"
app:layout_constraintStart_toStartOf="#+id/add_member_group_id"
app:layout_constraintTop_toBottomOf="#+id/add_member_user_id"/>
</androidx.constraintlayout.widget.ConstraintLayout>
In order to have a constraint width/height DialogFragment or (any specific width or height in general):
wrap your ConstraintLayout into another ConstraintLayout in order to make the outer take the full size of the screen, and the inner get the desired width/height percentage:
Make the android:background of the outer to be transparent
Constraint the width & height of the inner ConstraintLayout, make it centered in parent, and add the percentage constraint to the width & height:
app:layout_constraintHeight_percent="0.7"
app:layout_constraintWidth_percent="0.7"
Now the layout looks like:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/main_layout"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_gravity="center"
android:background="#drawable/dialog_background_shape"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.7"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.7"
android:padding="#dimen/app_padding">
<TextView
android:id="#+id/textView13"
style="#style/text_plain3"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:text="#string/add_member_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/button_add_member_close"
style="#style/text_title2"
android:textStyle="bold"
android:layout_width="28dp"
android:layout_height="28dp"
android:background="#drawable/button_dialog_close"
android:gravity="center"
android:text="X"
android:textColor="#color/text_plain3"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/add_member_group_id"
style="#style/text_group_id"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="64dp"
android:layout_marginEnd="32dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView13" />
<TextView
android:id="#+id/textView17"
style="#style/text_card"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="#string/add_member_annotation"
app:layout_constraintStart_toStartOf="#+id/add_member_group_id"
app:layout_constraintTop_toBottomOf="#+id/add_member_group_id" />
<EditText
android:id="#+id/add_member_user_id"
android:layout_width="248dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:ems="10"
android:hint="#string/add_member_hint_id"
android:importantForAutofill="no"
android:inputType="textPersonName"
android:maxLength="28"
app:layout_constraintEnd_toEndOf="#+id/add_member_group_id"
app:layout_constraintStart_toStartOf="#+id/add_member_group_id"
app:layout_constraintTop_toBottomOf="#+id/textView17" />
<Button
android:id="#+id/button_add_member"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="48dp"
android:layout_marginBottom="48dp"
android:text="#string/add_member_button_add"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="#+id/add_member_group_id"
app:layout_constraintStart_toStartOf="#+id/add_member_group_id"
app:layout_constraintTop_toBottomOf="#+id/add_member_user_id" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
In your custom DialogFragment:
Designate the width & height of the dialog to MATCH_PARENT:
dialog?.window?.setLayout(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT
)
Set no background the theme:
<style name="NoBackgroundDialogTheme" parent="Theme.AppCompat.Light.Dialog">
<item name="android:windowBackground">#null</item>
</style>
Custom Dialog Fragment:
Java:
public class MyDialogFragment extends DialogFragment {
#Nullable
#org.jetbrains.annotations.Nullable
#Override
public View onCreateView(#NonNull #NotNull LayoutInflater inflater, #Nullable #org.jetbrains.annotations.Nullable ViewGroup container, #Nullable #org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
return inflater.inflate(
R.layout.dialog_layout, container,
false
);
}
#Override
public int getTheme() {
return R.style.NoBackgroundDialogTheme;
}
#Override
public void onStart() {
// Making the dialog full screen
if (getDialog() != null)
getDialog().getWindow().setLayout(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT
);
super.onStart();
}
}
Kotlin:
class MyDialogFragment : DialogFragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(
R.layout.dialog_layout, container,
false
)
}
override fun getTheme(): Int = R.style.NoBackgroundDialogTheme
override fun onStart() {
super.onStart()
// Making the dialog full screen
dialog?.window?.setLayout(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT
)
}
}
Note: I am assuming that the dialog layout is R.layout.dialog_layout
UPDATE
now if I click on empty space around the Dialog, it doesn't close.
This is because the dialog fragment consumes the entire screen size; you can solve this by the below workaround:
Add an ID to the outer most ConstraintLayout, assume it is root >> Updated on the top layout
Add an ID to the inner ConstraintLayout, assume it is main_layout >> Updated on the top layout
Dismiss the dialog when the root is clicked
Do nothing when the main_layout is clicked to consume the event so that it won't be dismissed:
So, update the onStart() of the MyDialogFragment to:
override fun onStart() {
super.onStart()
// Making the dialog full screen
dialog?.window?.setLayout(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT
)
val root = requireView().findViewById<ConstraintLayout>(R.id.root)
root.setOnClickListener {
dismiss() // Dismiss the dialog
}
val main = requireView().findViewById<ConstraintLayout>(R.id.main_layout)
main.setOnClickListener {
// Consume the event
}
}
ConstraintLayout:
I see your "Dialog" Box contains a lot of different views. For that I made a simple example for you to show how to use Guideline for achieving percentages of Views.
I suggest to learn how this works and rebuild your layout with better constraining on this Guidelines, because now everything is wired up really bad. The idea will be to wire the ConstraintLayout to the Guideline and everything beside that (e.g. TextView etc.) to the ConstraintLayout. (Without Hardcoding!, that's how relative design work).
My example shows a TextView (could be your ConstraintLayout (frame for everything) that has exactly 70% (app:layout_constraintGuide_percent="0.7") vertically and horizontal of the screen. Important is to set the TextViews width and height to 0dp and to attach to the Guideline:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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">
<androidx.constraintlayout.widget.Guideline
android:id="#+id/vertical_guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.7" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/horizontal_guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.7" />
<TextView
android:id="#+id/textView"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#2962FF"
app:layout_constraintBottom_toTopOf="#+id/horizontal_guideline"
app:layout_constraintEnd_toStartOf="#+id/vertical_guideline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="TextView" />
</androidx.constraintlayout.widget.ConstraintLayout>
Result:
In addition same for LinearLayout:
You can use android:layout_weight="" to give a percent amount. So 70% means a weight of .70.
Keep in mind to set the width or/and height to 0dp
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:text="70 percent of screen"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".70" />
</LinearLayout>
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);
}
}
}
}
}
});
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 .
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.
I have a big issues about onSwiped method and set a button's visibility to VISIBLE. Here my code Java Class :
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
mRecyclerView.getAdapter();
StepListAdapter.ViewHolder listViewHolder = (StepListAdapter.ViewHolder) viewHolder;
listViewHolder.itemView.setBackgroundColor(mContext.getResources().getColor(R.color.accent));
listViewHolder.titleView.setVisibility(View.GONE);
listViewHolder.locationView.setVisibility(View.GONE);
listViewHolder.status.setVisibility(View.GONE);
listViewHolder.undoButton.setVisibility(View.VISIBLE);
listViewHolder.undoButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Do something
}
});
}
And here my xml layout file:
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/view"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5sp"
android:layout_marginRight="5sp"
android:clickable="true"
android:foreground="?selectableItemBackground"
card_view:cardCornerRadius="1sp"
card_view:cardElevation="2sp"
card_view:cardUseCompatPadding="true"
card_view:contentPadding="5sp">
<RelativeLayout
android:background="#color/cardview_light_background"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/title_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:singleLine="true"
android:ellipsize="end"
android:layout_gravity="center"
android:padding="5sp"
android:textStyle="bold"
android:textColor="#android:color/black"
android:text="#string/empty"/>
<TextView
android:id="#+id/location_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:ellipsize="end"
android:layout_gravity="center"
android:padding="5sp"
android:textColor="#color/dark_grey"
android:layout_below="#id/step_title_text"
android:text="#string/empty"/>
<ImageView
android:id="#+id/status_image"
android:layout_width="26dp"
android:layout_height="26dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"/>
<Button
android:id="#+id/undo_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/undo"
android:textAllCaps="true"
android:visibility="gone"
android:textColor="#android:color/white"
android:layout_gravity="end|center_vertical"
android:layout_alignParentRight="true"
style="#style/Base.Widget.AppCompat.Button.Borderless"
/>
</RelativeLayout>
</android.support.v7.widget.CardView>
My problem is that when the method onSwiped was called, and after I setup the VISIBILITY of the button by Java code, the main card doesn't show the button .
Thanks a lot guys