I attempted to make a simple app to see if I could make an element a fixed size, in this case 4cm wide, regardless of device. To do this I tried to use the screen xDPI, use that as an inch, multiply that by a constant to get 4cm. It doesn't appear this is working after trying it on a few different devices.
final WindowManager w = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
final Display d = w.getDefaultDisplay();
final DisplayMetrics m = new DisplayMetrics();
d.getMetrics(m);
//find the correct x density and multiply it by 1.5748 to get 4cm
float density = m.xdpi;
density = (float) (density * 1.5748);
int intDensity = (int)Math.ceil(density);
//now set the view to be the dimensions that you want, it must be inside of it's own layout?
box.setLayoutParams(new LinearLayout.LayoutParams(intDensity,100));
Any suggestions?
Related
In our application, we need to determine screen width at startup. We have tried to get this width using a few different methods (see list below), but Samsung devices, especially their Galaxy devices, are sometimes giving us incorrect values.
We have a Galaxy s6 with a resolution of 1440 x 2560 pixels. Most of the time the device will report a width of 1440, but occasionally it will give us a width of 1080.
We have tried getting the width the following ways:
1)
getResources().getDisplayMetrics().widthPixels;
2)
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
3)
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getRealSize(size);
But in all cases we see an incorrect width being returned. We see incorrect values reliably when our application is launched for the very first time. Any help would be hugely appreciated.
Have you tried this?
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int screenWidth = metrics.widthPixels;
UPDATE
And a little bit hardcore.
You may find more here.
This is our getDeviceWidth() method for ages and we never had any trouble with it, but i guess it's your second version?! Please verify and comment. (Ensure you call this after your views are created.)
public static int getDeviceWidth(Activity activity) {
Display display = activity.getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
return size.x;
}
Otherwise i would try to get the y-position (or width) of an dummy layout which has sets its width to match_parent.
And test your getWidth on start and after app is running (f.e. on button click). Does it return wrong width during run time too?
In my method, I haven't run into any issues before in terms of not locating the right location of something or the exact size of any Android screen.
My method finds the screen size in inches and the screen height and width in pixels and inches
In my app this method is how I check if my app is being used by a tablet:
private void tabletChanges() {
DisplayMetrics dm = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
int height = dm.heightPixels;
int dens = dm.densityDpi;
double wi = (double)width/dm.xdpi;
double hi = (double)height/dm.ydpi;
double x = Math.pow(wi,2);
double y = Math.pow(hi,2);
double screenInches = Math.sqrt(x+y);
if(screenInches >= 7){
//Do certain things
}
}
Hi i want to fit my app to all screen sizes and to do so i need to get the screen width and height.
but if i use this code for example
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int height = displaymetrics.heightPixels;
int width = displaymetrics.widthPixels
It gives me the pixels so there can happen a situation that it gives me the same dimentions for tablet and a smaller phone.
how can i get the actual screen size?
and another thing, i have a game i made with bitmaps and on my phone it is working fine but on tablet the bitmaps are too small how can i resize them according to screen size?
You need screen density and pixel size. (Number of pixels) / (dots per inch) gives screen size in inches.
See: getting the screen density programmatically in android?
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int height = displaymetrics.heightPixels;
int width = displaymetrics.widthPixels
int realWidth = (int)((float)width/metrics.density);
int realHeight = (int((float)height/metrics.density);
Answer to the second question depends on how are you loading your bitmaps. You should provide multiple sizes for different devices. Then you can use built-in scaling mechanism - simply place bitmaps in their matching drawable-(dpi)-(screen size) folders. Other way you would have to load images from assets folder and scale them if necessary.
For your 2nd problem of bitmap appearing too small on tablet, try to nine patch your image and then place those images in their respective folders (hdpi, mdpi, xhdpi, xxhdpi)
Make sure you use the high quality resolution image for nine patching otherwise your image will get stretch (poor quality).
You can nine patch your image from here also nine patching image
try this:
Display display = activity.getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
You can get screen dimensions with this code:
public int getScreenHeight() {
return getDisplay().getHeight();
}
private Display getDisplay() {
return ((WindowManager) getContext().getSystemService(
Context.WINDOW_SERVICE)).getDefaultDisplay();
}
public int getScreenWidth() {
return getDisplay().getWidth();
}
Try this.
Add this to onCreate() Method. Declare point!
WindowManager wm = ((WindowManager) getSystemService(WINDOW_SERVICE));
Display display = wm.getDefaultDisplay();
point = getDisplaySize(display);
//here is the method to get device size.
#Deprecated
#SuppressLint("NewApi")
private static Point getDisplaySize(final Display display) {
final Point point = new Point();
try {
display.getSize(point);
} catch (java.lang.NoSuchMethodError ignore) { // Older device
point.x = display.getWidth();
point.y = display.getHeight();
}
return point;
}
So I have been experimenting today with making an Android Application, but I have tried the LineairLayout to make a welcom screen for my application, but I cannot get it right..
So I tried RelativeLayout and I saw I can move my ImageViews and buttons to everywhere. So my question is if I will move the items to places like center, bottom left and bottom right. Would this be a problem or all phones since not all phones have the same dimensions?
public class WelcomeActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.welcome_screen_relative);
final ImageView logo = (ImageView) findViewById(R.id.myImageView);
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
int displayHeight = metrics.heightPixels;
int displayWidth = metrics.widthPixels;
float scaledDensity = metrics.scaledDensity;
BitmapFactory.Options dimensions = new BitmapFactory.Options();
dimensions.inJustDecodeBounds = true;
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.log, dimensions);
int imageHeight = dimensions.outHeight;
int imageWidth = dimensions.outWidth;
float percentageToMoveViewDown = (float) 20.0;
float viewY_float = (float) ((displayHeight / 100.0) * percentageToMoveViewDown);
int viewY_int = Math.round(viewY_float);
RelativeLayout.LayoutParams view_Layout_params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
view_Layout_params.topMargin = viewY_int;
logo.setLayoutParams(view_Layout_params);
logo.getLayoutParams().height = imageHeight;
logo.getLayoutParams().width = imageWidth;
}
Thats depends. If you give objects a fixed size of course it will. for dp/dpi make sure to test it in Emu or real devices. You can also create density and orientation specific layout to support many screens. Consider that there are not only changes in size but also aspect ration and resolution and DPI.
For most apps RelativeLayout is might be the right approach.
You can read an excelent article about it here: http://developer.android.com/guide/practices/screens_support.html
If the items have fixed sizes you always will have trouble with some phones. For the big ones it may be too small, for the small ones too big...
In my experience Androids small/normal/large screens won't help you much for configuring, since the differences are just too big.
If you want to make sure everything sits where it belongs to, you could get the device metrics. That way you don't even need to rely on center, but you can work with percentages to place everything where you want it to be. Plus you can set the sizes in percentage, which is great. Like you could say I want a button thats width is 50% of the screen, no matter how large the screen is. Its more work (maybe even overkill), but I really like that approach. Once you figured it out its basically just a bit copy paste at the start of your classes.
Example:
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
int displayHeight = metrics.heightPixels;
int displayWidth = metrics.widthPixels;
float scaledDensity = metrics.scaledDensity;
//move some View 20% down:
float percentageToMoveViewDown = (float) 20.0;
float viewY_float = (float) ((displayHeight / 100.0) * percentageToMoveViewDown);
int viewY_int = Math.round(viewY_float);
RelativeLayout.LayoutParams view_Layout_params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
view_Layout_params.topMargin = viewY_int;
view.setLayoutParams(view_Layout_params);
//even works with text size for a TextView:
float percentageToResizeTextViewTextSize = (float) 3.1;
float textViewTextSize_float = (float) ((displayHeight / 100.0) * percentageToResizeTextViewTextSize);
int textViewTextSize_int = Math.round(textViewTextSize_float / scaledDensity);
textView.setTextSize(textViewTextSize_int);
Just a side note for the overkill thing: This should be only necessary if you want to support small devices (they mostly run something like android 2.3, but still are sold as budget phones) and big devices as well, but the trouble with the big ones is not as big as the trouble with the small ones. I personally rather put more effort in it than less, you never know.
Edit: ImageView by code
The easiest way is to do it hybridly, using xml and code. Note that you will have to change width and height if you set it to 0 in xml like in the following example.
Just place it in the xml where you would anyways, somewhere in your RelativeLayout.
In your xml:
<ImageView
android:id="#+id/myImageView"
android:layout_width="0dp"
android:layout_height="0dp" />
In your Code:
ImageView myImageView = (ImageView)findViewById(R.id.myImageView);
You now can work with that myImageView as I did it with view and textView. You can even set the image right here in code.
This imageView with the size of 0,0 is now placed where it would have been before. Now you could set the width to like 50% of the screenwidth and the height to...lets say 40% of the screen height. Then You would need to place it. If you want to center it you know that there must be 25% of the screen on each side, so you can add 25% as left and right margin.
Edit 2: maintain original imagesize
If you want to keep the original size of a image in your drawables, you can get its width and height like this:
BitmapFactory.Options dimensions = new BitmapFactory.Options();
dimensions.inJustDecodeBounds = true;
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.yourImageName, dimensions);
int imageHeight = dimensions.outHeight;
int imageWidth = dimensions.outWidth;
Now that you have that, you could use it to calculate the aspect ratio to keep it.
Now since you know the devices width and height, you can easily calculate how much of the screen this image will need.(imageheight/screenheight*100 = your percentage of the screen you want the imageviews height to be). So the Height you set to the imageview would be displayHeight / 100 * (imageHeight / displayHeight * 100).
How to place that?
Now if you take a Screenheight of 100 and a imageheight of 80 you get 80%. You would now take this percentage and divide it from 100. Divide that /2 and you know how much space you would have as top and bottom margins if you wanted it to be placed in the middle of the screen (you would have to do the same for width).
Caution: If you don't want it to be relative to the screensize but the original size, that percentage approach is kind of pointless. If you do to your image what I just described, it may still be too big for small devices and too small for big ones. Instead you could think about what percentage would look good in proportion to the rest of the stuff on the screen and resize it to that, since it would have that relative size on all devices.
Edit 3:
Since you load the image in original size, it will be small on big devices if it is a small image.
//first you need to know your aspect ratio.
float ratio = imageWidth / imageHeight;
//lets say you wanted the image to be 50% of the screen:
float percentageToResizeImageTo = (float) 50.0;
float imageX_float = (float) ((displayHeight / 100.0) * percentageToResizeImageTo);
int imageX_int = Math.round(imageX_float);
//now you know how much 50% of the screen is
imageWidth = imageX_int;
imageHeight = imageWidth * ratio;
RelativeLayout.LayoutParams view_Layout_params = new RelativeLayout.LayoutParams(imageHeight, imageWidth);
view_Layout_params.topMargin = viewY_int;
logo.setLayoutParams(view_Layout_params);
logo.setScaleType(ImageView.ScaleType.Fit_XY);
I have countdown functionality in my app.
Every second a timer sets the current time to a TextView.
So strings are: "56:05","56:04","56:03","56:02"...
I want to make the text size as big as possible
Therefore I've written the following code.
private void measureAndSetText(String text) {
Paint pMeasure = new Paint();
Integer iWidth = _tvContent.getWidth();
Float maxTextSize = 1000f;
pMeasure.setTextSize(maxTextSize);
pMeasure.setFakeBoldText(true);
Float fCurrentWidth = pMeasure.measureText(text);
while (fCurrentWidth > iWidth) {
pMeasure.setTextSize(maxTextSize -= 1);
fCurrentWidth = pMeasure.measureText(text);
}
_tvContent.setText(text);
_tvContent.setTextSize(TypedValue.COMPLEX_UNIT_PX, maxTextSize);
}
This code seems to work on my Note2, Lg Optimus 4x HD, Galay ACE and some others.
But not on my Xperia Z in landscape mode.
I guess the reason is the Full Hd Display but I don't understand why.
On the Xperia Z just the ":" sign is displayed in landscape mode. So I think the text is wrapped but I don't know why.
It would make sense to me if the text size I set to it is higher than the screen height (in landscape mode this is actually screen width -> 1080) but this isn't the case.
When I try to set a longer text -> "asdfasd asdf" it is correctly displayed.
Can someone point me to the problem?
Cheers,
Stefan
UPDATE:
I figured out that my iWidth variable which holds the width of my TextView (_tvContent.getWidth()) has the value 1770.
How can that be since my Xperia Z has just 1920x1080???
So I thought that it may be a failure in TextView.getWidth() and added the following code:
Display display3 = getWindowManager().getDefaultDisplay();
Point size3 = new Point();
display3.getSize(size3);
int width = size3.x;
Display display1 = getWindowManager().getDefaultDisplay();
int width1 = display1.getWidth(); // deprecated
int height1 = display1.getHeight(); // deprecated
Display display = getWindowManager().getDefaultDisplay();
Integer iWidth = display.getWidth(); // deprecated
int height = display.getHeight(); // deprecated
Results:
Point(1080, 1776)
Display id 0: DisplayInfo{"Integrierter Bildschirm", app 1080 x 1776, real 1080 x 1920, largest app 1794 x 1701, smallest app 1080 x 1005, 60.0 fps, rotation 0, density 480, 442.451 x 443.345 dpi, layerStack 0, type BUILT_IN, address null, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS}, DisplayMetrics{density=3.0, width=1080, height=1776, scaledDensity=3.0, xdpi=442.451, ydpi=443.345}, isValid=true
Is this a Bug on site of Sony?
After I implemented my own TextView with its own OnDraw I've seen that there is an error in LogCat: ERROR/OpenGLRenderer(2503): Font size to large to fit in cache.
After a short research I figgured out that this is really a Bug in Android.
Addding this line to my custom TextView did the trick for me:
this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
I have a tablet and a phone. Can I show 2*3 in the tablet and 2*2 in the phone properly. The activity only contains a gridview.
Thank you for your help!
Your question isn't clear. There are fragments which can be used to make/run many different sizes.of views fornyour application.
You can get the screen inches using some code. So you can separate tab and phone.
String inputSystem;
inputSystem = android.os.Build.ID;
Log.d("hai",inputSystem);
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth(); // deprecated
int height = display.getHeight(); // deprecated
Log.d("hai",width+"");
Log.d("hai",height+"");
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
double x = Math.pow(width/dm.xdpi,2);
double y = Math.pow(height/dm.ydpi,2);
double screenInches = Math.sqrt(x+y);
Log.d("hai","Screen inches : " + screenInches+"");