understanding View.setTranslationY() [ /X() ] - android

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"
...

Related

Constraint view not updating position after setX

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

How to position a view off-screen in Android layout

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.

View without Activity - Placement and Layout

I am using the Code from JawsWare - Overlay View to create a View that lays above everything.
This works fine, but I failed to adapt the given layout to my needs.
What I want: Two Phases.
First Phase: A button in the upper left corner that is always there above all other apps.
When this button is pressed, we enter the Second Phase:
The button is replaced by two images which are to be horizontally aligned at a certain distance from the top, again floating above everything else.
I have to admit that I dont really understand Android Layouting, but I've tried fiddling with a RelativeLayout and an ImageView but it seems buggy.
Additionally, I encountered a very strange behaviour: Even if the Image is only about 200x200 px in the upper left corner, nearly the whole screen is "blocked" by the View (it receives all TouchEvents, even though there shouldt be anything). It seems that if I position the Layout using Margins to float in the middle of the screen, everything to the left and top of the visible button is also receiving touch events and not letting them pass through to the underlying app (even though there is no visible content).
Any ideas to why this happens and how to circumvent that?
Secondly: How can I achieve the two layouts from earlier?
Edit 1: My Layout. (please keep in mind that I just copied this and then did what I thought was right)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="0dp"
android:onClick="overlayTextClicked"
android:padding="0dp"
android:id="#+id/overlay_layout_id"
>
<ImageView
android:id="#+id/imageview_info"
android:layout_width="200px"
android:layout_height="200px"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:scaleType="fitXY"
android:src="#drawable/picture_010512233437384578"
android:contentDescription=""/>
<TextView
android:id="#+id/textview_info"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:text="info"
android:textColor="#FFF"
android:orientation="vertical"
android:textAppearance="?android:attr/textAppearanceSmall" />
</RelativeLayout>
Afterwards I am trying to set the RelativeLayouts Gravity to TOP | CENTER_VERTICAL with a Top-Margin of 200px.
I believe what's going on here is your TextView is filling out the entire screen.
wrap_content bounds the size of a View with its content. match_parent fills a view to as big as it can get (i.e., whatever size the container is bound to).
So in this case, your RelativeLayout is does not have a max size it's bound to. Your TextView is going to try to get as big as it can get, so it's going to fill the screen. Likewise, the RelativeLayout is going to blow up to that size to wrap around the TextView.
Also, RelativeLayout doesn't really respond to Gravity well. That is used in LinearLayout and FrameLayout containers a lot, but RelativeLayout relational rules like "CENTER_IN_PARENT" are going to override whatever Gravity you set (if you set Gravity.RIGHT and "CENTER_IN_PARENT", then one has to win out I guess).

Making Android not clip the view while animating (simple flip-clock-like widget)

I'm implementing a simple flip-clock / counter / ticker widget which will consist of several instances of a following "digit" widget:
It's a digit placed on top of a background image. The digit is supposed to animate every second by sliding up and revealing next digit. During the animation both digits should stay "within" the background's boundary.
I'm trying to achieve this behavior by having a TextView with 2 lines - one digit per line - and animating this TextView's position upwards, until the next digit is fully visible. And then I will reset TextViews position and replace both digits at the same time, so that it's impossible to notice. Then I will repeat the process and make it look like the animation never ends.
Here you can see an intermediate state of the animation, when part of zero and part of nine is visible. I "mocked" it in the Graphical Layout editor of Eclipse, by setting the layout_marginTop property to a negative value.
Here's the layout file (the mentioned attribute is normally not there).
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="20dp"
android:layout_height="38dp"
android:background="#drawable/background_countdown_normal_grey"
android:clipChildren="false" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:paddingBottom="5dp"
android:paddingTop="5dp" >
<TextView
android:id="#+id/textview_countdown_digit"
style="#style/TextView.CountdownDigit"
android:layout_marginTop="-12dp"
android:text="0\n9" />
</LinearLayout>
</LinearLayout>
I tried two solutions. By using ViewPropertyAnimator on either translateY or y, I get a smooth animation, but the original clipping of the TextView does not change during animation, so in effect the second digit is never visible. As you can see, I tried clipChildren property, but it doesn't seem to change anything.
My second approach was to use ValueAnimator with a custom Evaluator, which modifies the topMargin of LayoutParams on the TextView. It works, but the animation is very choppy even on high-end devices.
So my question is, how to avoid view clipping during animation and make so in an efficient way? Is there a better approach?
I found an alternative solution in which I use a ScrollView instead. My layout looks like this:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/scrollview_countdown_digit"
android:layout_width="20dp"
android:layout_height="38dp"
android:background="#drawable/background_countdown_normal_grey"
android:paddingBottom="5dp"
android:paddingTop="5dp"
android:scrollbars="none" >
<TextView
android:id="#+id/textview_countdown_digit1"
style="#style/TextView.CountdownDigit"
android:text="0\n9" />
</ScrollView>
I animate using ObjectAnimator by scrollY property. Works well so far.
I also tried having 2 TextViews intsead of one (in my initial layout), but it did not change the fact of clipping.

Example XML Position function?

How do i position a button in xml. Im using Eclipse with android sdk, i just used margins to put the buttons in positions. But how can i do it through the postion function?
Placing a button on the screen using xml is going to very depending on what you use for your root view group.
There isn't a position function like what you are probably thinking where you would set the X and Y position of the button and for good reason. Because of the hardware fragmentation of android devices it would be difficult to write portable UI if you were relying on hardcoded X and Y coords (regardless of portrait vs landscape).
As an example if i wanted to put a button in the bottom right of the screen and I had a relative layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello"
android:layout_alignParentBottom = "true"
android:layout_alignParentRight = "true"/>
</RelativeLayout>
This will put a button on the button right of the screen regardless of screen pixel density/resolution or even landscape VS portrait

Categories

Resources