I have 2 views and I'm showing them one below the other one like this(both of them children of the same parent:
<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">
<View
android:id="#+id/view1"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#00FF00"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/view2"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#0000FF"
app:layout_constraintTop_toBottomOf="#id/view1" />
</android.support.constraint.ConstraintLayout>
All works fine but when I change view1 position with setY method the view2 view not updating it's y position too.
I tried to call invalidate and requestLayout, but nothing helps.
How can I refresh or update the constraints after setting the position.
This is a little confusing, so bear with me. setY() does the following:
Sets the visual y position of this view, in pixels. This is equivalent to setting the translationY property to be the difference between the y value passed in and the current top property.
And setTranslationY() does this:
Sets the vertical location of this view relative to its top position. This effectively positions the object post-layout, in addition to wherever the object's layout placed it.
The key phrase here is "positions the object post-layout." In other words, the view that is the subject of setY()is positioned according to the layout then is moved to the new location based upon the argument to setY(). This does not result in another layout. In essence, although the view appears in its new location, it is, effectively, still in its original location. Invalidating and requesting another layout just causes the same layout to occur followed by the translation.
Setting the top margin as Ben P. suggests should work to move the view.
I am not exactly sure why setY() doesn't also update the second view, but you can work around it by setting the first view's top margin instead of calling setY():
ConstraintLayout.LayoutParams params =
(ConstraintLayout.LayoutParams) view1.getLayoutParams();
params.topMargin = 200;
view1.setLayoutParams(params);
Here is my solution:
Just move view1 using setTranslationY(), then assign view1 translationY to view2.
Java example:
view1.setTranslationY(10f);
view2.setTranslationY(view1.getTranslationY())
Kotlin version:
view1.translationY = 10f
view2.translationY = view1.translationY
Related
I am hoping to position views within a parent view using percentages, similar to what is possible with absolute positioning in CSS. In my scenario, I will have a variable and unpredictable number of views that will be positioned this way.
Here is an example, which represents 3 TextViews inside a square with the following positions:
1: Top 55%, Left 29%
2: Top 77%, Left 58%
3: Top 54%, Left 43%
Is this best accomplished using custom drawing? Or is it possible to dynamically position views within a certain type of parent view given these percentages? If the former, how can I handle the text? And if the latter, what type of view should the parent be, and how should I go about setting these percentages?
You could use a ConstraintLayout
https://developer.android.com/training/constraint-layout/index.html
A constraint layout will allow you to position a view based on percentages like you want using horizontal and vertical bias. For example:
<android.support.constraint.ConstraintLayout
android:id="#+id/constraint"
android:layout_width="match_parent"
android:layout_height="200dp">
<TextView
android:id="#+id/edition_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.33"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.33"
android:background="#android:color/holo_purple"
android:text="text"/>
</android.support.constraint.ConstraintLayout>
Just make sure the child view (the Textview) is constrained to the top and bottom so you can set vertical bias. And also start, end so you can set horizontal bias.
The result is this:
And this can be done programmatically also, see here for a good guide:
http://www.zoftino.com/adding-views-&-constraints-to-android-constraint-layout-programmatically
Set the view according to X & Y position, use Android Absolute Layout here is the Example
Hope this will help you!!
as the title says i want to understand what that method exactly is doing.
firstable i have double checked that the coordinate system of android works like that:
coordinate system
secondary - please take a minute to check my android studio screen, and the method quick doc. why is that value of my view (after clicking it) is 106?
android screen
the coordinate system is correct.
getY() will return the value of the top of your View + the Y translation. so, if getY() is returning 106 and you set translation y to 10, the top of your view should be at 96. try calling also getTop() and check what is that value
the translation is an offset that is applied to the position of the View. if the layout place your View at x;y and you call setTranslationY(10), your View will appear at x;y+10. it's a way to control the positioning of the View after the layout
bonus tip, instead of logging everything, use the debugger
in case you still have doubts about the difference between the position and translation, you could try this, create an empty activity and set this layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.lelloman.dummy.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="asd asd"
android:layout_above="#+id/button"
android:layout_centerHorizontal="true"/>
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="asd"/>
</RelativeLayout>
then, you will see that the TextView is right above the Button, because this is how the RelativeLayout will position the Views given these layout parameters. now, try to call
findViewById(R.id.button).setTranslationY(100);
you will notice that the button will be moved down by 100px, but the TextView will still be at the old position, because the translation is applied after the layout. it is something specific to that View that is not taken into account for the positioning of the View within its parent
you could also set the translation in the xml with
<Button
android:translationY="100px"
...
I am developing an Android app where I have two different views. Both views are actually canvas drawings (drawn programmatically) with a bunch of text views and buttons on top. The positions of these buttons and text views need to be changed depending on the view selection. I created a relative layout with my drawing and the buttons and text views. I use one of the text views as an anchor for the others and programmatically change its position.
Here is a part of the xml:
<TextView
android:layout_width="50dp"
android:layout_height="wrap_content"
android:id="#+id/tvAnchor"
android:layout_above="#id/btnCtrl"
android:layout_marginBottom="130dp"
android:textSize="15sp"
android:textColor="#color/lightGrey"
android:gravity="center"
android:text="#string/Select1"
android:background="#drawable/controls_border_not_active"
android:clickable="true"/>
<TextView
android:layout_width="50dp"
android:layout_height="wrap_content"
android:id="#+id/tvAlign"
android:layout_alignBottom="#id/tvAnchor"
android:layout_toStartOf="#id/tvAnchor"
android:layout_marginEnd="2dp"
android:textSize="15sp"
android:textColor="#color/lightGrey"
android:gravity="center"
android:text="#string/Select2"
android:background="#drawable/controls_border_not_active"
android:clickable="true"/>
In my main I have the following code to change the position of the text views accordingly:
private void PositionControls(){
RelativeLayout.LayoutParams lopAnchor = (RelativeLayout.LayoutParams) tvAnchor.getLayoutParams();
if (isView1Selected){
lopAnchor.resolveLayoutDirection(relativeLayout.getLayoutDirection());
lopAnchor.removeRule(RelativeLayout.ALIGN_START);
lopAnchor.setMargins(0,0,0,370);
lopAnchor.addRule(RelativeLayout.CENTER_HORIZONTAL);
}else{
lopAnchor.setMargins(0,0,0,300);
lopAnchor.removeRule(RelativeLayout.CENTER_HORIZONTAL);
lopAnchor.addRule(RelativeLayout.ALIGN_START,swDoIt.getId());
}
tvAnchor.setLayoutParams(lopAnchor);
}
Basically, in View1, the tvAnchor should be centered horizontally and in the other view it should be positioned off center - in the middle of 'center-to-right screen edge'. In order to do that when the second view is selected I remove the CENTER_HORIZONTAL rule and add a rule 'ALIGN_START' with a switch that is already positioned in the desired X coordinate. It works just fine. The problem occurs when View 1 is selected again and I switch from View 2 to View 1. In this situation I remove the ALIGN_START rule and add the CENTER_HORIZONTAL one. The thing is that tvAnchor remains aligned to the switch as if the ALIGN_START rule was not removed. I tried to get the direction of the layout, used requestLayout and other things that could think of, but nothing seems to remove that rule.
Did you check that there isn't coming some mystery values enabled??
I had case where is moved clockwidget place in layout
I did add ALIGN_PARENT_END and removed CENTER_IN_PARENT but when i set layout back i could not get clock widget centered.
RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) mTextClockWidget.getLayoutParams();
p.addRule(RelativeLayout.ALIGN_PARENT_END, 1);
p.removeRule(RelativeLayout.CENTER_IN_PARENT);
mTextClockWidget.setLayoutParams(p);
Then noticed that from somewhere my layout params got ALIGN_PARENT_RIGHT enabled and when tried to remove ALIGN_PARENT_END and enable CENTER_IN_PARENT it didn't work. So i had to also add remove for ALIGN_PARENT_RIGHT to get it work.
RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) mTextClockWidget.getLayoutParams();
p.removeRule(RelativeLayout.ALIGN_PARENT_END);
p.removeRule(RelativeLayout.ALIGN_PARENT_RIGHT);
p.addRule(RelativeLayout.CENTER_IN_PARENT, 1);
mTextClockWidget.setLayoutParams(p);
I'm using the Scene/Transition system introduced in 4.4 to simply move an image view from the left to the center of the screen. So the layout for my first scene requires the image to be off screen. I tried android:layout_marginRight but that no effect. What is the correct way to do this?
Use the property translationX or translationY with a negative value. This property sets the horizontal/vertical location of this view relative to its left/top position. You will not see the view off screen in the preview. Run your app and the view must be hidden.
Example:
<FrameLayout 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.support.design.widget.FloatingActionButton
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|start"
android:layout_margin="16dp"
android:translationX="-72dp"/>
</FrameLayout>
And then in the activity or fragment simply invoke the animate() function.
FloatingActionButton button = (FloatingActionButton)findViewById(R.id.button);
button.animate().translationX(0);
Was thinking one could make the image be to the right of something that is already at the right side, that should keep it off screen. Also, potentially just make it "gone" and then on transtion make it appear.
I need to implement the layout as in the picture. Parent and Sibling are in a vertical LinearLayout. So I need to make a child view to overlap it's parent. Can I do that in android?
If:
sibling is a sibling of parent
parent is a ViewGroup
and you really want child to be a child of parent
then maybe you could consider using android:clipChildren set to false on parent.
I was actually just looking at an example of a FrameLayout that had a TextView overlaid on top of an ImageView. So, there are obviously multiple ways to get it done. Your next question might be which one is best ... to that I have no idea, but here's a guy that might:
http://www.curious-creature.org/2009/03/01/android-layout-tricks-3-optimize-part-1/
Just contain them all within a RelativeLayout, and remember the draw order is top to bottom, so put the top most view on the bottom of the XML definition.
If you use a RelativeLayout you should have no problem achieving this effect. By default it will stack all of its children on top of each other in the top left corner if you don't supply them with android:layout parameters. So it will definitely support overlapping children. You'd just have to figure out what the best way to tell it where the child should go on the screen relative to something else.
There are at least two layouts that can do that. AbsoluteLayout and RelativeLayout. I suggest that you put your views in a RelativeLayout and add them with LayoutParams that specify their offset form the top and left of the parent:
RelativeLayout.LayoutParams rlp;
label = new TextView(ctx);
label.setBackgroundColor(0x00000000);
label.setTextColor(0xFF7ea6cf);
label.setTextSize(13);
label.setGravity(Gravity.LEFT);
label.setText("Examples:\n- Fentanyl\n- Dilaudid 2 mg PO q 4 hours prn moderate pain");
rlp = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,100);
rlp.topMargin=189;
rlp.leftMargin=30;
rlp.rightMargin=30;
rlParent.addView(label,rlp);
In my case, I have to set android:clipCildren to be false on the parent of parent.
i.e.
<?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="match_parent"
android:clipChildren="false"
android:id="#+id/parent1">
<FrameLayout
android:id="#+id/parent2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="64dp"
android:background="#android:color/holo_blue_bright">
<View
android:id="#+id/This_is_the_view_I_want_to_overlap_parent2"
android:layout_width="160dp"
android:layout_height="80dp"
android:layout_gravity="top|start"
android:layout_marginTop="-40dp"
android:background="#000000" />
</FrameLayout>
</FrameLayout>