How to add horizontal scroll on vertical recyclerview? - java

So i have a recyclerview like this :
as you can see, the screen width is not enough for displaying all the text nicely, so i need to add horizontal scroll so user can scroll horizontally and vertically at the same time, how do i do this?

Use HorizontalScrollView with LinearLayout as child. Set it's Orientation to horizontal and add your dynamic views to it.
<?xml version="1.0" encoding="utf-8"?>
<HorizontalScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent">
<LinearLayout
android:id="#+id/ll_main"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="match_parent">
// Add your dynamic views to this layout.
</LinearLayout>
</HorizontalScrollView>

You can use this in your row layout :
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
//Your layout item here
</HorizontalScrollView>

You can add android:scrollHorizontally="true" in your TextView
If there are more than one view in your list item, you can use HorizontalScrollView

Put vertical RecyclerView inside HorizontalScrollView like below.
<HorizontalScrollView
android:fillViewport="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/tasks_recycler_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"/>
</HorizontalScrollView>
Also the root element of the item view for the RecyclerView has to have width wrap_content not match_parent, by setting it's width to wrap_content it allows it to expand the width of its parent which in this case would be the RecyclerView.
Now in the item view either give wrap_content or fixed widths to the inner views which in your case are the views to display "No", "Wonum", "Item num", "Quantity" and "UOM". By giving inner views fixed or wrap_content option they will expand automatically or according to the given width hence expanding their parent.

Try this
val linearLayoutManager = LinearLayoutManager(this)
linearLayoutManager.orientation = LinearLayoutManager.HORIZONTAL
selected_recycler_view.layoutManager = linearLayoutManager
adapter = TAdapter(this, existing.selectedArrayList)

Use this layout manager to allow horizontal scrolling of long items in a vertical LinearLayoutManager.
import android.content.Context;
import android.view.View;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class FullScrollLayoutManager extends LinearLayoutManager {
private int offset;
private int maxOffset;
public FullScrollLayoutManager(Context context) {
super(context);
}
#Override
public void onLayoutCompleted(RecyclerView.State state) {
super.onLayoutCompleted(state);
int n = getChildCount();
offset = 0;
maxOffset = 0;
int ownWidth = getWidth();
for(int i=0; i<n; ++i) {
View view = getChildAt(i);
int x = view.getRight();
if(x>ownWidth) maxOffset = Math.max(maxOffset,x-ownWidth);
}
}
#Override
public boolean canScrollHorizontally() {
return true;
}
#Override
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
if(dx<0) {
if(-dx>offset) dx = -offset;
}
else
if(dx>0) {
if(dx+offset>maxOffset) dx = maxOffset-offset;
}
offsetChildrenHorizontal(-dx);
offset += dx;
return dx;
}
}

Related

How to get programmatically the children of same type from linearlayout?

I have a linearlayout with many progressbars (horizontal progressbars).
I can add programmatically many progressbar to my linearlayout as I want.
But I would like to get a progressbar in a specific index.
for example: If I add 4 progressBar to my linearlayout.
And I want to get the second progressBar and set a progress and max progress just to the second progressbar in my linearlayout.
I tried to loop through all the children of linearlayout and get the child in a specific index what it doesn't work.
// add progressbar to linearlayout
linearLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
linearLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
linearLayout.removeAllViews();
int newWidth = linearLayout.getWidth() / 7;
int newHeight = linearLayout.getHeight();
while (i < 7) {
i++;
LinearLayout child = (LinearLayout) getLayoutInflater().
inflate(R.layout.stories_progress,
linearLayout,
false);
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
lp.width = newWidth;
lp.height = newHeight;
linearLayout.addView(child);
}
}
});
// get progressbar children of linearlayout at a specific index
int count = linearLayout.getChildCount();
View v = null;
for (int i=0; i<count; i++) {
// i want the progressbar in index 1 (the second)
v = linearLayout.getChildAt(1);
// this code produces a blank page in my app
ProgressBar pg = (ProgressBar) v;
pg.setProgress(20);
pg.setMax(100);
}
I'm triyng to achieve the same result as Instagram Stories, where when an user posted 4 images/videos, we see above the 4 progressbars and seeing the first video/image (at index 0) the progress settings is activated to start counting.
My stories progress:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5dp">
<ProgressBar
android:id="#+id/stories_progressBar_id"
style="#style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ProgressBar>
</LinearLayout>
My Activity layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/linear_layout_id"
android:layout_width="match_parent"
android:layout_height="30dp"
android:orientation="horizontal"
tools:context=".stories">
</LinearLayout>

How to resize RecyclerView when Material BottomSheet is Expanded?

I have a layout where i have a bottom sheet which could be expanded, then from that bottomsheet i can click some items which then will be added to my RecyclerView, the issue is that when the bottomsheet is expanded i'm unable to see the last added items as the recyclerView goes behind the bottomSheet.
So i would do something like the bottomSheet pushes to top the recyclerView (or that the recyclerView is resized)
The issue is that i was trying to do the resize in onSlide but it doesn't work as expected...
Here is my Layout:
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="2dp"
app:layout_anchorGravity="top"
android:layout_marginBottom="60dp"
app:layout_anchor="#+id/bottomSheet"
android:padding="2dp"
android:scrollbars="vertical"
tools:listitem="#layout/recyclerview_pterm" />
<include layout="#layout/bottom_sheet_pterm" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
And my BottomSheetBehavior callback:
bottomSheet.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_EXPANDED) {
mRecyclerViewTOP.scrollToPosition(dummyDataItems.size() - 1);
}
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
int padding = bottomSheet.getHeight();
ViewGroup.LayoutParams params= mRecyclerViewTOP.getLayoutParams();
params.height = params.height - padding;
mRecyclerViewTOP.setLayoutParams(params);
}
});
So how could i make the recyclerView shows ever the last inserted item even when bottomSheet is expanded?

Android making an scrolled two independent listview in activity

I am working in Android Studio in a new app and I want to create a layout with two independent scrolled listview (each listview scrolling in independent way) in the same activity. I cannot obtain the target that I want. Could you give me some advice?
I am not sure about efficient way but I worked in following way.
First, I have created two dynamic ListView and put in into one activity.
It will calculate the height dynamically rather than match_parent.
Here is the code:
public void setListViewDynamicHeight(ListView listView) {
ListAdapter adapter = listView.getAdapter();
if (adapter == null) {
return;
}
int height = 0;
int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(), View.MeasureSpec.UNSPECIFIED);
for (int i = 0; i < adapter.getCount(); i++) {
View listItem = adapter.getView(i, null, listView);
listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
height += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams layoutParams = listView.getLayoutParams();
layoutParams.height = height + (listView.getDividerHeight() * (adapter.getCount() - 1));
listView.setLayoutParams(layoutParams);
listView.requestLayout();
}
You can build it in your layout xml like this:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.widget.NestedScrollView
android:id="#+id/nested_scroll_view_1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hallo!" />
<!--Other views inside NestedScrollView-->
</android.support.v4.widget.NestedScrollView>
<android.support.v4.widget.NestedScrollView
android:id="#+id/nested_scroll_view_2"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hallo!" />
<!--Other views inside NestedScrollView-->
</android.support.v4.widget.NestedScrollView>
</LinearLayout>

Views are invisible after they was added into ViewGroup

I'm adding views programatically into FrameLayout:
public class PixelGridView extends FrameLayout {
...
public void addViewWithoutCoords(TableView view, int column, int row) {
float x = column * mCellSideSize;
float y = row * mCellSideSize;
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
view.setLayoutParams(lp);
view.setLeft(0);
view.setTop(0);
view.setX(x);
view.setY(y);
view.setVisibility(VISIBLE);
addView(view);
}
...
}
However, all they are somehow invisible. getChildCount() returns count with all of them. getVisibility() for each added view also returns VISIBLE.
I can drag'n'drop such views from another ViewGroup into my Framelayout and when I do this, all earlier added views become visible.
view layout file:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<ImageView
android:id="#+id/ivTable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
<EditText
android:id="#+id/ivTableName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="#color/style_table_grey"
android:textColor="#android:color/white"/>
</RelativeLayout>
Even If I add new view without drag everything become visible.
The item view of the FrameLayout and RelativeLayout can be overlapping. If two item views are in the same positions of FrameLayout, the first loaded item will be covered by the later item.
Try turn on the show layout bounds in developer option of your android devices,and find the position of your item.

Perfectly linear spacing between gridview items

I am using following code to show the GirdView items.
<GridView
android:id="#+id/gridView"
android:gravity="center_horizontal"
android:layout_below="#+id/searchLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:horizontalSpacing="10dp"
android:numColumns="3"
android:stretchMode="columnWidth"
android:verticalSpacing="10dp" />
Each GridItem (ImageView) is of size 92dp
What i want is to show only 3 Columns or 3 images each Row and each Top, bottom ,left right all needs to be perfectly aligned and equal.
Below is the result of above code.
It can be seen that spaces on left and right of the grid are very less as compared with the ones in between images and also between rows are very small.
Secondly, I am using 92dp. above is the result of S3, but when i use small screen the 3rd image doesn't get fit like in 320 dp screen.
Shouldn't using "dp" automatically adjust according to screen size?
I think this code will help you
try it :-
GridView
android:id="#+id/grid_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:numColumns="3"
android:gravity="center"
android:stretchMode="columnWidth"
android:background="#000000"/>
In xml of GridView
<GridView
android:id = "#+id/gridViewSms"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
android:numColumns = "3"
android:horizontalSpacing = "10dp"
android:verticalSpacing = "10dp"
android:gravity = "center"
android:stretchMode ="columnWidth">
In ImageAdapter.java
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
public class ImageAdapter extends BaseAdapter {
private Context mContext;
private int widthOfScrren;
public Integer[] mThumbIds;
// Constructor
public ImageAdapter(Context c,int ScrrenSize,Integer[] mThumbIds){
mContext = c;
widthOfScrren=ScrrenSize;
this.mThumbIds = mThumbIds;
}
#Override
public int getCount() {
return mThumbIds.length;
}
#Override
public Object getItem(int position) {
return mThumbIds[position];
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(mContext);
imageView.setImageResource(mThumbIds[position]);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setLayoutParams(new GridView.LayoutParams(widthOfScrren / 4,widthOfScrren / 4));
return imageView;
}
}
In Your Activity
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
public class MainActivity extends Activity{
private Integer[] mThumbIds = {
R.drawable.image1 ,
R.drawable.image2,
R.drawable.image3,
R.drawable.image4,
R.drawable.image5,
R.drawable.image6,
R.drawable.image7,
R.drawable.image8,
R.drawable.image9
};
#SuppressWarnings("deprecation")
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//found width of Screen for Gridview
WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
int densityX = display.getWidth();
GridView grid = (GridView) findViewById(R.id.gridViewSms);
grid.setAdapter(new ImageAdapter(getApplicationContext(), densityX, mThumbIds));
grid.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View v, int position ,
long id) {
}
});
}
}
I tested it. It works.
In the past, I have used a GridLayout instead of GridViewso that I can keep compatibility back to api v8.
for GridLayout, I wrote a nifty little function which is placed in the activity to dynamically stretch/space the items in the grid to fill the view evenly. I wrote about it here:
https://stackoverflow.com/a/15341447/2066079
I've also copied the code below for your convenience:
public void fillview(android.support.v7.widget.GridLayout gl)
{
Button buttontemp;
//Stretch buttons
int idealChildWidth = (int) ((gl.getWidth()-20*gl.getColumnCount())/gl.getColumnCount());
for( int i=0; i< gl.getChildCount();i++)
{
buttontemp = (Button) gl.getChildAt(i);
buttontemp.setWidth(idealChildWidth);
}
}
(The 20 is for the internal and external padding and margins. This could be done more universally, but this is far cleaner)
Then it can be called like this:
android.support.v7.widget.GridLayout gl = (android.support.v7.widget.GridLayout)findViewById(R.id.buttongrid);
ViewTreeObserver vto = gl.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {#Override public void onGlobalLayout()
{
android.support.v7.widget.GridLayout gl = (android.support.v7.widget.GridLayout) findViewById(R.id.buttongrid);
fillview(gl);
ViewTreeObserver obs = gl.getViewTreeObserver();
obs.removeGlobalOnLayoutListener(this);
}});
It must be done with an observer because we need to wait for the view to be drawn before we call the views.
Please try this code :
Grid.xml :
<GridView
android:id="#+id/photo_grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:numColumns="3" />
Your custom xml file for photo :
<ImageView
android:id="#+id/img_photo"
android:layout_width="#dimen/grid_photo"
android:layout_height="#dimen/grid_photo"
android:scaleType="fitXY"
android:layout_margin="5dp"
android:src="#drawable/ic_launcher" />
NOTE : Here i recommend to use different dimension for image size instead of fixed 92dp. So, by using dimens.xml you can get exact width and height for different resolution also with same space from all side in Gridview.
I have gone through the same problem a long time ago & get solved by
this:
You can do some change attributes as below in
Gridview:
<GridView
android:id="#+id/gridView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_below="#+id/rltop"
android:fadingEdge="none"
android:fitsSystemWindows="true"
android:gravity="center"
android:horizontalSpacing="10dp"
android:numColumns="3"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:soundEffectsEnabled="true"
android:stretchMode="columnWidth"
android:verticalSpacing="10dp" >
</GridView>
Get your Screen Size & Width by:
Display display= ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
myapp.screen_width = display.getWidth();
myapp.screen_height = display.getHeight();
And The Most Important thing:
In your GridAdapter class -> in getView() method:
call below method to target devices with different resolution:
public void screenResolutions(int screen_width,int screen_height, RelativeLayout relativeLayout)
{
if((myapp.screen_width == 240)&&(myapp.screen_height==320))
{
// relativeLayout.getLayoutParams().height=(myapp.screen_height-(35+General.getStatusBarHeight(cntxt)))/3;
relativeLayout.getLayoutParams().width=(myapp.screen_width)/3;
}
else if((myapp.screen_width== 720)&&(myapp.screen_height==1280))
{
// relativeLayout.getLayoutParams().height=(myapp.screen_height-(107+General.getStatusBarHeight(cntxt)))/3;
relativeLayout.getLayoutParams().width=(myapp.screen_width)/3;
}
else if((myapp.screen_width== 320)&&(myapp.screen_height==480))
{
// relativeLayout.getLayoutParams().height=(myapp.screen_height-(47+General.getStatusBarHeight(cntxt)))/3;
relativeLayout.getLayoutParams().width=(myapp.screen_width)/3;
}
else if((myapp.screen_width == 480)&&(myapp.screen_height==800))
{
// relativeLayout.getLayoutParams().height=(myapp.screen_height-(71+General.getStatusBarHeight(cntxt)))/3;
relativeLayout.getLayoutParams().width=(myapp.screen_width)/3;
}
else if((myapp.screen_width == 768)||(myapp.screen_height==1280))
{
// relativeLayout.getLayoutParams().height=(myapp.screen_height-(114+General.getStatusBarHeight(cntxt)))/3;
relativeLayout.getLayoutParams().width=(myapp.screen_width)/3;
}
else if((myapp.screen_width == 540)&&(myapp.screen_height==960))
{
// relativeLayout.getLayoutParams().height=(myapp.screen_height-(80+General.getStatusBarHeight(cntxt)))/3;
relativeLayout.getLayoutParams().width=(myapp.screen_width)/3;
}
else if((myapp.screen_width == 1080)||(myapp.screen_height==1920))
{
// relativeLayout.getLayoutParams().height=(myapp.screen_height-(160+General.getStatusBarHeight(cntxt)))/3;
relativeLayout.getLayoutParams().width=(myapp.screen_width)/3;
}
}
Where relativelayout = layout which consists ImageView.
You also have to change your height & width of imageview to target
multiple resolutions as below:
put this in your imageview:
android:layout_width="#dimen/image_width"
android:layout_height="#dimen/image_height"
Put this:
In values folder values-hdpi => dimens.xml(480x800)
<dimen name="image_width">92dp</dimen>
<dimen name="image_height">92dp</dimen>
In values folder values-mdpi => dimens.xml(320x480)
<dimen name="image_width">64dp</dimen>
<dimen name="image_height">64dp</dimen>
In values folder values-sw360dp-notlong-hdpi => dimens.xml(540x960)
<dimen name="image_width">114dp</dimen>
<dimen name="image_height">114dp</dimen>
In values folder values-sw360dp-xhdpi => dimens.xml(720x1280)
<dimen name="image_width">138dp</dimen>
<dimen name="image_height">138dp</dimen>
In values folder values-sw360dp-notlong-xhdpi => dimens.xml(768x1280)
<dimen name="image_width">184dp</dimen>
<dimen name="image_height">184dp</dimen>
Have you try default demo given by Developer site?
this demo clear shows all the images with equal height and width and with equal space around it.
Please also check this Example for GridView.
Please let me know if its not helping you.
Enjoy Coding... :)

Categories

Resources