Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing on Canvas issue in high end devices

I want to draw a SeekBar on canvas programmatically. I wrote code to set the LayoutParams of the SeekBar based on device density. I am using switch case with device density like

final DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
if(metrics.densityDpi <= DisplayMetrics.DENSITY_LOW){
        zoomBarParams = new LinearLayout.LayoutParams(18,
                LayoutParams.FILL_PARENT);
        } else if (metrics.densityDpi <= DisplayMetrics.DENSITY_MEDIUM){
            zoomBarParams = new LinearLayout.LayoutParams(24,
                    LayoutParams.FILL_PARENT);

        }else if (metrics.densityDpi <= DisplayMetrics.DENSITY_HIGH){
            zoomBarParams = new LinearLayout.LayoutParams(24,
                    LayoutParams.FILL_PARENT);

        }else if (metrics.densityDpi <= DisplayMetrics.DENSITY_XHIGH){
            zoomBarParams = new LinearLayout.LayoutParams(31,
                    LayoutParams.FILL_PARENT);


        }else if (metrics.densityDpi <= DisplayMetrics.DENSITY_XXHIGH){
            zoomBarParams = new LinearLayout.LayoutParams(60,
                    LayoutParams.FILL_PARENT);

        }else if (metrics.densityDpi <= DisplayMetrics.DENSITY_XXXHIGH){
            zoomBarParams = new LinearLayout.LayoutParams(60,
                    LayoutParams.FILL_PARENT);

        } else {
            zoomBarParams = new LinearLayout.LayoutParams(60,
                    LayoutParams.FILL_PARENT);

        }

But this isn't working in high end devices like Samsung Note 5, Galaxy S6 Edge etc..I believe that these devices comes in the density range XXXHIGH, then why is this not working?? Is there any relation between device density and screen size while drawing on canvas? Any help will be greatly appreciated.

like image 332
Jas Avatar asked Jun 23 '16 10:06

Jas


3 Answers

Why don't you try to get rid of all the if else cases and make something generic? Since you need to put different pixel values depending on the screen size, you can use dp instead.

You can get px from dp depending on the screen density of the device and use that in LayoutParams.

public static float convertDpToPixel(float dp, Context context){
    Resources resources = context.getResources();
    DisplayMetrics metrics = resources.getDisplayMetrics();
    float px = dp * ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT); // You can cache "((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT)" to avoid re-calculation.
    return px;
}

So you will create the param like this:

zoomBarParams = new LinearLayout.LayoutParams(convertDpToPixel(DP_VALUE, context),
                LayoutParams.FILL_PARENT);

where DP_VALUE will remain constant across all devices.

I hope this might solve your problem.

like image 156
Rohit Arya Avatar answered Nov 07 '22 09:11

Rohit Arya


Problem is there is not any generic code for this problem.
If you want original density then you can use metrics.xdpi and metrics.ydpi for horizontal and vertical density respectively.

or go follow this code:

public static String getDensity(Resources resources) {
    switch (resources.getDisplayMetrics().densityDpi) {
        case DisplayMetrics.DENSITY_LOW:
            return "ldpi";
        case DisplayMetrics.DENSITY_MEDIUM:
            return "mdpi";
        case DisplayMetrics.DENSITY_HIGH:
            return "hdpi";
        case DisplayMetrics.DENSITY_XHIGH:
            return "xhdpi";
        case DisplayMetrics.DENSITY_XXHIGH:
            return "xxhdpi";
        case DisplayMetrics.DENSITY_XXXHIGH:
            return "xxxhdpi";
        case DisplayMetrics.DENSITY_TV:
            return "tvdpi";
        default:
            return "unknown";
    }

A very depth explanation of this topic is given by this guy here :

https://stackoverflow.com/a/33789580/5476209

also check DisplayMetrics section in Android developers documentation

like image 24
TapanHP Avatar answered Nov 07 '22 08:11

TapanHP


If you are working on canvas, my recommendation to play with pixels only. In stead of dpi you can use percentage width and height according to your requirement. That will best suit and work on every device. For example if you need a seekbar of 600 x 128px for the screen size 800 x 1280 px. Then it is like 75% of width and 10% of height. Now apply this percentage by code-

DisplayMetrics dm = getResources().getDisplayMetrics();
int seekBarWidth= dm.widthPixels * 75 / 100;
int seekBarHeight= dm.heightPixels * 10 / 100;

And this will work for all screen sizes perfectly. Let me know in case of further assistance :)

like image 22
Neo Avatar answered Nov 07 '22 09:11

Neo