Android align button programmatically - android

I have an Android button on a RelativeLayout which I want to animate.
The animation is currently done with a ObjectAnimator to move the button 50dp up and down on a scroll event.
The position of the button is currently calculated programmatically with
height = context.getResources().getDisplayMetrics().heightPixels
y = height - buttonheight - bottomMargin
My problem with this is, that the calculation works fine in the portrait mode, but as soon as I switch to landscape mode the distance between bottom and button is bigger than in portrait mode.
What did I miss?

Try to convert pixels to dp right before putting your button on the layout:
public static float convertPxToDp(int px, Context context) {
final float scale = context.getResources().getDisplayMetrics().density;
float dp = (float) ((px - 0.5f) / scale);
return dp;
}
This should work!

This is correct and obvious when you will change your orientation your height calculation value will also change as display matrics.heightPixel will return more height in case of landscape mode.
height = context.getResources().getDisplayMetrics().heightPixels
It will return more value and accordingly it will be recalculated. If you want to just give fixed value of space between button and bottom than you have to recheck your height calculation idea.

first try to convert pixel to dp like this :
Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics ();
display.getMetrics(outMetrics);
float density = getResources().getDisplayMetrics().density;
float dpHeight = outMetrics.heightPixels / density;
float dpWidth = outMetrics.widthPixels/density;
then i think you must change your algorithm in landscape mode

Converting to dp did not work.
So my solution is to wrap a RelativeLayout around my button, and animate the button relative to its parent, which is fixed.
<RelativeLayout android:layout_width="56dp"
android:layout_height="85dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginRight="13dp">
<Button
android:id="#+id/button"
android:layout_marginTop="10dp"
android:layout_width="56dp"
android:layout_height="56dp"/>
</RelativeLayout>

Related

Converting dp into pixels for multiple screen support

I am having a hard time to make this right.
Basically I am creating an ImageView and applying a LayoutParameter to it.
LayoutParams lp = new LayoutParams(width, height);
lp.gravity = Gravity.CENTER;
I know that width and height parameters receive pixel numbers, so I am passing them in DP and converting it to absolute pixels using:
public int convertToPixels(float dpSize){
final float density = getResources().getDisplayMetrics().density;
return ((int) (dpSize * density + 0.5f));
}
As far I know, this should make a drawable fill exactly the same area in different screens, right? Unfortunately, that is not happening at all.
Is there something wrong with these methods I am using?
These two emulators below have the same image and the same amount of DP.
Left emulator is 1.0 density and right one is 2.0. Why still does it look
so different ? Don't undertand..
Use :
public class Convert{
public static float convertDpToPixel(float dp){
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return Math.round(px);
}
}
Just use it in a static way:
float requiredPixel = Convert.convertDpToPixel(16.0);
For more info: https://developer.android.com/guide/practices/screens_support.html

Automatically scrolling to top left corner in Android TouchImageView

I'm using a TouchImageView in my app in which I have an image which is larger than the screensize. When I start the activity that contains my TouchImageView it currently automatically shows the center of my image in the middle of the screen. I have to manually (using a drag gesture) make the top left-corner visibe. However, I would like to have the top-left corner of the image visible in the top left corner of my screen by default.
I tried imgView.setScrollPosition(0,0), but without any result.
I also tried setting the scaletype to "matrix", but this zooms out on the image, while I want the image to be shown in it's original size. Scaletypes fitStart and fitEnd are not supported by TouchImageView.
How can I scroll to the top left corner of my TouchImageView?
Here's my XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.frankd.wttv.TouchImageView
android:id="#+id/imageView"
android:layout_width = "wrap_content"
android:layout_height ="wrap_content"
android:scaleType="matrix"/>
</LinearLayout>
And here is how I open the layout and set the image.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.myLayout);
//set timetable image
TouchImageView imgView = (TouchImageView)findViewById(R.id.imageView);
imgView.setImageResource(R.drawable.myImage);
//TODO: scroll to top left corner of image
}
The cause of the problem is that scrollToPosition(x,y) in TouchImageView doens't use the x and y pixels as input, but instead a number between 0 and 1 that reflects a proportion of the image size.
Also the scrollToPosition(x,y) sets a point of the image in the center of the TouchImageView. So if you call scrollToPosition(0.5,0.5) on the TouchImageView, the center of the image is being displayed at the center of the TouchImageView. We need to calculate which point of the image needs to be placed in the center of the TouchImageView to get it aligned nicely.
I created the function scrollToTopLeft() in TouchImageView.java, which only works if you call it at the end of onMeasure() from within the TouchImageView.java file. If you call it earlier the getWidth() and getHeight() will return 0 as the view hasn't been sized yet.
public void scrollToTopLeft() {
try {
float x, y, viewWidth, viewHeight, viewCenterX, viewCenterY, imageWidth, imageHeight;
//these calls will only work if called after (or at the end of) onMeasure()
viewWidth = this.getWidth();
viewHeight = this.getHeight();
// get center of view
viewCenterX = viewWidth / 2;
viewCenterY = viewHeight / 2;
// get image height and width
imageWidth = getImageWidth();
imageHeight = getImageHeight();
//calculate the x and y pixels that need to be displayed in at the center of the view
x = viewWidth / imageWidth * viewCenterX;
y = viewHeight / imageHeight * viewCenterY;
//calculate the value of the x and y pixels relative to the image
x = x / imageWidth;
y = y / imageHeight;
setScrollPosition(x, y);
} catch (Exception E) {
Log.v(TAG, E.toString());
}
}

Measuring margin of a "fitCenter" imageView in Android

Given a simple RelativeLayout like this:
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#0fffff">
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="#drawable/img001" />
</RelativeLayout>
the left/top spacing between the layout border and the image border depends on the W/H ratio of the image being load in the imageView.
How can I know (programmatically) the real margin (width and height of the cyan area) after an image is shown in this layout?
This method will calculate the new rectangle which bounds the object after FIT_CENTER and all other related values.
It should work on all cases of object and container.
public static Rect calculateFitCenterObjectRect(float containerWidth, float containerHeight, float objectWidth, float objectHeight) {
// scale value to make fit center
double scale = Math.min( (double)containerWidth / (double)objectWidth, (double)containerHeight / (double)objectHeight);
int h = (int) (scale * objectHeight); // new height of the object
int w = (int) (scale * objectWidth); // new width of the object
int x = (int) ((containerWidth - w) * 0.5f); // new x location of the object relative to the container
int y = (int) ((containerHeight - h) * 0.5f); // new y location of the object relative to the container
return new Rect(x, y, x + w, y + h);
}
You can use FrameLayout to position the view wherever you want after using the previous method with the new x, y, width, height of the scaled object.
If you know the width of the ImageView, like this
int ivWidth = iv.getMeasuredWidth();
and the total width of the layout (your RelativeLayout), like this
int layoutWidth = yourLayout.getWidth();
then, you can easily get the horizontal margin, like this
int horizontalMargin = (layoutWidth - ivWidth)/2;
And the same goes for height.
You should call functions like getWidth and getHeight after the dimensions of your layout have been calculated, as described by Veer's and Khan's answer on How to get the width and height of an Image View in android?.
Calling getWidth or getHeight in onCreate will return 0.

Making UI elements relative to screen size?

Lets say I wanted to make a relative view with two columns of buttons, left and right.
Where each button takes up exactly 20% of the screen, separated by 10%, with the remaining border on the sides. But to do this for any screen size. DP I think won't work because how do you know the DP pixel count on each different screen?
Basically how do you keep UI's relatively the same and fitting between all devices?
Short answer: LinearLayout.
Long answer is here:
Defining a percentage width for a LinearLayout?
There are also ways of getting density at runtime, but the above is easier in the long run.
Get ready for some pseudo-xml!
<LinearLayout double fill parent, vertical>
<RelativeLayout w = 0, h = 0, weight smallish>
<Button A />
</RelativeLayout>
<LinearLayout w = 0, h = 0, weight largish. horizontal>
<!-- maybe you want these to be RelativeLayout and set the buttons
as centerHorizontalInParent="true" -->
<LinearLayout w = 0, h = 0, weight whatever 20% is>
<Buttons with some padding/margins>
</LinearLayout>
<Some kind of spacer, or just pad the LLs />
<LinearLayout repeat above />
</LL>
</LL>
Edit:
If you are bent on doing alot of dynamic resizing, I have this custom class for getting screen size:
public class ScreenGetter {
private float pixHeight;
private float pixWidth;
private float dpHeight;
private float dpWidth;
private float density;
public ScreenGetter (Context context){
Display display = ((WindowManager)
context.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics ();
display.getMetrics(metrics);
pixHeight = metrics.heightPixels;
pixWidth = metrics.widthPixels;
density = context.getResources().getDisplayMetrics().density;
dpHeight = pixHeight / density;
dpWidth = pixWidth / density;
}
public float getPixHeight(){return pixHeight;}
public float getPixWidth(){return pixWidth;}
public float getDpHeight(){return dpHeight;}
public float getDpWidth(){return dpWidth;}
public float getDensity(){return density;}
}
Obviously you'll need to do some math to figure out what you want at different sizes and densities. You also need to account for parts of the screen you are not using (ActionBar, etc.)

How to programatically set the width of an Android EditText view in DPs (not pixels)

I'm dynamically generating a grid of EditText views in code based on a specified number of rows and columns. I want each of the EditText views to be the same width (e.g., 100dp).
Although I can set the size of the views with either setWidth or by creating a LayoutParam object, I only seem able to specify the value in pixels. I instead want to use the DP (density independent) units, similar to what I've done using an XML layout.
How can this be done in code?
I have a method in a Utils class that does this conversion:
public static int dip(Context context, int pixels) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (pixels * scale + 0.5f);
}
float value = 12;
int unit = TypedValue.COMPLEX_UNIT_DIP;
DisplayMetrics metrics = getResources().getDisplayMetrics();
float dipPixel = TypedValue.applyDimension(unit, value, metrics);
Using the below code i was able to do it.
int width = (int)
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, (100)your Size
in int, getResources().getDisplayMetrics());

Categories

Resources