I'm writing a program for android. I read that the layout-swNdp notation could be used only on SDK 13 level ..But I want the app to adapt to screens 540x960 also on older android versions..like 2.0 2.2
It's possible to do this without using the layout-swNdp folder ?
If you want to do that programatically, you can get the height and width with the Display object:
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
final int height = display.getHeight();
final int width = display.getWidth();
And get the current API level with:
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
And then you can use a specific layout for those devices by calling setContentView() under an if condition:
if ((currentapiVersion <= android.os.Build.VERSION_CODES.FROYO) && (height == 960) &&(width == 540)) {
setContentView(R.layout.your_special_layout);
} else {
setContentView(R.layout.your_main_layout);
}
Hope that helps!
Related
Hello I want to ask about the most efficient way to adjust layout in all devices mobile and tablets sometimes I can't use wrap_content and layout_weight
I set size in some percentage to the device size in java like this:
ImageView img;
Display display = getWindowManager().getDefaultDisplay();
width = display.getWidth();
height = display.getHeight();
img.getLayoutParams().width = width* 7 / 10;
and when rotating screen I use this method to change percentage
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE&& getResources().getBoolean(R.bool.isTablet)) {
width=(int) (width * 0.7);
}
I am asking If this procedure is more efficient than using multi XML files for each screen size / orientation
Actually it depends on the scenario. Sometimes maintaining xml is efficient and easy sometimes dynamic calculation is necessary. You can go through the link https://developer.android.com/guide/practices/screens_support.html . It will give you some ideas. In your above code for width/height calculation sometimes you may not get proper result for some devices. Below is the code that will support all version of android device Resolution(Width, Height) accurately at runtime.
private void calculateDeviceResolution(Activity context) {
Display display = context.getWindowManager().getDefaultDisplay();
if (Build.VERSION.SDK_INT >= 17) {
//new pleasant way to get real metrics
DisplayMetrics realMetrics = new DisplayMetrics();
display.getRealMetrics(realMetrics);
realWidth = realMetrics.widthPixels;
realHeight = realMetrics.heightPixels;
} else if (Build.VERSION.SDK_INT >= 14) {
//reflection for this weird in-between time
try {
Method mGetRawH = Display.class.getMethod("getRawHeight");
Method mGetRawW = Display.class.getMethod("getRawWidth");
realWidth = (Integer) mGetRawW.invoke(display);
realHeight = (Integer) mGetRawH.invoke(display);
} catch (Exception e) {
//this may not be 100% accurate, but it's all we've got
realWidth = display.getWidth();
realHeight = display.getHeight();
Constants.errorLog("Display Info", "Couldn't use reflection to get the real display metrics.");
}
} else {
//This should be close, as lower API devices should not have window navigation bars
realWidth = display.getWidth();
realHeight = display.getHeight();
}
}
I want to add image resources to an Android app that won't be used for icons. I wanted to know what is the right way of doing it while supporting multiple device screen sizes. The only solution I can think of is resizing the image to different pixel (width, height) combinations and storing them in their appropriate drawable folders.
For images that are icons, I use the Android studio image asset tool to automatically generate different sized icons. I want that for images that are not icons(won't be placed in the toolbar and similar places).
Solution that worked for me
Used Android Asset Studio, Generic Icon Generator
to generate the resource images for the different device resolutions.
I think you can try this:
Create folder drawable-nodpi and put your images inside it.
Use this code to find the width of the device:
public static int getWidth() {
int width = 400;
try {
WindowManager wm = (WindowManager) DataBackApplication.getInstance().getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
if (Build.VERSION.SDK_INT > 12) {
Point size = new Point();
display.getSize(size);
width = size.x;
} else {
width = display.getWidth(); // Deprecated
}
} catch (Exception e) {
e.printStackTrace();
}
return width;
}
Build your layout.
Load image using this code:
int width = getWidth();
int imgWidth = width/6;
int imgHeight = width/9;
Glide.with(PermissionActivity.this)
.load(R.drawable.privacy_mobile_img)
.override(imgWidth, imgHeight )
.into(imgUserPerm);
Use Glide to load the image because it will resize it for small, mid, or any size device. I used width / 6 as an example, you can adjust as needed.
For normal uses you can use the DisplayMetrics class and get the "renderable" size, but I want to figure out the actual physical screen size, which includes the virtual buttons height.
On my Galaxy Nexus the reported size no matter what I tried is 1196x720, what can I use to get the physical one which is 1280x720 ? Same goes for Nexus 7, Nexus 4 and Nexus 10 devices.
UPDATE : This is the final code I now use, including the fix :
//Activity A = this;
DisplayMetrics displayMetrics = new DisplayMetrics();
WindowManager wm = (WindowManager) A.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
Display disp = wm.getDefaultDisplay();
int API_LEVEL = android.os.Build.VERSION.SDK_INT;
if (API_LEVEL >= 17)
{
disp.getRealMetrics(displayMetrics);
}
else
{
disp.getMetrics(displayMetrics);
}
int Width = displayMetrics.widthPixels;
int Height = displayMetrics.heightPixels;
You should use Display.getRealSize(Point) From the official docs here
The display area is described in two different ways.
The application display area specifies the part of the display that
may contain an application window, excluding the system decorations.
The application display area may be smaller than the real display area
because the system subtracts the space needed for decor elements such
as the status bar. Use the following methods to query the application
display area: getSize(Point), getRectSize(Rect) and
getMetrics(DisplayMetrics).
The real display area specifies the part
of the display that contains content including the system decorations.
Even so, the real display area may be smaller than the physical size
of the display if the window manager is emulating a smaller display
using (adb shell am display-size). Use the following methods to query
the real display area: getRealSize(Point),
getRealMetrics(DisplayMetrics).
The answer in the similar question seems to have a solution to get the real size of the display when API < 17 https://stackoverflow.com/a/15699681/601298
WindowManager w = activity.getWindowManager();
Display d = w.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
d.getMetrics(metrics);
// since SDK_INT = 1;
widthPixels = metrics.widthPixels;
heightPixels = metrics.heightPixels;
// includes window decorations (statusbar bar/menu bar)
if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 17)
try {
widthPixels = (Integer) Display.class.getMethod("getRawWidth").invoke(d);
heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(d);
} catch (Exception ignored) {
}
// includes window decorations (statusbar bar/menu bar)
if (Build.VERSION.SDK_INT >= 17)
try {
Point realSize = new Point();
Display.class.getMethod("getRealSize", Point.class).invoke(d, realSize);
widthPixels = realSize.x;
heightPixels = realSize.y;
} catch (Exception ignored) {
}
I was given a task to provide devices with < 1024x800 resolution with one group of layouts and >=1024x800 - with another.
Below there's some code I'm using. Regarding on _isTablet flag application can decide which layout it should use.
Do you think it's a decent tactic or should I consider another functionality for achieving resolution-based segregation of design layouts ? Thanks.
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
final int height = display.getHeight();
final int width = display.getWidth();
_leadingSideResolution = Math.max(height, width);
if (_leadingSideResolution <= HANDSET_LAYOUT_RESOLUTION) {
_isTablet = false;
} else if(_leadingSideResolution > HANDSET_LAYOUT_RESOLUTION
&& _leadingSideResolution <= TABLET_LAYOUT_RESOLUTION) {
_isTablet = true;
}
Try this code to check whether the device is tablet or not
public boolean onTablet()
{
int intScreenSize = context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
return (intScreenSize == Configuration.SCREENLAYOUT_SIZE_LARGE) // LARGE
|| (intScreenSize == Configuration.SCREENLAYOUT_SIZE_LARGE + 1); // Configuration.SCREENLAYOUT_SIZE_XLARGE
}
if(!onTablet())
{
setContentView(R.layout.not_tablet_layout);
}
else
{
setContentView(R.layout.tablet_layout);
}
For supporting android mobile devices and tablets, android has provided a very simple solution. You can get it from: http://developer.android.com/guide/practices/screens_support.html
From this please read:
1. How to Support Multiple Screen
2. Designing alternative layouts and drawables
3. Declaring Tablet Layouts for Android 3.2
4. Configuration examples
Is there a way to determine the dimension (width) of the menu bar of devices without hard menu buttons? (like the archos devices).
I need to know the usable dimension of the screen...
This method is very useful in order to set the layout padding in Android KitKat (4.4). Using this, you can avoid the soft buttons bar overlapping over your layout.
The getRealMetrics method is only available with API 17 and +, but I'm only using the following method I wrote for devices on API 19+
#SuppressLint("NewApi")
private int getSoftbuttonsbarHeight() {
// getRealMetrics is only available with API 17 and +
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
return 0;
}
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int usableHeight = metrics.heightPixels;
getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
int realHeight = metrics.heightPixels;
return realHeight > usableHeight ? realHeight - usableHeight : 0;
}
Tested upon Nexus 5 & Nexus 7 2013.
A very late answer but for anyone that encounters this problem. A simple way to get the amount of usable space offsetting any soft keys/navigation bar or even the status bar, is to use getWindowVisibleDisplayFrame(Rect) from the Apps DecorView. This will load a Rect object with the dimension of the display that is actually usable.
Since you cannot directly get a reference to the Activiy's DecorView, you need to first get the Activity's window using the accessor method, getWindow(). This will return the window object that holds the Activity and other screen elements. To get the decorView that contains the activity as well as the screen decorations i.e. the status bar, navigation bar/soft button bar, call accessor method getDecorView(). Once your have a reference to the DecorView call getWindowVisibleDisplayFrame(Rect) and you will have a loaded Rect object.
Starting Andorid 3.2, the height of system status bar is not included in DisplayMetrics's height, you have to use undocumented APIs (Display.getRawWidth() and Display.getRawHeight()) to get the physical screen width or height.
Method mGetRawW = Display.class.getMethod("getRawWidth");
Method mGetRawH = Display.class.getMethod("getRawHeight");
int nW = (Integer)mGetRawW.invoke(dp);
int nH = (Integer)mGetRawH.invoke(dp);
UPDATED: For API 13-16, you have to use the above code to get real width/height. For API 17+, you can now use the new public API, Display.getRealSize()
for me, in android note 10, I need to get navigation bar height by dimen:
fun getSoftNavigationBarSize(resources: Resources): Int {
var result = 0
val resourceId: Int = resources.getIdentifier("navigation_bar_height", "dimen", "android")
if (resourceId > 0) {
result = resources.getDimensionPixelSize(resourceId)
}
return result
}