I have one main guideline, that's going to be programatically adjusted. To that, I attached 'anchor' that's supposed to always center on aforementioned guideline. Then, further view is going to be attached to the anchor.
The problem is - how can I also add constraint, that'll change horizontal bias, so that view attached do anchor is held within the screen?
Here's layout I've got that will not limit to screen bounds:
<?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/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<FrameLayout
android:id="#+id/frameLayout4"
android:layout_width="wrap_content"
android:layout_height="148dp"
app:layout_constraintEnd_toEndOf="#+id/frameLayout2"
app:layout_constraintStart_toStartOf="#+id/frameLayout2"
app:layout_constraintTop_toTopOf="#+id/frameLayout2">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="aasdasdasdadasdasda"
tools:text="asdasadasdasddddddddddd" />
</FrameLayout>
<FrameLayout
android:id="#+id/frameLayout2"
android:layout_width="90dp"
android:layout_height="90dp"
app:layout_constraintEnd_toStartOf="#+id/guideline"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="#+id/guideline"
tools:layout_editor_absoluteY="117dp">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Related
I have a layout like this:
My xml for that layout:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
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:fillViewport="true"
tools:context=".view.testviews.ProfileFragment"
android:background="#color/colorDarkGrey">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_marginStart="20dp"
android:layout_marginTop="100dp"
android:layout_marginEnd="20dp"
app:cardCornerRadius="16dp">
<FrameLayout
android:layout_gravity="center_horizontal"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="-50dp">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/profile_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:src="#drawable/user_image_placeholder"
app:civ_border_color="#FF000000"
app:civ_border_width="2dp">
</de.hdodenhof.circleimageview.CircleImageView>
</FrameLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
I'm trying to center the circleImageView on the edge of the cardView. But the top part of it is invisible. I looked up for similar questions, but they couldn't meet my requirements. How can I achieve this?
So I tried #PPartisan's solution, and it made it like this:
The code for that :
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
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:fillViewport="true"
tools:context=".view.testviews.ProfileFragment"
android:background="#color/colorDarkGrey">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:id="#+id/cardView2"
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_marginStart="20dp"
android:layout_marginTop="150dp"
android:layout_marginEnd="20dp"
app:cardCornerRadius="16dp">
</androidx.cardview.widget.CardView>
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/profile_image"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="90dp"
android:src="#drawable/user_image_placeholder"
app:civ_border_color="#FF000000"
app:civ_border_width="2dp"
>
</de.hdodenhof.circleimageview.CircleImageView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Don't make your ImageView a child of the CardView, as it will be clipped by its parent. Also, when considering XML, the drawing order is specified from top to bottom, which means that Views specified later in the XML will be drawn over any views that are specified earlier. This mean you should draw your CardView first, and then your CircleImageView. Your layout structure should therefore be:
<CardView.../>
<...CircleImageView.../>
I would also recommend you use CoordinatorLayout as it will be simpler to use features like guidelines to correctly align your various views.
Edit: Thankyou Adinia for pointing out in the comments that it is also necessary to set an elevation on the image to ensure it draws on top.
android:layout_gravity="center"
So your layout becomes:
<android.support.v7.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="80dp"
app:cardElevation="10dp"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="#drawable/titelbild280x280"
/>
</android.support.v7.widget.CardView>
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
I am working on my first android-project, a memory-game in Android Studio. The gameActivity-Frame should contain some textViews, displayed in one line (for stats) on the top of the screen and the memory-cards below. There are mutliple memory-versions, so the number of memory-cards vary - and by that the dimension of thier GridLayout.
My main Layout is a LinearLayout (vertical). I placed another LinearLayout (horizontal) on it, where the Textviews take place. To display the cards, I used a GridLayout which will be filled with cards once the game started.
The LinearLayout (with textViews) should always stick on the top of the screen. The GridLayout should be centered in the remaining space below.
What I get is that both Layouts either stick in the middle, or that the LinearLayout is correct, but the GridLayout is either on the bottom or on the top of the remaining space.
I tried to find a solution here on SO, and I think I tried every possible combination of the gravity- and layout_gravity - settings of the components. I can imagine the problem is that I can use either wrap_content or match_parent in the main Layout, but not both. Guess I'd need wrap_content to stick the first Layout to the top and match_parent to use the whole space below this Layout.
How can I stick the first Layout to the top and center the GridLayout in the remaining space?
The picture shows my current layout (see code below) and how I want it to look.
center_GridLayout
Edit to clarify:
The LinearLayout should stick to the top of the screen, the GridLayout should be
centered in the remaining space below the LinearLayout.
RelativeLayout won't do the job properly, because the layouts might overlap, depending on the amount of memory-cards and the user's device's dimensions.
I uploaded another screenshot where it's better visible what I want to achieve:
This is my .xml (deleted some unimportant textViews):
<?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/MemoryLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="20dp"
android:layout_marginTop="10dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="10dp"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:id="#+id/textStatsPairs"
android:layout_width="65dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/textStatsPairs" />
</LinearLayout>
<GridLayout
android:id="#+id/gridLayoutMainActivityTEST"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:columnCount="4"
android:foregroundGravity="center"
android:orientation="horizontal"
android:rowCount="4"
android:textAlignment="center"
android:useDefaultMargins="true"
tools:context=".GameActivity" />
</LinearLayout>
use relative layout or constraint 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/MemoryLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_alignParentTop="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="20dp"
android:layout_marginTop="10dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="10dp"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:id="#+id/textStatsPairs"
android:layout_width="65dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/textStatsPairs" />
</LinearLayout>
<GridLayout
android:layout_centerInParent="true"
android:id="#+id/gridLayoutMainActivityTEST"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:columnCount="4"
android:foregroundGravity="center"
android:orientation="horizontal"
android:rowCount="4"
android:textAlignment="center"
android:useDefaultMargins="true"
tools:context=".GameActivity" />
</RelativeLayout >
You can use relative layout along with linearlayout.From your question i got that you want your linearlayout always stick to top and GridLayout always stick to center.If this is the case then i think following code snippet will help you.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
</GridLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_alignParentTop="true">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Texts Here"
android:layout_gravity="center"
android:gravity="center"/>
</LinearLayout>
</RelativeLayout>
The ConstraintLayout was what fixed my problem... Here's the solution that finally works perfectly:
<?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/memory_activity_4x4"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/linearLayout_4x4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_gravity="center"
android:layout_marginLeft="20dp"
android:layout_marginTop="10dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="10dp"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:id="#+id/textStatsPairs"
android:layout_width="65dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/textStatsPairs" />
</LinearLayout>
<GridLayout
android:id="#+id/gridLayout4x4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:columnCount="4"
android:foregroundGravity="center"
android:orientation="horizontal"
android:rowCount="4"
android:textAlignment="center"
android:useDefaultMargins="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/linearLayout_4x4"
tools:context=".GameActivity" />
</androidx.constraintlayout.widget.ConstraintLayout>
I'm trying to create a layout of a list which starts on the bottom of a button and it's 3/4 of screen's width.
Just like this:
First, I used nested Linear layouts a horizonal and a vertical one, but then I read here that Constraint layouts are more responsive and I was impressed and gave it a try.
So, I tried to replace the outer layout to a constraint layout but now, I can't constraint the list to start at the bottom of the button and it starts at top of the screen.
I tried to see what would happen if I replaced the whole linear layout with a button just to see that the attributes are correctly implemented and it worked, so I understood that the Constraint layout does'nt effect the sons of the Linear layout although it should be effecting the whole layout (as I see it).
my code is the following:
<?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"
tools:context=".MainActivity">
<ImageButton
android:id="#+id/settings_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#FFFFFF"
android:src="#drawable/ic_menu_black_32dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<LinearLayout
android:id="#+id/list_linear_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#+id/settings_button"
app:layout_constraintTop_toBottomOf="#+id/settings_button">
<ListView
android:id="#+id/listview"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>
My current layout looks like this:
I really appriciate the helpers!
You need to change layout height of linear layout to 0dp, I will put here the layout for you. Also consider migrating to androidx :)
<?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">
<ImageButton
android:id="#+id/settings_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#FFFFFF"
android:src="#drawable/ic_menu_black_32dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<LinearLayout
android:id="#+id/list_linear_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:weightSum="4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/settings_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/settings_button">
<ListView
android:id="#+id/listview"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
I think, that using match_parent as width or height of child and adding any constraint is wrong here.
Edited xml (change margins if you want):
<?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"
tools:context=".MainActivity">
<ImageButton
android:id="#+id/settings_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="24dp"
android:layout_marginTop="24dp"
android:backgroundTint="#FFFFFF"
android:src="#drawable/ic_menu_black_32dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<LinearLayout
android:id="#+id/list_linear_layout"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="24dp"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="#+id/settings_button"
app:layout_constraintTop_toBottomOf="#+id/settings_button"
app:layout_constraintWidth_percent="0.75">
<ListView
android:id="#+id/listview"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"/>
</LinearLayout>
I would make a view that has 70% width and align to the right of its parent using constraint layout as follow
<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="wrap_content"
>
<android.support.constraint.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.3"/>
<TextView
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="Hello text"
app:layout_constraintLeft_toRightOf="#+id/guideline"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>
The TextView always occupy full parent width. Any idea what I'm doing wrong?
Two minor but important changes:
TextView width should be 0dp i.e. match constraint and not match parent
Guideline orientation should be vertical not horizontal
Here's the code:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.3" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Hello text"
app:layout_constraintLeft_toRightOf="#id/guideline"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>
Output:
Also note that I changed the ConstraintLayout height to match_parent so that the guideline was visible in the output. You can change it back to wrap_content.