简体   繁体   中英

Make bitmap size and position the same on every device

I've been trying to figure out how to do it, I have the size of the screen and the size of the emulator I use, how do I change the size to fit all devices (Including tablets and phones) and also position them correctly because it seems like the X and Y on a tablet is different than one that is on the phone.

EDIT:

I tried converting pixels to DPI that way:

    public CreatorView(Context c) {
    super(c);
    this.c=c;


    WindowManager wm = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    this.screenw= display.getWidth();
    this.screenh=display.getHeight();


    this.PixelDetect   = BitmapFactory.decodeResource(   getResources(),   R.drawable.custom_pixel);
    this.smallpixel   = Bitmap.createScaledBitmap(PixelDetect, (int)getPixelsFromDip(3,c), (int)getPixelsFromDip(3,c), false);


    this.grass=BitmapFactory.decodeResource(getResources(), R.drawable.block_grass);
    this.grassSide=BitmapFactory.decodeResource(getResources(), R.drawable.block_grassside);
    this.grassTop=BitmapFactory.decodeResource(getResources(), R.drawable.block_grasstop);
    this.orange=BitmapFactory.decodeResource(getResources(), R.drawable.block_cube1);
    this.dirt=BitmapFactory.decodeResource(getResources(), R.drawable.block_dirt);
    this.dirt2=BitmapFactory.decodeResource(getResources(), R.drawable.block_dirt2);
    this.dirt3=BitmapFactory.decodeResource(getResources(), R.drawable.block_dirt3);
    this.arrowno=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_noclick);
    this.arrown=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_normal);
    this.arrowl=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_left);
    this.arrowr=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_right);
    this.arrowu=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_up);
    this.arrowd=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_down);
    this.arrowul=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_upperleft);
    this.arrowur=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_upperright);
    this.arrowdl=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_downleft);
    this.arrowdr=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_downright);
    this.arrowno=Bitmap.createScaledBitmap(arrowno, arrowno.getWidth()*3, arrowno.getHeight()*3, false);
    this.save=BitmapFactory.decodeResource(getResources(), R.drawable.button_save);
    this.bin_Empty=BitmapFactory.decodeResource(getResources(), R.drawable.bin_empty);
    this.bin_Full=BitmapFactory.decodeResource(getResources(), R.drawable.bin_full);
    this.bin_Empty=Bitmap.createScaledBitmap(bin_Empty, bin_Empty.getWidth()*3, bin_Empty.getHeight()*3, false);
    this.bin_Full=Bitmap.createScaledBitmap(bin_Full, bin_Full.getWidth()*3, bin_Full.getHeight()*3, false);
    this.arrown=Bitmap.createScaledBitmap(arrown, arrown.getWidth()*3, arrown.getHeight()*3, false);
    this.arrowl=Bitmap.createScaledBitmap(arrowl, arrowl.getWidth()*3, arrowl.getHeight()*3, false);
    this.arrowr=Bitmap.createScaledBitmap(arrowr, arrowr.getWidth()*3, arrowr.getHeight()*3, false);
    this.arrowu=Bitmap.createScaledBitmap(arrowu, arrowu.getWidth()*3, arrowu.getHeight()*3, false);
    this.arrowd=Bitmap.createScaledBitmap(arrowd, arrowd.getWidth()*3, arrowd.getHeight()*3, false);
    this.arrowul=Bitmap.createScaledBitmap(arrowul, arrowul.getWidth()*3, arrowul.getHeight()*3, false);
    this.arrowur=Bitmap.createScaledBitmap(arrowur, arrowur.getWidth()*3, arrowur.getHeight()*3, false);
    this.arrowdl=Bitmap.createScaledBitmap(arrowdl, arrowdl.getWidth()*3, arrowdl.getHeight()*3, false);
    this.arrowdr=Bitmap.createScaledBitmap(arrowdr, arrowdr.getWidth()*3, arrowdr.getHeight()*3, false);

    Menu_Add(arrowno,0,true,"arrows");
    Menu_Add(bin_Empty,1,false,"bin");
    Menu_Add(save,2,false,"save");
    Menu_Add(grassTop,1,true,"grasstop");
    Menu_Add(grassSide,2,true,"grassside");
    Menu_Add(grass,3,true,"grass");
    Menu_Add(dirt,4,true,"dirt");
    Menu_Add(orange,5,true,"orange");
    arrowsp=new Point();
    arrowsp.x=0;
    arrowsp.y=0;
}
private void Menu_Add(Bitmap b,int order,boolean vertical,String name)
{
    Point p=new Point();
    if(order==0){
        p.x=0;
        p.y=0;
        MenuButton m=new MenuButton(order,b , vertical, p,name);
        menuButtonList.add(m);
    }
    else{
        for (MenuButton m : menuButtonList) {
            if((m.isVertical()==vertical||order==1)&&m.getOrder()+1==order ){
                if(vertical){
                    p.x=0;
                    p.y=m.getP().y+m.getBit().getHeight()+(int)getPixelsFromDip(2,c);
                }
                else{
                    p.x=m.getP().x+m.getBit().getWidth()+(int)(getPixelsFromDip(2,c));
                    p.y=0;
                }
                MenuButton m2=new MenuButton(order,b , vertical, p,name);
                menuButtonList.add(m2);
                return;
            }
        }
    }
}
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    Paint paintAlpha = new Paint();
    paintAlpha.setAlpha(200);
    canvas.drawARGB(255, 86, 194, 243);
    for(MenuButton m : menuButtonList){
        switch(m.getName()){
        case "bin":
            if(bin_isEmpty){
                canvas.drawBitmap(bin_Empty, getPixelsFromDip(m.getP().x,c), getPixelsFromDip(m.getP().y,c),paintAlpha);
                }
                else{
                    canvas.drawBitmap(bin_Full, getPixelsFromDip(m.getP().x,c), getPixelsFromDip(m.getP().y,c),paintAlpha);
                }
            break;
        case "arrows":
            canvas.drawBitmap(m.getBit(),getPixelsFromDip(m.getP().x,c),getPixelsFromDip(m.getP().y,c),paintAlpha);
            switch (arrowcheck) {
            case "normal":
                canvas.drawBitmap(arrown, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
                break;
            case "left":
                canvas.drawBitmap(arrowl, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
                break;
            case "right":
                canvas.drawBitmap(arrowr, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
                break;
            case "down":
                canvas.drawBitmap(arrowd, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
                break;
            case "up":
                canvas.drawBitmap(arrowu, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
                break;
            case "upleft":
                canvas.drawBitmap(arrowul, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
                break;
            case "upright":
                canvas.drawBitmap(arrowur, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
                break;
            case "downleft":
                canvas.drawBitmap(arrowdl, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
                break;
            case "downright":
                canvas.drawBitmap(arrowdr, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
                break;
            }
            break;
        default:
            canvas.drawBitmap(m.getBit(),getPixelsFromDip(m.getP().x,c),getPixelsFromDip(m.getP().y,c),paintAlpha);
            break;
        }
    }
}
public static float getPixelsFromDip(float dip,Context context)
{
    //TODO move this to aplication class?
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, context.getResources().getDisplayMetrics()); 
}

this is how it shows in the emulator (correct): http://puu.sh/ehhHp/05c1530218.png this is how it shows in my phone: http://puu.sh/ehhKX/b28ee357e3.png please help :(

What you don't want to do is to use pixels. What you most probably also don't want to do is to speficy the width/height using dps unless you're prepared to set different values for your different resolution devices (by specifying the values in @dimen and overriding them for different sizes).

If you know approximately how much of the screen width (or height) you would like your ImageView to occupy, the easiest thing you can do to achieve it is to use weights within a LinearLayout .

An example would be this (handwritten and missing all the NS prefixes)

<LinearLayout
 ...
 ...
 orientation=vertical>

    <some empty filler here with weight=1 and width="match_parent"/>
    <ImageView 
     ...
     ...
     width="match_parent"
     scaleType=fitCenter (or whatever works for your images)
     weight=1 />

    <some empty filler here with weight=1 width="match_parent"/>
</LinearLayout>

What this would do is to make sure your ImageView takes 1/3rd of the screen width as determined by weights. You then control the image scaling by setting the correct scaleType. This will work universally across all phone sizes and tablets and will always take 1/3rd of the width of the screen regardless of the resolution or the orientation of the device (which may or may not be what you want).

You can also play around with the weights if you want more/less than 1/3rd of the screen width for your images.

Other solutions (using dp for instance) are already mentioned but they're a bit more involved in that you have to override them for different resolutions as described above.

Positioning in terms of pixels will definitely differ as there are different type of devices with different DPI.

So declaring Imageview with widht, height in dp should serve your problem. Coming to position, it should be maintained Relatively or through gravity.

We need your code to understand what exactly the problem is and what more you need.

EDIT: Convert Dip to pixel and the apply it to your Bitmap size. It will maintain physical size and gets resolution according to device.

public static int convertDipToPixels(float dips)
{
    return (int) (dips * appContext.getResources().getDisplayMetrics().density + 0.5f);
}

Edit 2:

Just give a trail changing your loop with this code snippet and check it it replicates same on all devices

for (MenuButton m : menuButtonList) {
        if((m.isVertical()==vertical||order==1)&&m.getOrder()+1==order ){
            if(vertical){
                p.x=0;
                p.y=(int)getPixelsFromDip(100,c);
            }
            else{
                p.x=m(int)(getPixelsFromDip(100,c));
                p.y=0;
            }
            MenuButton m2=new MenuButton(order,b , vertical, p,name);
            menuButtonList.add(m2);
            return;
        }
    }

Why not use percents? As example - percent_x = device.widht / 100; And begin draw image in this position * percent_x? In every device if should be look similar, but with streches.

use dp to define width and height of image. Or we can calculate the percentage of image size of our screen.

ok if you use an xml layout just defing layout_width and layout_hight using density pixel value "10dp" for example. those scale with the screen size so you get the same result according to screen size.

if you use canvas then when you set the hight and width of an objecs use the following method:

/**
 * get width or hight as density independent pixels and return the real 
 * amount of pixels requiered for the current screen
 * used to programaticlly set width and hight using dip
 * @param dip - the amount of dip
 * @param context - the activity used in
 * @return - return the real amount of pixels required for the current screen
 */
public static float getPixelsFromDip(float dip,Context context)
{
    //TODO move this to aplication class?
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, context.getResources().getDisplayMetrics()); 
}

another option is to calculate max screen size, and the precent from it you need

here is the method for the max size:

/**
     * get maximum width and hight as dp avaliable in the screen
     * @param context
     * @return
     */
    public static float[] getMaxPixels(Context context)
    {
        //TODO move this to application class
        float result[]=new float[2];
        DisplayMetrics displayMetrics=context.getResources().getDisplayMetrics();
        float screenWidthInDp=displayMetrics.widthPixels/displayMetrics.density;
        float screenHeightInDp=displayMetrics.heightPixels/displayMetrics.density;
        result[0]=screenWidthInDp;
        result[1]=screenHeightInDp;
        return result;
    }

last but not least rule of thumb density is:mdpi=1, hdpi=1.5 and ldpi is 0.75 so once you get the pixels for one screen size you can multiply by those values to get a rough estimate for the value in the other enjoy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM