I have set the background of an Imageview in android (portrait mode) whose dimensions are 400 X 400 pixels. This image looks perfect on a 10" WXGA MDPI tablet (dimensions 800 X 1280). I happen to use the same layout with no modifications in the code on a 7" Nexus 7 (TVDPI 800 X 1280) tablet. The image is looking stretched. Can I programmatically find out the dimensions of the background in the layout on the Nexus 7? I want to mathematically scale down the dimensions of the background such that it looks like a square. I feel that the image background's width looks more than 400 pixels (say X) and the height is also more than 400 pixels (say Y). Also Y > X which makes it looks like a rectangle. How do I find X and Y programmatically in android on the Nexus 7? Please help. Is there a set formula to scale down or scale up the images so that the looks remain consistent on all android phones. Thank you
bellow code will let you take the width of the image and scale it accordingly
try {
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
SCREEN_WIDTH = displaymetrics.widthPixels;
Drawable ob = new BitmapDrawable(getResources(), bm);
float h = ob.getMinimumHeight();
float w = ob.getMinimumWidth();
float Hight = (h / w) *SCREEN_WIDTH;
imageView.setVisibility(View.VISIBLE);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, (int) Hight);
// imageView.setImageBitmap(bitmap);
params.setMargins(5, 5, 5, 5);
imageView.setLayoutParams(params);
int sdk = android.os.Build.VERSION.SDK_INT;
if (sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
imageView.setBackgroundDrawable(ob);
} else {
imageView.setBackground(ob);
}
} catch (Exception e) {
e.printStackTrace();
}
Rather than manually calculating the size of the image, have you tried using android:scaleType="centerInside" in your xml? You can set the size of the ImageView in dp units to keep a consistent size across different screens. The scaleType will ensure that the aspect ratio is maintained on scaling. You can also use android:scaleType="center" if you would like to prevent scaling and place different sized images in your drawables-xxx folders.
Related
I'm new in designing the layouts. I am getting the bitmap from the server and I'm setting the imageview height such that it look good on every density either ldpi, mdpi, hdpi, xhdpi.
stripImageView.getLayoutParams().height = (int) ((Util.screenWidth(this) * strip.getHeight() / strip.getWidth()) * getResources().getDisplayMetrics().density);
But This code not working for me. Some device images looking very small and Some device it look fine
Try just setting the dimensions in your layout using dp instead of px. Dp (or dip) stands for density independent pixels and will automatically scale based on density.
EDIT: another issue I see is that you're referencing both the screen width and height so your screen aspect ratio would also affect that calculation.
convert them to DIP:
stripImageView.getLayoutParams(). height =
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, <HEIGHT>,
getResources().getDisplayMetrics());
where HEIGHT is the height in px you want. You could base it off the strip height or something.
At the top of my app, I have a title which should be shown in the middle, and a button on the right. As the textViews length is behind my control, I sometimes have my title crossing the button due to long length of the content of it.
After following this, I somehow tend to solve the problem. My device was HTC desire. Unfortunately, if I check with Galaxy SIII, it doesn't do the trick.
I am wondering how I can manage this in terms of different devices with different densities.
My controls inside the relative layout
You can also check the device screen density by this--
WindowManager wm = (WindowManager) _context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
int screenWidth = display.getWidth();
int screenHeight = display.getHeight();
And can manage accordingly whats your apps needed..
just use weightsum in your xml and make width of all the views as fill parent ..... this makes auto resizing of your textview
you can maintain layouts according to their DPI`s
replicate the same XML data in XHDPI (As S3 falls in XHDPI) and test it similarly replicate the XML data in HDPI
but
keep in mind the following Thing Pixel Ratio of the layOut as
following
in LDPI its 1:0.75
in MDPI its 1:1
in HDPI its 1:1.5
in XHDPI its 1:2
Display display = ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
DisplayMetrics dm = new DisplayMetrics();
display.getMetrics(dm);
float density = dm.density;
int screenWidth = display.getWidth();
With this code above, you'll have your screen density as float.. So you can use it to calculate your textView's width like:
int newWidth = (int) (density * 100);
which 100 is here based size.
Or you can have a ratio according to your screenWdith.
int newWidth = screenWidth / 2;
I am making a game using And Engine, when i tried to make it in generic way that works on all devices then i am in trouble...
I need to set a sprite on specific position of background sprite that should work on all screens... My background screen has same size as dimension of Device..
I tried to use pixel let say Glaxy S3 ha dimensions 720*1280
And i set according to it my sprite at location (584,608)
and my HTC experia ha dimensions (320,480)
SO i need to set it on (244,172) ....
I have tried all the following ways to set the position of sprites in generic way but not if any work...
I have tried alot of following things to make some formula that enables me to do it but unable to find any.. please advise
final Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
metrics.density;
metrics.densityDpi;
metrics.heightPixels);
metrics.scaledDensity);
metrics.widthPixels);
metrics.xdpi);
metrics.ydpi);
Point point = getDisplaySize(display);
CAMERA_WIDTH = point.x;
CAMERA_HEIGHT = point.y;
DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm);
double x = Math.pow(dm.widthPixels/dm.xdpi,2);
double y = Math.pow(dm.heightPixels/dm.ydpi,2);
double screenInches = Math.sqrt(x+y);
int widthPix = (int) Math.ceil(dm.widthPixels * (dm.densityDpi / 160.0));
//CAMERA_WIDTH = display.getWidth();
//CAMERA_HEIGHT = display.getHeight();
Problem is little bit complex.. As i told above I tried to use pixel let say Glaxy S3 ha *dimensions 720*1280 And required sprite location is (584,608)
so i set in manner ( CAMERA_WIDTH/1.233f,CAMERA_HEIGHT/2.112f)*
BUT HTC experia has dimensions *320*480 So the required positions according to ( CAMERA_WIDTH/1.233f,CAMERA_HEIGHT/2.112f) is (2599.5,227.27)*
but this wrong according to display...
when i set it on (244,172) for experia its working perfect.... please help.
AndEngine offers multiple resolution policies. They are used to determine the size of the RenderSurfaceView, thus the actual size of the game on the screen, depending on the screen size.
You should use RatioResolutionPolicy: It will use the largest possible size, while keeping a constant ratio between the width and the height. By keeping the camera's size constant, everything it shows will be scaled by this constant ratio which will vary on different devices.
Example: Let CAMERA_WIDTH = 720 and CAMERA_HEIGHT = 480. If we create the camera and the engine options this way:
this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
EngineOptions options = new EngineOptions(..., new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), mCamera);
The ratio is 720 / 480 = 1.5.
When placing a sprite on your scene, use constant coordinates. Let's say we place it in the middle of the screen:
Sprite sprite = new Sprite(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2, ...);
So:
On a device with screen size 720x480, the sprite will be placed at (360, 240) screen coordinates.
On a device with screen size 480x320, the sprite will be placed at (240, 160) screen coordinates.
On a device with screen size 800x480, the sprite will be placed at (400, 240) screen coordinates.
And so on...
I am new to Android. I like having the free range of drawing objects where ever I want. So i have been using Absolute Layout. I get a message saying to use a different layout. And I have read that this is because of the different res of different phones. My question is, is this the only reason in not using Absolute Layout? I have made a method that uses metrics to adjust the pixels.
public int widthRatio(double ratioIn){
DisplayMetrics dm = new DisplayMetrics(); //gets screen properties
getWindowManager().getDefaultDisplay().getMetrics(dm);
double screenWidth = dm.widthPixels; //gets screen height
double ratio = screenWidth/100; //gets the ratio in terms of %
int displayWidth = (int)(ratio*ratioIn); //multiplies ratio desired % of screen
return displayWidth;
}
//method to get height or Ypos that is a one size fits all
public int heightRatio(double ratioIn){
DisplayMetrics dm = new DisplayMetrics(); //gets screen properties
getWindowManager().getDefaultDisplay().getMetrics(dm);
double screenHeight = dm.heightPixels; //gets screen height
double ratio = screenHeight/100; //gets the ratio in terms of %
int newHeight = (int)(ratio*ratioIn); //multiplies ratio by desired % of screen
return newHeight;
}
//sets size of any view (button, text, ...) to a one size fits all screens
public void setSizeByRatio(View object, int width, int height){
LayoutParams params = object.getLayoutParams();
params.width = widthRatio(width);
params.height = heightRatio(height);
}
So if i say setSizeByRatio(Button, 10, 25); It will set the buttons width to 10% of the width of the screen and the height to 25% percent of the screen.
Are there any phones that Absolute Layouts do not work on? Does this layout cause any other issues?
The reason why the AbsoluteLayout is deprecated is because you have alternatives in the LinearLayout or the GridLayout that does the same and more. It seems that you are trying to calculate positions based on absolute positions and number of pixels, an approach that should in general be avoided due to issues with varoius screen sizes and densities.
Read the link that #amiekuser provided and focus on the understanding how the best practice is. Some hints are creating images for ldpi, mdpi and hdpi folders, using the unit for dpi (density independent pixels) instead of raw pixels and how to test your app on multiple screen sizes and densities using the emulator.
Edit:
To set the x- and y-position of a View you must use LayoutParams. See this question on how to to set the TopMargin and LeftMargin for a View using LayoutParams.
Android phones comes in many form factors i.e. not only it varies greatly in terms of screen size(2.7", 3.2", 3.7" ....) but also in terms of resolution (480X800, 480X848 etc).
Google itself suggest not to use AbsoluteLayout. in fact its deprecated in the newer api versions.
The link below explains all these in details:
http://developer.android.com/guide/practices/screens_support.html
Check the best practices section.
Strange thing happens - at least I don't get it.
I have an image (w: 120px, h: 63px) which is presented on one ImageButton. The only variant of that image that I have is placed in drawable-hdpi (and there is no other drawable directory).
Everything is ok with this image and every resolution (density), Android takes care of it very nicely.
But, trouble is when I take a photo from an album (some very big photo, for example), scale it to dimensions of a button (previously mentioned, w: 120px h: 63px) and set that small image as ImageButton background.
In case when I am testing on emulator with medium density (160) it is ok, but when testing on device with high density button gets resized since scaled image appears smaller.
Does anyone has an idea what is happening and why is size of image changed once more after I scaled it?
Any clue will be highly appreciated.
Here is the code I use for resizing the image:
public static void resizeAndSaveImage(String pathToResize, int newWidth, int newHeight, FileOutputStream output) {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(pathToResize), null, options);
if (bitmap != null) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
resizedBitmap.compress(Bitmap.CompressFormat.PNG, 100, output);
output.close();
}
} catch (Exception e) {
// ...
}
Dimension parameters are passed in as follows: newWidth = 120, newHeight = 63.
In order to achieve what you want you need to use density-independent pixels (dp) and not physical pixels. Reading from here:
The density-independent pixel is
equivalent to one physical pixel on a
160 dpi screen, the baseline density
assumed by the platform (as described
later in this document). At run time,
the platform transparently handles any
scaling of the dp units needed, based
on the actual density of the screen in
use. The conversion of dp units to
screen pixels is simple: pixels = dps
* (density / 160). For example, on 240 dpi screen, 1 dp would equal 1.5
physical pixels. Using dp units to
define your application's UI is highly
recommended, as a way of ensuring
proper display of your UI on different
screens.
In order to explain in more detail why this is happening with one image (album photo) and not with an image resource, you need to post the code you are using for the scaling.