So I'm working on creating a dialog fragment to allow user to choose from some options. I have a pretty simple layout inside a constraint layout. TextView on top, recycler view, then two buttons at the bottom.
The problem is, I want the recyclerview to be wrap content, so that if there aren't a lot of options, the dialog will shrink down. However, if there are a lot of options, i'd like it to expand but then start scrolling so all views are visible on the screen.
I can't seem to get past the situation where either it constantly is large. Or if I just allow wrap content, the dialog will grow so large the bottom buttons are missing.
I'm assuming it has something to do with some particular constraint options, but I can't figure out the combination. Any ideas?
EDIT: I know an easy answer is to set a max height on the recycler view. I'm hoping to do that same thing but with constraints, so its not a fixed hard height.
EDIT2: It looks like the constraints will work nicely with wrap as default if the view model's height is fixed. I really can't deal with a fixed height view model though...
Thanks
Create a customRecyclerView that override onMeasure method.
public class CustomRecyclerView extends RecyclerView{
public CustomRecyclerView (Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomRecyclerView (Context context) {
super(context);
}
public CustomRecyclerView (Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
you can call the recyclerview like this
<com.example.yourpackage.CustomRecyclerView>
Related
I am trying to implement a ChipGroup with some chip items inside it. Which works fine so far. But My requirement is to show these items inside the ChipGroup with certain number of rows. As example: I have 20 items as chip inside my group, And only 6/7 items fits in between the 2 lines. So, I want to show the chips which fit into the ChipGroup between 2 lines only.
Currently I am getting this (sample) output:
And my expectation is like below:
Additional queries:
Is it possible to get the current row count of chip items from the
ChipGroup? If yes how?
Can I set the maximum visible rows for the ChipGroup
programatically?
I use customer view to make this feature.
public class AppChipGroup extends ChipGroup {
private static final int[] MAX_HEIGHT_ATTRS = {android.R.attr.maxHeight};
private int mMaxHeight = Integer.MAX_VALUE;
public AppChipGroup(Context context) {
super(context);
}
public AppChipGroup(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public AppChipGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = context.obtainStyledAttributes(attrs, MAX_HEIGHT_ATTRS);
mMaxHeight = typedArray.getDimensionPixelSize(0, Integer.MAX_VALUE);
typedArray.recycle();
}
#SuppressLint("RestrictedApi")
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int height = Math.min(getMeasuredHeight(), mMaxHeight);
setMeasuredDimension(getMeasuredWidth(), height);
}
}
then when use ChipGroup, set the maxHeight value.
<packagename.chip.AppChipGroup
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"
style="#style/Widget.MaterialComponents.ChipGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxHeight="#dimen/search_input_history_max_height"
app:chipSpacing="#dimen/search_input_history_chip_space" />
Or you can get the chip height and calculate the max_height in onMeasure method and set the measure dimension.
ExtendedChipGroup
U can set max lines and show/hide button
For this I created a class and inherited it from ChipGroup, next rewrote the onLayout method so that all elements that are after the visible line are hidden
<io.github.tiarait.extendedchipgroup.ExtendedChipGroup
android:id="#+id/chip_group"
app:maxRow="2"
app:itemSpacing="6dp"
app:additionalTextColor="#eee"
app:additionalChipColor="#color/colorDarkBtn"
app:additionalChipColorPressed="#color/colorDarkBtnSecondary"
app:additionalChipMore="#string/btn_show"
app:additionalChipHide="#string/btn_hide"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
The question is a bit weird. I have a GridLayoutmanager linked with a Recyclerview, this Grid has two 5 rows, and 2 columns, every second row has the size of 2 columns.
CELL1-CELL2
C E L L 3
CELL4-CELL5
The second row, has a cell with a size of two cells. This step, i have done it without any issues, now to my request.
I have a square Linearlayout, with the following code:
public class SquareLinearLayout extends LinearLayout {
public SquareLinearLayout(Context context) {
super(context);
}
public SquareLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareLinearLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//noinspection SuspiciousNameCombination
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}
I have applied this layout to the Grid's items, so every cell has a perfect width and height EXCEPT for the 3rd cell, because it has the size of two cells. Here's my problem, i want it to take the space of two cells, but not the size of two cells.
So I've done a naught trick to do it. I've created two custom views, one for the LinearLayout and one for the ImageView. in the LinearLayout, I've saved the widthMeasureSpec in a static constant in another class called Constants, and added a boolean to only save the value one time.
in the ImageView, i took that value from Constants and applied it to the ImageView's onMeasure.
A bit tricky, but did the work. 2 Cell space, but one cell size and most important, in the center.
I want to create an Excel type layout where there is infinite scroll vertically. There are fixed number of columns horizontally, but they should be scrollable.
I tried the below code
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<android.support.v7.widget.RecyclerView
android:id="#+id/table_data_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</HorizontalScrollView>
If I used the above code, then I am able to scroll vertically, but the columns are not scrollable.
Even giving fixed height in the xml for HorizontalScrollView and RecyclerView, the columns do not scroll.
Finally, I found an answer here, where it was advised to extend the RecyclerView and calculate the height dynamically.
public class MySmartRecyclerView extends RecyclerView {
public MySmartRecyclerView(Context context) {
super(context);
}
public MySmartRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MySmartRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public boolean canScrollHorizontally(int direction) {
return false;
}
#Override
public int getMinimumWidth() {
return computedWidth;
}
#Override
protected void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec, heightSpec);
setMeasuredDimension(computedWidth, getMeasuredHeight());
}
#Override
protected int getSuggestedMinimumWidth() {
return computedWidth;
}
}
So is this the only way, this can be achieved? Or is there any other way to achieve this. For RecyclerView inside ScrollView there is NestedScrollView, but no such thing for HorizontalScrollView.
Any pointers will be appreciated. TIA.
There is one alternate solution. You can use this library.
You want to do Ehhhh? Like the guy said, use library. You need and have normal easy to use solutions.
EDIT:
Okay my bad.
You want to infinite scroll vertically, not excel. I'm back from excel topic:
at onScroll listener, you should incriment endlessly the totalItemCount, you do it with double recurssion. From within the function of listener, you call to another listner whereas you call it by a function in the middle, which also increments that number before calling to the same listener again. You simply edit the view and re-attach the listener.
I have one imageView and I am trying to give it minus margin top as much as its height / 2. I can do it at programmatically but i wondred is it possible at xml also andorid published percentrelative layout . I don't know how to to do it or possible?
--Edit: As #aga suggests, there seems to be a way to achieve it via the Percent Support Library--
If you want to use this type of imageView more often throughout your application you could extend imageview and put your margin-code inside of it's onMeasure:
public class HalfMarginImageView extends ImageView {
public HalfMarginImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
((ViewGroup.MarginLayoutParams) getLayoutParams()).topMargin = -getMeasuredHeight() / 2;
}
}
for this to work the view must be part of a ViewGroup.Also make sure you use the constructor with AttributeSet, oltherwise you can't create the View from xml. Yo then just include a CustomView in your layout xml, select HalfMarginImageView and use it as normal imageView.
I have a custom Button and I want to set its dimensions in code (as opposed to in xml), so that users can customize the dimensions. The seemingly obvious way to this is:
public class MyButton extends Button
{
public MyButton(Context context, AttributeSet attrs)
{
super(context, attrs);
int buttonSize = getSize();
setLayoutParams(new LinearLayout.LayoutParams(buttonSize, buttonSize));
}
However, this fails to be generic because it only works if the Button's parent is a LinearLayout. Instead, I tried this:
#Override
protected void onMeasure(int specw, int spech)
{
int spec = MeasureSpec.makeMeasureSpec(getButtonSize()), MeasureSpec.EXACTLY);
super.onMeasure(spec, spec);
}
...which seems to work well. Is anyone aware of any shortcomings to this? or aware of a better way to generically set widget dimensions in code?
Doing it from onMeasure() is a good way to do it (even though your code doesn't work since you're not using the measure spec you've created.) You could also override onFinishInflate() and call getLayoutParams() and change the width and height fields.