Fragments not fitting correctly in Tab Layout / ViewPager2 - android

I've tried a few different ways at getting this to work but the fragments I host inside of the ViewPager for a tab layout don't display correctly unless I position the components in the fragments oddly. Here's my fragment_tab xml and code is in Java:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="37dp" />
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF" />
</LinearLayout>
<Button
android:id="#+id/btnPost"
android:layout_width="147dp"
android:layout_height="47dp"
android:layout_marginBottom="16dp"
android:text="Post"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
And for instance in one of the fragments I host inside of it, the XML is this:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/swiperefresh"
android:layout_width="387dp"
android:layout_height="491dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="387dp"
android:layout_height="491dp"
android:layout_marginBottom="8dp">
</androidx.recyclerview.widget.RecyclerView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyle"
android:layout_width="96dp"
android:layout_height="103dp"
android:visibility="invisible"
android:layout_marginBottom="342dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
<TextView
android:id="#+id/txtViewEmpty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
and this is what the design view looks like below. This fragment is hosted inside of the view pager with the tabs, inside of another screen that has an action bar but the tabs is hosted within that one.
I've been testing on Android Studio using an emulator and then when I test on hardware the UI is all messed up, but also positioning the screens like above, ideally I'd like to be able to use the whole view for the recycler view without having to place it like that as it may look right on my emulator but not hardware device if I use match_parent or the whole screen. Any ideas? I tried coordinator layout and relative layout as well and couldn't get it exact, it's possible it was done incorrectly though.
Thanks all!!
Edit: Picture on the hardware device where its messed up, but looks fine on emulator in the odd position that view was created with:

Related

Draw a floating view on a recycler view item

I want to draw a floating view outside a recycler view item.
It's like a tooltip in excel, each cell will be an item, and some items will have that tooltip:
I tried to use
clipChildren="false"
but it's still covered by other items.
This is item layout:
<?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"
android:layout_width="50dp"
android:layout_height="50dp"
android:clipChildren="false"
android:orientation="vertical">
<View
android:id="#+id/box"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#f0f0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:layout_width="30dp"
android:layout_height="20dp"
android:background="#ff00"
android:translationX="10dp"
android:translationY="15dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
And this is activity layout with recycler view:
<?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="wrap_content"
android:clipChildren="false"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
This is my result:
And expected result is something like this:
Is there any way to archive this?
It looks like each RecyclerView item is partially overwriting the previous item. It is not clear to me how you got the first image (not the Excel image but the next one), but you can try setting the following attributes in the XML for the RecyclerView. The result is to write the items in the reverse order from what is normally done.
<androidx.recyclerview.widget.RecyclerView
...
android:clipChildren="false"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toTopOf="parent"
app:reverseLayout="true" />
You could also set these, or any combination of these, in code. I would play around with these values to see where it gets you.

Add animation for Changing Height of Layout

I have a small view, which at the beginning only contains a loading indicator, which is why it is relatively small. However, when the actual content is loaded, I would like to display that instead of the loading indicator, for which I add 2 text fields and an ImageView. Currently I just do this by hiding the ProgressBar and showing the elements I just mentioned, but this way there is a hard cut between the two states. I would like to change this so that first the height of the view is adjusted over a short period of time, and then the content is shown (maby faded in, but I'm more concerned about changing the height).
In general I already have some ideas how to do this, but I don't know how to calculate the new height? Is there a way to calculate it, or even a function directly from Android that solves my Problem?
Thanks already :)^
Heres the Layout for the Fragment:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/home_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".viewables.fragments.home.HomeFragment">
<ListView
android:id="#+id/home_vertretungsplan_preview"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="#layout/vertretungsplan_list_item"/>
<include
android:animateLayoutChanges="true"
android:layout_weight="0"
android:id="#+id/home_article_preview"
layout="#layout/thomsline_main_recyclerview_article"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp" />
</LinearLayout>
and here ist the Included Layout
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView
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"
android:animateLayoutChanges="true"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:clickable="true"
android:focusable="true"
app:cardElevation="10dp"
app:cardCornerRadius="20dp"
app:cardPreventCornerOverlap="false">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/thomsline_post_image"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_margin="0dp"
android:adjustViewBounds="true"
android:padding="0dp"
android:scaleType="centerCrop"
android:src="#drawable/img_thomsline_article_image_default"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp"
android:id="#+id/container1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/thomsline_post_image"
app:layout_constraintLeft_toLeftOf="parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="19sp"
android:id="#+id/thomsline_post_title"
tools:text="Article Title"/>
<TextView
android:id="#+id/thomsline_post_excerpt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:textAllCaps="false"
android:textSize="12.5sp"
tools:text="Post Excerpt" />
</LinearLayout>
<ProgressBar
android:id="#+id/thomsline_post_loading_indicator"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:visibility="gone"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
You can try using animateLayoutChanges attribute in your parent layout.
Add this line to your root element of your activity layout :
android:animateLayoutChanges="true"
Or you can use TransitionManager for smooth transitions. (API 19+)
Add this code to your file just before the line where you set your content :
TransitionManager.beginDelayedTransition(cardView); //Default transition
You can pass your preferred transition to this function like this :
Transition transition = new ChangeBounds();
TransitionManager.beginDelayedTransition(cardView,transition);
You can choose any transition :
ChangeBounds
Explode
Slide
Fade
AutoTransition
TransitionSet
If you want to know more about animations in android, i would suggest u read this : Simple Animations in Android

How to keep progressbar always below a recyclerView and not to be squeezed out of screen if there are too many items?

I am making a layout for showing scanned bluetooth device. Here is the layout:
<?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"
tools:context=".fragments.ScannedListFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view_scan_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/progressBar_scan_list"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:itemCount="12"
tools:listitem="#layout/list_item_scanned_list" />
<ProgressBar
android:id="#+id/progressBar_scan_list"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#id/recycler_view_scan_list"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
But when there are too many list items, the progressbar will be squeezed out of the screen. Just like this:
demonstration1
I want to keep the progressbar stick to the bottom of the recyclerView when the screen has enough space to show all content and the progressbar can be completely shown above the bottom of the screen without scrolling even if there are too many items in the recyclerView.
I tried vertically chaining two views and packed chain with bias but no luck. Also, I found that adding app:layout_constraintHeight_max="" for the recyclerView can achieve similar effect. But it seems not a general solution for different screen sizes.
Create a vertical chain by constraining the bottom of the ProgressBar to the parent, then set the chain style to packed so that both views stick together and then set the vertical bias to 0 to align them to the top of the parent. To prevent the RecyclerView from pushing the ProgressBar out of the screen set the app:layout_constrainedHeight="true" attribute for the RecyclerView - it enforces constraints when the height is set to wrap_content.
<?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"
tools:context=".fragments.ScannedListFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view_scan_list"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintVertical_bias="0"
app:layout_constrainedHeight="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/progressBar_scan_list"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:itemCount="12"
tools:listitem="#layout/list_item_scanned_list" />
<ProgressBar
android:id="#+id/progressBar_scan_list"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#id/recycler_view_scan_list"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?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"
tools:context=".fragments.ScannedListFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view_scan_list"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/progressBar_scan_list"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:itemCount="12"
tools:listitem="#layout/list_item_scanned_list" />
<ProgressBar
android:id="#+id/progressBar_scan_list"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
This way it will be always visible. Make the progress bar bottom constraint to parent and recycler view height 0dp

Constraints not centering views on phone

I'm having a weird bug. I really don't know why.
So, on the editor, my constraints work just as I want. But on the phone, they don't.
Pictures (I don't have enough reputation to show images..):
android studio
phone problem
Code:
<?xml version="1.0" encoding="utf-8"?>
<layout
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">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
tools:context=".fragments.home.HomeFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="some text"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView" />
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="some text"
app:layout_constraintBottom_toTopOf="#+id/textView2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</layout>
Thank you in advance!
Have you tried setting the ConstraintLayout height to "match_parent"?
It seems like you restrict it to the combined height of the TextViews.
Also, you shouldn't set BottomToTop and TopToBottom in such a way, one should depend on the parent. You can easily do it by selecting both views in the editor, right clicking the choosing Chain Vertically.
Never mind, just found the problem.
Both width and height need to be match_parent on the NavHostFragment in activity_main.xml.
<!-- navigation fragment -->
<androidx.fragment.app.FragmentContainerView
android:id="#+id/navHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:navGraph="#navigation/navigation"
android:layout_height="match_parent"
android:layout_width="match_parent" />

What is the correct way to implement multiple views on top of each other?

A bit of context: I am trying to implement a SearchView, when onQueryTextChange is called, it displays a ProgressBar, and when the query is done it hides the progress bar and displays another view depending on the outcome of the query. If the query returns nothing, it makes a textview visible saying "No Results" and if there is data, it populates the recyclerView.
My question is, what is the correct way of implementing this?
Do I stack them all on top of each other and make each one visible/invisible depending on the outcome of the query? Or do I use a viewflipper to display a fragment for no result and a fragment containing a recyclerview? Or lastly there is another way I do not know of?
This is what my search fragment looks like:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:background="#color/colorWhite">
<android.support.v7.widget.SearchView
android:id="#+id/fragsearch_searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:queryBackground="#android:color/transparent"
app:queryHint="Search"
app:iconifiedByDefault="false"
android:background="#color/backgroundColor"/>
<View
android:id="#+id/fragsearch_divider1"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#color/dividerColor"
android:layout_below="#+id/fragsearch_searchView"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/fragsearch_recycler"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorWhite"
android:layout_below="#+id/fragsearch_divider1"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/fragsearch_progress_layout"
android:background="#color/colorWhite"
android:visibility="invisible"
android:layout_below="#+id/fragsearch_divider1"
android:gravity="center">
<ProgressBar
android:id="#+id/fragsearch_progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<TextView
android:id="#+id/fragsearch_textview_noresults"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/fragsearch_divider1"
android:padding="12dp"
android:text="No Results Found"
android:visibility="invisible"/>
</RelativeLayout>
Right now I'm just stacking all of them on top of each other and changing the visibility on each one. Is there a better way of doing this?
I like to use a ViewFlipper for this. This way you can encapsulate the various view states in separate layouts and verify at design time that the correct layout is displayed. Much nicer than setting visibility on different Views.
<ViewFlipper>
<ViewGroup1>
</ViewGroup1>
<ViewGroup2>
</ViewGroup2>
</ViewFlipper>
To switch between the different children of a ViewFlipper call setDisplayedChild(index),
FrameLayout is used for this purpose.It is very useful for arranging views on top of each other.In your case replace RelativeLayout with FrameLayout.
I have done it using Constraintlayout considering searchview inside toolbar:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="#dimen/padding_8dp">
<ProgressBar
android:id="#+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:id="#+id/recycler_company_details"/>
<TextView
android:id="#+id/txt_empty_data"
android:text="No data available!!"
android:layout_width="wrap_content"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textColor="#android:color/holo_red_dark"
android:layout_height="wrap_content" />
</androidx.constraintlayout.widget.ConstraintLayout>
Consider using framelayout for this purpose, also we can easily set children layout gravity, it gets rendered perfectly. Relativelayout could also help, but we should avoid views termed as 'Legacy'.

Categories

Resources