Extra spaces in gridview inside recyclerview - android

Hallo i have some problem in gridviiew inside recyclerview, there is some spaces above grid item 2. like this pic. that spaces changes dinamicaly if i reload content inside recyclerview.
normal recyclerview
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView2"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
item cardview
<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:clickable="true"
android:clipChildren="true"
card_view:cardPreventCornerOverlap="false"
card_view:cardUseCompatPadding="false"
android:foreground="?attr/selectableItemBackground"
android:orientation="vertical">

found weird solution by add 2 dummy content and remove it (item 1 and 2) in recycler adapter onBindViewHolder solved my problem.
if (position == 1 || position == 0) {
// holder;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
0,
0
);
int margin = dpToPx(0);
params.setMargins(margin, margin, margin, margin);
holder.cardview2.setLayoutParams(params);
holder.cardview2.setVisibility(View.GONE);
} else {
so whats is the problem?

Related

How to center ImageView in GridLayout?

I have a full screen grid layout with 8 rows of 7 ImageView.
I need all the rows centered without spaces between them (now I have as result the image I uploaded). The space must be only on the top and on the bottom. I already tried to find a solution on the Internet but I haven't found one.
XML:
<?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"
tools:context=".MainActivity">
<GridLayout
android:id="#+id/gameGrid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:rowCount="8"
android:columnCount="7"
>
<!-- ROW 1-1 -->
<ImageView
android:layout_width="0dp"
android:layout_height="0dp"
android:id="#+id/cellR1-1"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
app:srcCompat="#drawable/dl"
/>
<!-- ROW 1-2 -->
<ImageView
android:layout_width="0dp"
android:layout_height="0dp"
android:id="#+id/cellR1-2"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
app:srcCompat="#drawable/dl"
/>
<!-- ROW ... -->
</GridLayout>
</RelativeLayout>
I tried as solution to set all the ImageViews height same as the width but my code didn't worked:
void setGrid(){
//setting the cell height as the cell widht
int imagWidth = cell[0][0].getLayoutParams().width;
for(int r=0;r<rowCount;r++)
for(int c=0;c<columnCount;c++) {
cell[r][c].getLayoutParams().height = imagWidth;
cell[r][c].requestLayout();
}
}
Image:
It might be helpful to you, use the RecyclerView instead of GridLayout
RecyclerView.LayoutManager recyclerViewLayoutManager = new GridLayoutManager(getApplicationContext(), 7); // 7 means how many column you want you can change according to your requirement.
recyclerView.setLayoutManager(recyclerViewLayoutManager);
Try using RecyclerView with GridLayoutManager like below:
GridLayoutManager layoutManager = new GridLayoutManager(getContext(), 7);
YourAdapter adapter = new YourAdapter();
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
int spacing = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16,
Objects.requireNonNull(getContext()).getResources().getDisplayMetrics());
recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
#Override
public void getItemOffsets(#NotNull Rect outRect, #NotNull View view, #NotNull RecyclerView parent, #NotNull RecyclerView.State state) {
if (parent.getChildAdapterPosition(view) == Objects.requireNonNull(parent.getAdapter()).getItemCount() - 1) {
outRect.bottom = spacing;
}
if (parent.getChildAdapterPosition(view) == 0) {
outRect.top = spacing;
}
}
});
Other solution is:
Instead of adding padding to both the top and bottom items, You can just add the padding to the top and bottom of your RecyclerView and set the clipToPadding attribute to false.
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingTop="8dp"
android:paddingBottom="8dp" />

Text jumps right to center when keyboard toggled

I have a RecycleView in which I visualize some text. The text is entered through an EditText view in the bottom. The RecycleView contains a TextView which is has the text centered.
I have also a function that detects if the keyboard is visualised. When the keyboard is visualised, then some layout parameters are changed so that the EditText looks good. I also have a smooth scroll to the last position of the RecycleView.
When I reopen the keyboard again, the text is first drawn to the left of the screen. If I swipe, the text is re-aligned to center. That is very disturbing and I always want the text to be centered. I probably miss something when changing the parameters of the layouts.
KeyBoard openedListener:
// Function to see of keyboard is opened or not.
private void detectKeyBoard(){
final ConstraintLayout rootView = findViewById(R.id.activity_root);
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
float heightDiff = rootView.getRootView().getHeight() - rootView.getChildAt(0).getHeight();
if (!isRefSet){
refDiff = heightDiff;
isRefSet = true;
}
if (heightDiff > refDiff) {
LinearLayout.LayoutParams params = new
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
0);
params.weight = wRSmall;
mRecyclerView.setLayoutParams(params);
LinearLayout.LayoutParams eParams = new
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
0);
eParams.weight = wESmall;
mLinearInput.setLayoutParams(eParams);
if (mAdapter.getItemCount() > 0) {
mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount() - 1);
}
} else {
LinearLayout.LayoutParams params = new
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
0);
params.weight = wRStart;
mRecyclerView.setLayoutParams(params);
LinearLayout.LayoutParams eParams = new
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
0);
eParams.weight = wEStart;
mLinearInput.setLayoutParams(eParams);
if (mAdapter.getItemCount() > 0) {
mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount() - 1);
}
}
}
});
}
xml for RecycleView:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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"
android:id="#+id/activity_root"
tools:context="com.example.erikbylow.autoflash.TranslateActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/translate_linear"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.9"
android:scrollbars="vertical"
android:layout_gravity="center_horizontal"
android:id="#+id/translate_recycle"
android:background="#android:color/holo_blue_bright" />
<LinearLayout
android:layout_width="match_parent"
android:id="#+id/linear_input"
android:layout_height="0dp"
android:layout_weight="0.1"
android:orientation="horizontal">
<EditText
android:layout_width="0dp"
android:layout_weight="0.75"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:singleLine="true"
android:id="#+id/source_input"
android:hint="Type text to translate"/>
<Button
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="0.25"
android:layout_alignRight="#+id/source_input"
android:text="Translate"
android:clickable="true"
android:onClick="startTranslate"
android:background="#android:color/holo_green_dark"/>
</LinearLayout>
</LinearLayout>
TextView for Adapter:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:textSize="#dimen/active_text_size"
android:id="#+id/adapter_textview"/>
After swiping it is re-aligned:
EDIT: It did not work to remove android:layout_gravity="center_horizontal" in the recycle xml part.
Further, if the screen is full without the keyboard being opened, the text is moved to the right:
Can you comment the detectKeyBoard() function? Just to check if the same problem exists or not?
Just a guess -
I see that you are creating a new LayoutParams object and assign it to your mRecyclerView and mLinearInput.
As far as I know, this new LayoutParam object will replace what you have set in XML, including layout_gravity, layout_weight, etc.
Try getting existing LayoutParams from mRecyclerView and mLinearInput, and modify their values instead.
Cannot advise much because I do not really understand the reason behind resetting layout params in your case.

How to scroll to a particular position in recyclerview inside scrollview?

I have searched a lot regarding my query and none of them was useful. I have a recyclerview and some static data inside a scroll view which is inside a root parentlayout as show below.
I have set -
scrollview.scrollto(0,0);
because everytime i open the activity it jumps to the recyclerview firstitem and it skips out the static data above the recyclerview.
recyclerview.setNestedScrollingEnabled(false);
recyclerview.setfocusable(false);
for smoothscroll.
the problem is with-
layoutmanager.scrollToPositionWithOffset(pos,0);
it is not working. I have set the aboveline after setting adapter to recyclerview. Also tried with NestedScrollView but in vain.
although I have used
layoutmanager.scrollToPosition(pos);
For those who skip the code, i have set match_parent to ScrollView and
fillviewport to true.
Here is my layout.
<?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:id="#+id/bottomsheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.inkdrops.khaalijeb.BrandCouponActivity">
<RelativeLayout
android:id="#+id/inclusionviewgroup"
android:layout_width="match_parent"
android:layout_height="match_parent">
<static data/>
<ScrollView
android:id="#+id/scrollviewmain"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/one"
android:fillViewport="true"
android:scrollbars="none"
android:layout_above="#+id/donelayout">
<staticdata/>
<TextView
android:id="#+id/dealstext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/card1"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:textSize="16sp"
android:text="Deals & Coupons"
android:textColor="#444444" />
<RelativeLayout
android:id="#+id/recyclerlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/dealstext"
android:layout_marginTop="5dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:background="#color/colorbackground">
<android.support.v7.widget.RecyclerView
android:id="#+id/coupon_rec_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorbackground"
android:visibility="visible"/>
</RelativeLayout>
<statisdata>
</RelativeLayout>
</ScrollView>
include layout="#layout/activity_coupons"
android:visibility="gone"
/>
</RelativeLayout>
</RelativeLayout>
Need to scroll ScrollView by getting top position of RecyclerView's child :
float y = recyclerView.getY() + recyclerView.getChildAt(selectedPosition).getY();
scrollView.smoothScrollTo(0, (int) y);
you can use scroll view method to reach your desired locations as:
scrollView.smoothScrollTo(int x, int y);
Step 1: Add this line for selecting that position in the recyclerview
adaptercat.setSelectedItem(Integer.parseInt(dealtypeid));
Step 2: Once check below constructor by getting current position
public CatgerotyAdapter(Context context, ArrayList<HashMap<String, String>> arraylist,String selectedPosition) {
this.context = context;
this.data = arraylist;
resultp = new HashMap<>();
currentItemPos=Integer.parseInt(selectedPosition)-1;
}
Step 3: And this function also in adapter
public void setCurrentItem(int item)
{
this.currentItemPos = item;
}
Last step 4. Add this function outside adapter in your class
private void onPagerItemClick2(Integer tag)
{
adaptercat.setCurrentItem(tag);
catsp.setAdapter(adaptercat);
}
Pust this line in your listview item click listner
((ClassName) context).onPagerItemClick2(position);
That position will be selected when will you open listview ..
Use this method scrollToPosition (int position) this is work for me. hope this will help you.
mMessagesRecyclerView = (RecyclerView) findViewById(R.id.messagesRecyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setStackFromEnd(true);
mMessagesRecyclerView.setLayoutManager(layoutManager);
mMessagesAdapter = new MessagesAdapter();
mMessagesRecyclerView.setAdapter(mMessagesAdapter);
mMessagesRecyclerView.scrollToPosition(your position);
this is my layoutstructer

How to center items of a recyclerview?

I need to center elements in each row so they will be like in this mockup.
I've been searching if there is any layout that works that way without look.
items are centered in their rows.
This is how it looks now in my code.
Make recyclerview width to wrap_content and its container's layout_gravity to center_horizontal
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycrer_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp" />
</LinearLayout>
Take LinearLayout in your RecyclerView's item row layout then give android:layout_gravity="center" to LinearLayout.
For each row of images you have to take different LinearLayout.
Here is example code:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
<ImageView
android:id="#+id/image1"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:src="#drawable/image1" />
<ImageView
android:id="#+id/image2"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:src="#drawable/image2" />
<ImageView
android:id="#+id/image3"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:src="#drawable/image3" />
</LinearLayout>
Achieved with:
recyclerView.adapter = MyAdapter()
val layoutManager = FlexboxLayoutManager(context).apply {
justifyContent = JustifyContent.CENTER
alignItems = AlignItems.CENTER
flexDirection = FlexDirection.ROW
flexWrap = FlexWrap.WRAP
}
recyclerView.layoutManager = layoutManager
You need to add FlexboxLayout to your gradle:
implementation 'com.google.android.flexbox:flexbox:3.0.0'
I am assuming that you are using a LinearLayoutManager with a RecyclerView for a ListView-style effect. In that case, use a horizontal LinearLayout for each row, with android:gravity="center" to center its contents.
Use FlexboxLayout from com.google.android:flexbox library. Note the flexwrap and justifyContent property values. Then, set layout_wrapBefore = true on the view that you want to wrap the line of items before.
<com.google.android.flexbox.FlexboxLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:flexWrap="wrap"
app:justifyContent="center">
<View ... />
<View app:layout_wrapBefore="true" ... />
<View ... />
</com.google.android.flexbox.FlexboxLayout>
Use the gridLayoutManager = new GridLayoutManager(context,6) and override setSpanSizeLookup.
Example:
int totalSize=list.size();
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
int span;
span = totalSize % 3;
if (totalSize < 3) {
return 6;
} else if (span == 0 || (position <= ((totalSize - 1) - span))) {
return 2;
} else if (span == 1) {
return 6;
} else {
return 3;
}
}
});
This will work if you want to display 3 items in a row and remaining in the center of the grid.
Change the grid layout manager span counts accordingly your requirement.
you can use the new layoutManager from google FlexLayoutManager
it will gives you a lot of control and flexibility over the recyclerView items
you can add some layouts dynamically, for example:
adapter object can be a horizontal LinearLayout
1- create a LinearLayout in java code and customize it (gravity,...)
2- add some icons to linearLayout
3- add linearLayout to your adapter
4- repeat 1,2,3
// : declare new horizontal linearLayout
ImageView myIcons[nomOfIcons];
// : add all icons to myIcons
for(int i=1; i<=nomOfIcons; i++){
linearLayout.addView(myIcons[i - 1]);
if(i%numOfIconsInOneHorizontalLinearLayout==0) {
results.add(linearLayout); // add linearLayout to adapter dataSet
// : declare new horizontal linearLayout
}
}
if(n%numOfIconsInOneHorizontalLinearLayout!=0) // add last linearLayout if not added in the loop
results.add(linearLayout);
mAdapter.notifyDataSetChanged(); // update adapter
Currently, I think we need to write our own custom view for it because Android has not supported this feature as we expected yet.
It is the Sample I made in case someone needs it:
https://github.com/mttdat/utils
(Try the CenterGridActivity.kt by adjusting Manifest file to start this activity as default)
Trust me, this gonna work.
In your main xml file where you've put the recycler view, copy my code.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="#dimen/_50sdp"
android:gravity="center">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="wrap_content"
android:layout_height="#dimen/_50sdp"/>
</LinearLayout>

Keeping an image "pinned" when scrolling

I am trying to create the effect seen on this webpage for example
http://www.soyuzcoffee.com/ru/home
the part where as you scroll it appears as the main content is scrolling over the big images (images that act as dividers between sections)
I am very close but if the image is smaller that the height of the view (image does not fill the entire screen) the image scrolls up like it normally would until it hits the top. I am trying to make it look like the image is stationary and the frame is moving over it.
here is my layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.pinnedscrollview.CustomScrollView
android:id="#+id/scroller"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.pinnedscrollview.PinnedImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.pinnedscrollview.PinnedImageView
android:id="#+id/image2"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.pinnedscrollview.PinnedImageView
android:id="#+id/image3"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.pinnedscrollview.PinnedImageView
android:id="#+id/image4"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
</LinearLayout>
</com.example.pinnedscrollview.CustomScrollView>
</RelativeLayout>
Then I have an onScrollChangedListener that runs this method everytime the scroll position changes
private void handleScroll(ViewGroup source, int top) {
ViewGroup container = (ViewGroup) source.findViewById(R.id.container);
final int count = container.getChildCount();
for (int i = 0; i < count; i++) {
View item = container.getChildAt(i);
View v = null;
if(i == 0){
v = item.findViewById(R.id.image);
}else if(i == 1){
v = item.findViewById(R.id.image2);
}else if(i == 2){
v = item.findViewById(R.id.image3);
}else if(i == 3){
v = item.findViewById(R.id.image4);
}
source.getHitRect(mTempRect);
if (v != null && v.getLocalVisibleRect(mTempRect)) {
((PinnedImageView) v).reveal(source, item.getBottom(),item.getTop());
}
}
}
Then this is the reveal method that just sets the Translation in the Y direction
public void reveal(View scroller,int parentBottom,int parentTop) {
float previousOffset = mOffsetY;
if(parentTop - scroller.getScrollY() < 0){
mOffsetY= Math.abs(parentTop - scroller.getScrollY());
}else{
mOffsetY = Math.min(0, scroller.getHeight() - (parentBottom - scroller.getScrollY()));
}
if (previousOffset != mOffsetY) {
setTranslationY(mOffsetY);
}
}
I am not sure if I need to do something with the Matrix of the image in the onDraw and redraw the bitmap or not.
Any ideas or other ways that I can accomplish something similar to that website?
I would set the desired image as a background image of a containing layout. Then set appropriate transparencies and place the scrollable view as a child of the parent layout that contains the image. You may even be able to set the background of the scrollable view itself.
You then may be able to use conditionals etc to adjust the frame of the background image and swap images based on the scroll position.
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:layout_marginTop="48dp"
android:background="#drawable/tmf_background"
>
<ImageView
android:src="#drawable/the_lineup_header"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="16.5dp"
android:contentDescription="#string/noDescription" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#drawable/tmf_sub_header" >
<TextView... />
<Button ... />
<Button... />
<Button ... />
<TextView ... />
</LinearLayout>
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="#drawable/tmf_divider"
android:background="#android:color/transparent" >
</ListView>
</LinearLayout>
Here is a chunk of the xml for the free app I did for True Music Festival for it's first year.
https://play.google.com/store/apps/details?id=com.fyresite.truemusicapp
There we have a single background image that stays static while the content scrolls over it. Combining that with your scroll position listener you should be able to, at the very least, change the background image as you scroll. You could then try transforming the background image to get that scrolling effect on the site.
You may find this question to be useful Android: Moving background image while navigating through Views

Categories

Resources