I am creating app in which there is screen with searchBar by this lib.
My activity layout looks like this:
<?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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.ConstraintLayout
android:id="#+id/wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true">
<TextView
android:id="#+id/title"
android:textColor="#color/colorPrimary"
android:text="#string/mainScreenTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAlignment="center"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:paddingTop="100dp"/>
<com.arlib.floatingsearchview.FloatingSearchView
android:id="#+id/searchView"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginTop="100dp"
android:animateLayoutChanges="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/title"/>
</android.support.constraint.ConstraintLayout>
</RelativeLayout>
There i have to move FloatingSearchingView to top of screen and change height to for example 500dp - like this:
app:layout_constraintTop_toTopOf="parent"
android:layout_height="500dp"
And later i will have to move it back and change height again to default value
app:layout_constraintTop_toBottomOf="#+id/title"
android:layout_height="50dp"
The problem is, i have to animate it. I have spent a lot of time searching for solution but unfortunately i didnt find anything.
I had to animate the TextView height inside a ConstraintLayout.
<androidx.constraintlayout.widget.ConstraintLayout
...
android:animateLayoutChanges="true"
>
<TextView
...
I first informed the ConstraintLayout that the layout was about to change:
constraintlayout.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
and then updated the textView height (or whatever other param)
textView.getLayoutParams().height = 200;
textView.requestLayout();
for something simple as that, no need to set animators or involve other libraries.
#beeb's version didn't work for me either, unfortunately. Although the question is old, here is a solution that worked for me, using the TransitionManager. It's a bit "redundant", as you have to duplicate some code, but therefor very easy and includes only two basic steps:
Create two layout.xml files. One for each state (before/after animation).
If your constraint layout is one of multiple children of a parent layout, you can create two files containing only this constraint layout and include the version you wan't at app-start via <include #layout=""/>, where previously you constraint layout has been. That way, you don't have to duplicate the entire layout file. This however caused the findViewById() method to return null, when my include element had an id. So be careful with this.
In your case this would be e.g.: floating_searching_view_at_bottom.xml:
<com.arlib.floatingsearchview.FloatingSearchView
android:id="#+id/searchView"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginTop="100dp"
android:animateLayoutChanges="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/title"
android:layout_height="50dp" />
and floating_searching_view_at_top.xml:
<com.arlib.floatingsearchview.FloatingSearchView
android:id="#+id/searchView"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginTop="100dp"
android:animateLayoutChanges="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/title"
android:layout_height="50dp"
app:layout_constraintTop_toTopOf="parent"
android:layout_height="500dp" />
Animate the transition between these layout files using TransitionManager:
boolean toggle = false // you should give this guy a more descriptive name!
Context context = this; // in scope of the activity.
public void animateTransition() {
// Load ConstraintSets from the two layouts
ConstraintSet atBottom = new ConstraintSet();
ConstraintSet atTop = new ConstraintSet();
atBottom.clone(context, R.layout.floating_searching_view_at_bottom);
atTop.clone(context, R.layout.floating_searching_view_at_top);
// apply ConstraintSet depending on "toggle"
ConstraintSet newLayout = (toggle) ? expanded : collapsed;
TransitionManager.beginDelayedTransition(constraintLayout);
newLayout.applyTo(constraintLayout);
// invert the toggle
toggle = !toggle;
}
Note:
1. Make sure context is of type Activity and you're using an
AppCompat theme. I accidentally used getApplicationContext(), what
obviously resulted in a crash.
2. If you are receiving an NPE on your constraintk
Try to use Animation class for this:
Animation animation = new Animation() {
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
LayoutParams params = yourView.getLayoutParams();
// modify your layout params here
yourView.setLayoutParams(params);
}
};
animation.setDuration(500); // in ms
yourView.startAnimation(animation);
Related
I have a fragment that has a CoordinatorLayout type of the main layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
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">
<include
android:id="#+id/secondContainer"
android:layout_height="match_parent"
android:layout_width="match_parent"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"/>
<include
android:id="#+id/mainContainer"
layout="#layout/view_home_content"
app:layout_anchorGravity="bottom"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
So inside the main container I got two included separate layouts. First one
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/topContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="#+id/topButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>
And the bottom one
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/bottomContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="#+id/bottomText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>
So my main goal is to make view with id topButton constraint to bottom of bottomText. I was trying to make it programmatically and it works fine if they are In the same xml file but when they are separate as I show above it doesn't work
Here is how I programmatically connects them
with(binding.topContainer) {
topContainer = topContainer
button = topButton
}
with(binding.bottomContainer) {
text = bottomText
}
val mConstraintSet = ConstraintSet()
mConstraintSet.clone(topContainer)
mConstraintSet.clear(R.id.topButton, ConstraintSet.TOP)
mConstraintSet.connect(R.id.topButton, ConstraintSet.TOP, R.id.bottomText, ConstraintSet.BOTTOM)
mConstraintSet.applyTo(topContainer)
As I said earlier it works if I use ID's of layouts from one file. But this way seems they don't see each other
It's expected that It won't work when using the two separate files. To use constraints, you need to put the desired views inside the same constraint layout. You have a ConstraintLayout for bottom and another for top. You can try to put a ConstraintLayout inside your coordinatorLayout and try to put the constraints in include tags.
Few days ago I want to customize a TabLayout like this (RallyTab), which uses Flow and can rearrange the elements according to the clicked icon.
I read its source code, and its function of rearranging elements seems to be achieved by the ConstraintHelper.setReferencedIds(int[] ids) on line 168. But when I try the following code, it does not work:
findViewById(R.id.button).setOnClickListener(v -> {
Flow flow = findViewById(R.id.flow);
int[] ids = new int[] {R.id.image1, R.id.image3, R.id.image2, R.id.image4, R.id.image5};
flow.setReferencedIds(ids);
});
This is layout xml:
<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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/cl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp">
<androidx.constraintlayout.helper.widget.Flow
android:id="#+id/flow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:constraint_referenced_ids="image1, image2, image3, image4, image5"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/image1"
android:layout_width="52dp"
android:layout_height="52dp"
app:srcCompat="#drawable/ic_baseline_exposure_neg_2_24" />
<!-- image2, image3, image4, image5 are the same as image1, only the id and srcCompat are different -->
</androidx.constraintlayout.widget.ConstraintLayout>
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Button" />
</LinearLayout>
Even if I copy its source code and layout xml to my project, it still not work. When i clicked on its icon, the position of elements did not change, only the TextView was playing its beautiful animation.
So I realized that the ConstraintHelper.setReferencedIds(int[] ids) method does not change the position of elements (or it will, welcome to correct me :-)), and RallyTab may have called some method in somewhere that I did not notice to rearrange them.
How do I do to change the position of elements like RallyTab? Can anybody point out where I missed? Or what should I do to achieve this function without Flow? Thanks in advance.
I am having a weird issue which might be very simple to solve but I don't know why its behaving like it does. I have two screens A and B. Navigation is from A -> B. On B, I have parent view as LinearLayout (LL) as
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="#+id/container"
android:orientation="vertical"
android:background="#color/tcRaspberry"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:animateLayoutChanges="true"
android:layout_height="match_parent">
<include
app:layout_constraintBottom_toTopOf="#+id/bottomSheetContainer"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:id="#+id/toolbarx"
layout="#layout/include_toolbarx"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_marginStart="#dimen/itinerary_start_margin"
android:layout_marginEnd="#dimen/itinerary_start_margin"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatImageView
android:contentDescription="#null"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="#dimen/itinerary_start_margin"
app:layout_constraintStart_toStartOf="parent"
android:id="#+id/myAccountImage"
android:layout_gravity="center"
app:srcCompat="#drawable/ic_panorama_circle_24dp"
android:layout_width="#dimen/image_size_profile"
android:layout_height="#dimen/image_size_profile"/>
<androidx.appcompat.widget.AppCompatTextView
android:textSize="20sp"
android:contentDescription="#string/travel_counsellor_contact"
android:layout_marginStart="#dimen/top_margin"
app:layout_constraintTop_toTopOf="#+id/myAccountImage"
app:layout_constraintStart_toEndOf="#+id/myAccountImage"
app:layout_constraintBottom_toBottomOf="#+id/myAccountImage"
android:id="#+id/myAccountTitle"
android:textAppearance="#style/TcTextAppearance.Bold.Header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/my_account"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
Even though the parent LL's height (id: container) is set as match_parent and is filling whole screen, its still accepting click events from previous screen A. The only way I got it to not accept clicks from A is to put a ClickListener on it which seems like a hack to me. What can I do to prevent it taking clicks from A.
Make the view that should block the call clickable via xml android:clickable="true" or set a click handler for it from fragment/activity
i had gone through research about for couple of days but didn't get it resolved. Problem in this Question is similar to mine but I couldn't solve my issue using this either.
I had tried to get the circular reveal effect just like whatsapp where the revealed view will be inflated over the top of other views. In my case when I apply the animation on a layout already present in the layout.xml of current java class then its work fine but the problem is that the revealing layout which in my case is LInearLayout will push the other contents(which are under it) down and make place for it.
My layout in this case is as follow,
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<io.codetail.widget.RevealFrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/reveal_items"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageButton
android:layout_width="70dp"
android:layout_height="70dp"
android:background="#drawable/icon_camera" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Gallery" />
</LinearLayout>
<!-- Other 2 icons here-->
</LinearLayout>
</io.codetail.widget.RevealFrameLayout>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Enter Name" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="OK" />
LinearLayout/>
my reveal layout will push the EditText and button down to make place for it but i want to reveal over the top of them..
Then I tried to put the revealing view code in another reveal-layout.xml file and inflate that layout to a View(LinearLayout in my case) created in javacode. And then try to apply the revealing effect on this LinearLayout but it gives me this "cannot start this animator on a detached view" exception.
My revealing-layout.xml looks like
<io.codetail.widget.RevealFrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/reveal_items"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageButton
android:layout_width="70dp"
android:layout_height="70dp"
android:background="#drawable/icon_camera" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Gallery" />
</LinearLayout>
<!-- Other 2 icons here-->
</LinearLayout>
</io.codetail.widget.RevealFrameLayout>
In button click i call function revealView();
which looks as below,
public void revealView()
{
int cx = (mRevealView.getLeft() + mRevealView.getRight());
int cy = mRevealView.getTop();
int radius = Math.max(mRevealView.getWidth(), mRevealView.getHeight());
// and all animations here, the animator is working fine so i did not put the code here
}
If i initialize mRevealView in my MainActivity onCreate() methoed as, mRevealView=(LinearLayout)findviewbyid(R.id.reveal_items) and inflate and assign view to it then the animator will work fine on this view. But when i try to create new layout like,
mRevealView=new LinearLayout(this) and set its parameters etc everything then it will gives this error when i apply animator on it.
Cannot start this animation on a detached view.
What I am doing wrong here can anybody suggest me.
Try to put your reveal code in a ViewTreeObserver of intended reveal-layout, something like this:
boolean reveal = false;
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
reveal = true;
}
});
LinearLayout layout = (LinearLayout) findViewById(R.id.reveal_items);
layout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if(reveal) {
reveal = false;
// start reveal animation here
// ...
}
// for SDK >= 16
ll.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
To achieve a similar effect like whatsapp using the Circular Effect like whatsapp library you mentioned i first set my parent view as FrameLayout. This parent Framelayout includes two childrens first is LinearLayout and second is FrameLayout(Here comes the code you want to display on top of view written in LinearLayout). Write all your code which you want display on the screen in the first LinearLayout and the reveal effect code in second FrameLayout as i mentioned. Its simply the use of FrameLayout property. You are good to go.
You can use the same java code provided in the discription of the library.
Is it possible to have a margin/padding for the ListView without having the margin applied to the header? I want my ListView to be like the Google Now layout. I've got everything working except for this little problem.
Question: Is it possible to not have layout parameters of the ListView apply to its header?
EDIT1:More info
The purple view is the header to the listView.
I have tried adding margin to the list item layout.This doesnt work either.
All i need is a way to apply margin to the listview so that it doesnt apply the margin to the header in the listView.
EDIT2:
My layouts
header.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:orientation="vertical" >
<View
android:layout_width="match_parent"
android:layout_height="#dimen/top_height"
android:background="#color/top_item" />
<View
android:id="#+id/placeholder"
android:layout_width="match_parent"
android:layout_height="#dimen/sticky_height"
android:layout_gravity="bottom" />
</FrameLayout>
root_list.xml
<LinearLayout>
<com.test.CustomListView
android:id="#android:id/list"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_height="wrap_content" /></LinearLayout>
list_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/card_background"
android:orientation="vertical" >
<TextView
android:id="#+id/textview_note"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textview_note_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"/></LinearLayout>
I've removed uselsess layout properties here due to length of this post.
After much digging around i found that its is not posssible to decouple the listView layout params from its headers and the header is part of listView. So in order to get the desirred margin effect, After much looking around I found out that adding margin to your root of the layout in the list view item didnt work. So I added another dummy LinearLayout inside the existing root LinearLayout(a nested LinearLayout) and added the children inside the nested layout.Now setting margin to the inner layout gives the desired effect.
Code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:layout_marginLeft="16dp"
android:background="#drawable/list_selector"
android:orientation="vertical" >
<TextView
android:id="#+id/textview_note"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textview_note_date"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
In your header part, add the following tag:
android:layout_alignParentLeft="true"
this will solve your problem.
// Temp is the root view that was found in the xml
final View temp = createViewFromTag(root, name, attrs, false);
ViewGroup.LayoutParams params = null;
if (root != null) {
if (DEBUG) {
System.out.println("Creating params from root: " +
root);
}
// Create layout params that match root, if supplied
params = root.generateLayoutParams(attrs);
if (!attachToRoot) {
// Set the layout params for temp if we are not
// attaching. (If we are, we use addView, below)
temp.setLayoutParams(params);
}
// We are supposed to attach all the views we found (int temp)
// to root. Do that now.
if (root != null && attachToRoot) {
root.addView(temp, params);
}
// Decide whether to return the root that was passed in or the
// top view found in xml.
if (root == null || !attachToRoot) {
result = temp;
}
...
return result;
this is the code of LayoutInflater,as you can see ,if you add a root,it's not null,generated the layoutParams from root.
and then if the thrid param is false,there is only make temp.setLayoutParams(params) which params is generated by root!! and the temp is as return....
if attachToRoot is true,root will execute root.addView(temp, params),and then the root is as return..
if you just do LayoutInflater.from(this).inflate(R.layout.popup_choose_type, null);,and if you had set some attribute as paddingBottom,it will surprised you that is will not work!!because of loss LayoutParams!
As for how to solve it,you can see
here
you can do it by give margin in listview's layout file then you will get it the output.