简体   繁体   English

自定义Android UI和多屏支持

[英]Custom Android UI and multiple screen support

I know these kinds of questions have been asked before, but I haven't seen one of this type yet. 我知道以前曾问过这类问题,但我还没有看到这类问题。 I am creating a custom android UI using android canvas. 我正在使用android canvas创建自定义android UI。 I have created all the necessary drawables for it and put them in the appropriate folders and I am now drawing the UI with this code: 我已经为其创建了所有必需的可绘制对象,并将它们放置在适当的文件夹中,现在使用以下代码来绘制UI:

public class MainMenuView extends View {

private Bitmap pasteImage;
private Bitmap adventureLetters;
private Bitmap settingsLetters;
private Bitmap quitLetters;
private Bitmap backgroundImage;
private DisplayMetrics metrics;

public MainMenuView(Context context){
    super(context);
    pasteImage = decodeFile(R.drawable.paste, 200, true);
    Log.w("Visina imagea", String.valueOf(pasteImage.getHeight()));
    pasteImage.recycle();
}

public MainMenuView(Context context, AttributeSet attrSet){
    super(context, attrSet);
    metrics = context.getResources().getDisplayMetrics();
    pasteImage = decodeFile(R.drawable.paste, 330, true);
    adventureLetters = decodeFile(R.drawable.adventureletters, 100, true);
    settingsLetters = decodeFile(R.drawable.settingsletters, 100, true);
    quitLetters = decodeFile(R.drawable.quitletters, 50, true);
    Log.w("Je li image null? ", pasteImage == null ? "da" : "ne");
    backgroundImage = decodeFileScaled(R.drawable.toothpastebackground);
    backgroundImage = Bitmap.createScaledBitmap(backgroundImage, metrics.widthPixels - 20, metrics.heightPixels, true);
    //adventureLetters = BitmapFactory.decodeResource(getResources(), R.drawable.adventureletters);
    //settingsLetters = BitmapFactory.decodeResource(getResources(), R.drawable.settingsletters);
    //quitLetters = BitmapFactory.decodeResource(getResources(), R.drawable.quitletters);
}

@Override
protected void onMeasure(int widthMeasure, int heightMeasure){
    setMeasuredDimension(calculateMeasure(widthMeasure), calculateMeasure(heightMeasure));
    Log.w(String.valueOf(calculateMeasure(widthMeasure)), "Izmjereno");
}

private static final int DEFAULT_SIZE = 70;
private int calculateMeasure(int measure) {

    int result = (int)(DEFAULT_SIZE * getResources().getDisplayMetrics().density);
    int specMode = MeasureSpec.getMode(measure);
    int specSize = MeasureSpec.getSize(measure);

    if(specMode == MeasureSpec.EXACTLY) result = specSize;
    else if(specMode == MeasureSpec.AT_MOST){
        result = Math.min(result, specSize);
    }

    return result;
}

@Override
protected void onDraw(Canvas canvas){
    super.onDraw(canvas);
    if(canvas == null) Log.w("Canvas je null", "Da");
    else Log.w("Canvas nije null", "ne");
    Log.w("Usao u onDraw", "u onDraw sam sad");
    canvas.save();
    if(pasteImage == null) Log.w("Slika je null", "null slika");
    canvas.drawBitmap(backgroundImage, 0, 0, null);
    Log.w("Dimenzije slike sirina x visina bg", backgroundImage.getWidth() + " " + backgroundImage.getHeight());
    canvas.drawBitmap(pasteImage, 110, 420, null);
    canvas.drawBitmap(adventureLetters, 50,  60, null);
    canvas.drawBitmap(settingsLetters, 80,  60, null);
    canvas.drawBitmap(quitLetters, 100,  60, null);
    pasteImage.recycle();
    adventureLetters.recycle();
    settingsLetters.recycle();
    quitLetters.recycle();
    canvas.restore();
}

private Bitmap decodeFile(int id, int size, boolean resize){

        //Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(getResources(), id, o);

        //The new size we want to scale to
        final int REQUIRED_SIZE = size;

        //Find the correct scale value. It should be the power of 2.
        int scale = 1;
        while(o.outWidth/scale/2 >= REQUIRED_SIZE && o.outHeight/scale/2 >= REQUIRED_SIZE)
            scale*=2;

        //Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        return BitmapFactory.decodeResource(getResources(), id, o2);

}

private Bitmap decodeFileScaled(int id){

    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(getResources(), id, options);
    Log.w("Sirina x visina displaya", metrics.widthPixels + "x" +   metrics.heightPixels);
    options.inSampleSize = calculateScale(options, metrics.widthPixels, metrics.heightPixels);

    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(getResources(), id, options);
}

private int calculateScale(BitmapFactory.Options options, int reqWidth, int reqHeight){

    final int rawHeight = options.outHeight;
    final int rawWidth = options.outWidth;
    int inSampleSize = 1;

    if (rawHeight > reqHeight || rawWidth > reqWidth) {

        // Calculate ratios of height and width to requested height and width
        final int heightRatio = Math.round((float) rawHeight / (float) reqHeight);
        final int widthRatio = Math.round((float) rawWidth / (float) reqWidth);

        // Choose the smallest ratio as inSampleSize value, this will guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }

    return inSampleSize;
}
}

You can see immediately that I'm using some hardcoded values for positioning on screen. 您可以立即看到我正在使用一些硬编码值在屏幕上定位。 Can you give me some advice on how to code it so that it appears as it should on every screen(especially medium and high dimensions). 您能给我一些如何编码的建议,以便它在每个屏幕上(特别是中尺寸和高尺寸)都应显示。 As it should means no blurring tearing empty space and so on. 因为这应该意味着没有模糊的撕裂空白空间等等。 If you need any more info let me know in the comments and thank you very much! 如果您需要更多信息,请在评论中让我知道,非常感谢!

You should always use positions relatives to the screen. 您应该始终在屏幕上使用位置亲戚。 For example: 例如:

float left = getScreenSize().x * 0.10f;
float top = getScreenSize().y * 0.10f;

canvas.drawBitmap(pasteImage, left, top, null);

private float getScreenSize() {
     WindowManager windowManager = (WindowManager) getContext.getSystemService(Context.WINDOW_SERVICE);
     Display display = windowManager.getDefaultDisplay();
     Display display = getWindowManager().getDefaultDisplay();
     Point size = new Point();
     display.getSize(size);
     return size;
}

But If you are going to use absolute values, you should do it in dp, not px. 但是,如果要使用绝对值,则应使用dp而不是px。

Resources resources = getResources();

float left = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 140, resources.getDisplayMetrics());

float top = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 140, resources.getDisplayMetrics());

canvas.drawBitmap(pasteImage, left, top, null);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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