How to position a view off-screen in Android layout - android

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.

Related

Android: placing an ImageView on an exact location on the screen

I would like to use getLocationOnScreen to get the location of an ImageView, and then I would like to place another ImageView exactly at that place.
Assume they both are in the same layout. When the app starts only imgv1 is visible. The user can move and rotate that image. Then the user can press a button and second image, imgv2 should be placed exactly on top of imgv1 so it covers it. Both imgv1 and imgv2 have the same size.
For example, assume I have imgv1 and imgv2 as:
ImageView imgv1, imgv2;
int[] img_coordinates = new int[2];
imgv1.getLocationOnScreen(img_coordinates);
I wanted to use something like:
imgv2.setX(img_coordinates[0]);
imgv2.setY(img_coordinates[2]);
but this doesn't do what I need to do, which is to place the top left corner of imgv2 on the top left corner of imgv1.
Any other method that helps me to do so is fine too.
** Update **
This is the layout I have:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/tools_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent">
<ImageView
android:id="#+id/imgv1"
android:layout_width="300dp"
android:layout_height="200dp"
android:layout_gravity="center_vertical|center_horizontal"
android:visibility="gone"
app:cameraCropOutput="true"
app:cameraPlaySounds="false" />
<ImageView
android:id="#+id/imgv2"
android:layout_width="300dp"
android:layout_height="200dp"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:visibility="gone" />
</FrameLayout>
The javadoc for view says that setX and setY will offsett the image from it's original location. It looks like what you want to use is setLeft and setTop.
https://developer.android.com/reference/android/view/View#setleft
If i have overlapping views I generally put them in layout and show/hide them. However if you want to dit via code try setting layout params of second image like:
lp.addRule(RelativeLayout.ALIGN_LEFT, image1.getId());
lp.addRule(RelativeLayout.ALIGN_TOP, image1.getId());
...something like it.
Positioning depends a lot on parent of Image views. Relative Layout would be correct choice.
Step #1: Put imgv1 in a FrameLayout
Step #2: Put imgv2 in that same FrameLayout, with android:visibility="gone"
Step #3: When the user presses the button, call imgv2.setVisibility(View.VISIBLE)
<FrameLayout android:id="combined">
<ImageView android:id="imgv1" android:layout_width="match_parent" android:layout_height="match_parent" />
<ImageView android:id="imgv2" android:visibility="gone" android:layout_width="match_parent" android:layout_height="match_parent" />
</FrameLayout>
Missing are sizing/positioning rules for the FrameLayout, which would be whatever you are presently using for your starting conditions for imgv1, presumably.
Alternatively, have one ImageView, rather than two, and change the image on the button click. For example, you could use a LayerDrawable (or the equivalent resource) to layer two drawables on top of each other, and show that.

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

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

Exclude certain elements from being animated in android layout transitions

I have a question regarding the android layout transition framework. In particular i want to achieve an effect that a certain part of an layout slides down or up depending on the visibility of another view(s).
Imagine the following layout. (And please overlook the nested LinearLayouts here ;) )
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:id="#+id/changingView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"/>
<View
android:id="#+id/changingView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"/>
</LinearLayout>
<LinearLayout
android:id="#+id/movingView"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="false"/>
</LinearLayout>
Now what i want to achieve is that when changingView1 and changingView2 change their visibility that movingView slides up or down.
By enabling the LayoutTransition.CHANGING for the parent layout the sliding part works fine so. But this has the side effect that the movingView will also be animated when there are being items added or removed because this layout changes its bounds. And here lies my problem because this results in a very strange looking animation.
So back to my question. Is there a way to keep the sliding animation without animating layout bound changes on the movingView?
Disabling layoutTransitions on the movingView obviously does not help because this only effects the animations of the child views. I also tried playing around with enabling and disabling different LayoutTransitions on the parent layout but so far without the desired effect.
If i can add more details please let me know otherwise i hope someone can help me out.
Thanks in advance!
I know it's late but hope it can help someone. Since android:animateLayoutChanges is the property of the direct parent, you can wrap your View/Layout in a FrameLayout (or some other ViewGroup) and set android:animateLayoutChanges="false" on the new parent.
To avoid unwanted animations you can remove the animate layout changes by code when needed, something like this:
//removing the animate layout changes to prevent the default animation for the newly added items
parentLayout.setLayoutTransition(null);
/* do some logic to add the new views */
//add the animate layout changes back so the over changes will be still animated
new Handler().post(() -> {parentLayout.setLayoutTransition(new LayoutTransition());});

Android Studio - change background image size

So, i wanted to put an image in background of my screen. My problem is that if i just add the image to "background" it will fill all the screen, and my image gets defaced. I could put as an ImageView, but the problem is that i have an expandableListView in the same screen, and i wanted the image to stay behind, as a background.
Any idea how to do this?
Can have 2 solutions: Put as an imagemView but behind the list. Or add as a background but resize it. How can i do it?
Here is what happened:
He is what happens if i put the image as an imageView:
Yes this is very easy to achieve with relative layouts
<RelativeLayout ... >
<ImageView ...
android:layout_alignParentTop="true"
android:scaleType="centerCrop“ />
<ListView ...
android:layout_alignParentTop="true“ />
</RelativeLayout>
With a relative layout z-index is decided by the order you declare the tags, so stuff towards the bottom of the xml is in front of stuff from closer to the top, when they are in the same position.
Use a FrameLayout (Inside FrameLayout view written on top will appear on top and so on)
<FrameLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
></ListView>
<ImageView
android:layout_width="your_width_in_dp"
android:layout_height="your_height_in_dp"
/>
</FrameLayout>
You can also place FrameLayout inside another layout.

Android - Change background color of margin

I have a fragment named HostFragment which nests one to four other fragments.
This is the layout of HostFragment:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/hostFragmentLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="12dp">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<RelativeLayout
android:id="#+id/fragmentContainer1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"/>
<RelativeLayout
android:id="#+id/fragmentContainer2"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"/>
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<RelativeLayout
android:id="#+id/fragmentContainer3"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"/>
<RelativeLayout
android:id="#+id/fragmentContainer4"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"/>
</TableRow>
</TableLayout>
The important part of this is android:layout_marginTop="12dp".
Background: The nested fragments cover the entirety of HostFragment except for this margin. When the nested fragments change their background color (by calling Canvas#drawColor), HostFragment needs to also change the color of this margin to match. I store the needed color in SharedPreferences.
Behavior: If the user goes from HostFragment to SettingsActivity, changes the color, and comes back to HostFragment, the nested fragments will change their color immediately (through their onResume() methods), but HostFragment's margin will still be the old color. If the user then leaves HostFragment and goes to another fragment, then returns to HostFragment, the margin will update its color. I don't know how or why - I have no code in HostFragment to update the color. The code in HostFragment only deals in swapping in and out nested fragments.
Problem: I need the margin color to update right away, so in onResume(), I've tried something like mTableLayout.setBackgroundColor(...) or even mView.setBackgroundColor(...) (mView is the layout I inflate in onCreateView()). This still doesn't work, and the color will only update if the user leaves and comes back.
Question: How can I change the color of the margin to match an int value in SharedPreferences once the user returns to HostFragment from another Activity (i.e. Right after the user returns from the Settings)?
Thank you in advance!
Try giving paddingTop instead of marginTop and then change the color of the view in onResume by mView.setBackgroundColor(...).
Margin is the space outside the View so background color of a view won't reflect in margin space.
Padding is the space inside of a view and background color given to a View will be applied to padding space as well.
Setting the color of a margin is not possible. To achieve something that looks like that though, there's two things to do.
1) Use padding instead of margin.
Margin is outside of an element, while padding is inside of the element. This means that the element will grow in size, and that the color you've given your element as background-color will also apply to the area around the content.
2) Use a border, or drawable.
This way of doing it requires more work, but is very highly configurable. Creating a border is done by simply setting a drawable as background, and giving it a stroke width and color. For more information (and an example implementation) see https://stackoverflow.com/a/8203840/4330555.
For more information on margin, padding, border etc. see http://www.w3schools.com/css/css_boxmodel.asp. This website explains it for CSS, but the concept is the same pretty much anywhere.
try this,
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/c1_cnxlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#android:color/black" >
<RelativeLayout
android:id="#+id/c2_cnxlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:background="#android:color/darker_gray" />
</RelativeLayout>
In order to change the color .setBackgroundColor(...) should work in onResume(), but you should be aware that as it has been pointed out above, a margin area is the space that is left outside from your view within the reference of its parent view. That is why changing a view´s background color would not have effect on the margin. What you could do is add a FrameLayoutthat wraps your TableLayout so that your TableLayout has a reference to set the margin from. In that case, you should be able to change FrameLayout's background and it should affect the desired margin area.
In the image below, the red rectangle represents your TableLayout as you can see on the left, it is the root view of your HostFragmentand the margin area is outside of your reach.On the right, the root view of your HostFragment is a FrameLayout and the red rectangle is still your TableLayout. In the later case, you can change the color of the FrameLayout.
image : http://oi59.tinypic.com/jz8q46.jpg
best way is to use background resource specifying multiple shapes with different color and use margin or padding..

Categories

Resources