0

I have a custom view on my layout, which I setted up the width and height to be 300dp.

After some researching (Determining the size of an Android view at runtime), I found a way to programmatically get the custom view's width and height.

The issue is that the dimensions I get programmaticaly are not the same I setted up on the layout.

Apparently (after some tests) there is a pattern, where the dimensions I get programmatically is 1.5 bigger than the dimensions a setted on the layout.

Example:

android:layout_width="270dp"   >>  myView.getWidth() returns 405
android:layout_width="300dp"   >>  myView.getWidth() returns 450

Here is the code.

Any ideas please?

The layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">

<com.examples.danilofernandes.housemap.ViewForLayout
    android:id="@+id/layout"
    android:layout_width="270dp"
    android:layout_height="270dp" />

<Button
    android:id="@+id/button"
    android:text="hello"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/layout"/>

</RelativeLayout>

The class:

public class ViewForLayout extends View {

boolean DEBUG_TAG = ActivityForLayout.DEBUG_TAG;

// To use with the Toasts on this Activity.
Context context;

// To use with the Canvas.
Paint paint;

// To advise display orientation.
boolean displayInPortraitMode;

// The plant (bitmap) to be displayed.
int myHousePlant;

// ---

int myDisplayWidth;
int myDisplayHeight;
float myDisplayRatio;

// ---

int myLayoutViewWidth;
int myLayoutViewHeight;
float myLayoutViewRatio;

// ---

float differenceInHeight;
float differenceInWidth;

float scaledPhotoHeight_1;
float scaledPhotoWidth_1;

float scaledPhotoHeight_2;
float scaledPhotoWidth_2;

// ---

Bitmap originalPhoto;
Bitmap scaledPhoto;

float originalPhotoRatio;
float scaledPhotoRatio;

// ---

Rect motionRect;

float motionRectLeft;
float motionRectTop;
float motionRectBottom;
float motionRectRight;

boolean drawMotionRect;

// ---

Rect room1;
Rect room2;
Rect looby;
Rect terrace;
Rect kitchen;
Rect bathroom;
Rect livingRoom;
Rect diningRoom;
Rect accessHall;
Rect serviceArea;

Rect room1Adjunct;
Rect kitchenAdjunct;
Rect serviceAreaAdjunct;

// ---

int drawRoom1;
int drawRoom2;
int drawLooby;
int drawTerrace;
int drawKitchen;
int drawBathroom;
int drawLivingRoom;
int drawDiningRoom;
int drawAccessHall;
int drawServiceArea;

// ---

public ViewForLayout(Context context, AttributeSet attrs) {

    super(context, attrs);

    // Bind the context to the activity.
    this.context = context;

    // Makes all connections.
    initializeAllVariables();

    // The background color of the view
    setBackgroundColor(Color.BLACK);

    // Resize the picture so that all of it will be visible.
    resizePictureToFitIntoScreen();

}

public void initializeAllVariables(){

    // Paint setting up
    paint = new Paint();
    paint.setColor(Color.BLACK);

    // Motion rect information
    drawMotionRect = false;

    // Display data

    myDisplayWidth = ActivityForLayout.myDisplayWidth;
    myDisplayHeight = ActivityForLayout.myDisplayHeight;

    myDisplayRatio = (float) myDisplayHeight / myDisplayWidth;

    displayInPortraitMode = ActivityForLayout.displayInPortraitMode;

    // Layout date

    ViewTreeObserver viewTreeObserver = this.getViewTreeObserver();
    if (viewTreeObserver.isAlive()) {
        viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
            @Override
            public void onGlobalLayout() {
                ViewForLayout.this.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                myLayoutViewWidth = ViewForLayout.this.getWidth();
                myLayoutViewHeight = ViewForLayout.this.getHeight();
            }
        });
    }

    myLayoutViewRatio = (float) myLayoutViewHeight / myLayoutViewWidth;

    // Photo data

    myHousePlant = R.drawable.ilha_de_malaga_transparente;

    originalPhoto = BitmapFactory.decodeResource(getResources(), myHousePlant);
    originalPhotoRatio = (float) originalPhoto.getHeight() / originalPhoto.getWidth();

    // None room will be 'lighted up' at the first place

    drawRoom1 = -1;
    drawRoom2 = -1;
    drawLooby = -1;
    drawTerrace = -1;
    drawKitchen = -1;
    drawBathroom = -1;
    drawLivingRoom = -1;
    drawDiningRoom = -1;
    drawAccessHall = -1;
    drawServiceArea = -1;

    // The boundaries for all rooms in the house.

    room1 = new Rect(64 ,224,265,467);
    room2 = new Rect(146, 12,376,211);
    looby = new Rect(595, 12,736,94);
    terrace = new Rect(389,424,595,468);
    kitchen = new Rect(607,104,736,340);
    bathroom = new Rect(275,308,376,467);
    livingRoom = new Rect(389,215,595,410);
    diningRoom = new Rect(389, 12,595,215);
    accessHall = new Rect(296,224,389,295);
    serviceArea = new Rect(607,362,736,468);

    room1Adjunct = new Rect(265,224,283,296);
    kitchenAdjunct = new Rect(607,340,670,352);
    serviceAreaAdjunct = new Rect(607,352,670,362);

}

@Override
protected void onDraw(Canvas canvas) {

    // Whenever onDraw starts, paint color is set to black.
    paint.setColor(Color.BLACK);

    // Makes the picture to be draw on the center of the view.
    float drawInTheMiddleOfTheScreen_Width = (myDisplayWidth - scaledPhotoWidth_2)/2;
    float drawInTheMiddleOfTheScreen_Height = (myDisplayHeight - scaledPhotoHeight_2) /2;

    // Draw the picture
    canvas.drawBitmap(scaledPhoto, drawInTheMiddleOfTheScreen_Width, drawInTheMiddleOfTheScreen_Height, paint);

    // To makes the text (for debug info) more visible.
    paint.setColor(Color.RED);
    paint.setTextSize(25.0f);

    // Debug information.
    if(DEBUG_TAG) {
        canvas.drawText("Device Height: " + myDisplayHeight, 0, 25, paint);
        canvas.drawText("Device Width: " + myDisplayWidth, 0, 50, paint);
        canvas.drawText("Device Ratio is: " + myDisplayRatio, 0, 75, paint);

        canvas.drawText("Original Photo Height: " + originalPhoto.getHeight(), 0, 125, paint);
        canvas.drawText("Original Photo Width: " + originalPhoto.getWidth(), 0, 150, paint);
        canvas.drawText("Original Photo Ratio is: " + originalPhotoRatio, 0, 175, paint);

        canvas.drawText("Scaled Photo Height: " + scaledPhoto.getHeight(), 0, 225, paint);
        canvas.drawText("Scaled Photo Width: " + scaledPhoto.getWidth(), 0, 250, paint);
        canvas.drawText("Scaled Photo Ratio is: " + scaledPhotoRatio, 0, 275, paint);

        canvas.drawText("View Height: " + myLayoutViewHeight, 0, 325, paint);
        canvas.drawText("View Width: " + myLayoutViewWidth, 0, 350, paint);
        canvas.drawText("View Ratio is: " + myLayoutViewRatio, 0, 375, paint);
    }
    // Set the color to a transparent yellow
    paint.setColor(Color.argb(100,255,255,0));

    // Check which room was clicked by the user
    //     > 1st click - turns the light ON
    //     > 2nd click - turns the light OFF

    if(drawRoom1 > 0) {
        canvas.drawRect(room1, paint);
        canvas.drawRect(room1Adjunct, paint);
    }
    if(drawRoom2 > 0) {
        canvas.drawRect(room2, paint);
    }
    if(drawLooby > 0) {
        canvas.drawRect(looby, paint);
    }
    if(drawTerrace > 0) {
        canvas.drawRect(terrace, paint);
    }
    if(drawKitchen > 0) {
        canvas.drawRect(kitchen, paint);
        canvas.drawRect(kitchenAdjunct, paint);
    }
    if(drawBathroom > 0){
        canvas.drawRect(bathroom,paint);
    }
    if(drawLivingRoom > 0) {
        canvas.drawRect(livingRoom, paint);
    }
    if(drawDiningRoom > 0) {
        canvas.drawRect(diningRoom, paint);
    }
    if(drawAccessHall > 0) {
        canvas.drawRect(accessHall, paint);
    }
    if(drawServiceArea > 0) {
        canvas.drawRect(serviceArea, paint);
        canvas.drawRect(serviceAreaAdjunct, paint);
    }

    // The Rect that is drawn if the user click and drag the finger on the screen.
    if(drawMotionRect) {

        canvas.drawRect(motionRect, paint);

        // Makes the drawn motion rect to be erased from the screen on next onDraw call.
        drawMotionRect = false;

    }

}

@Override
public boolean onTouchEvent(MotionEvent event) {

    switch (event.getAction()) {

        case MotionEvent.ACTION_DOWN:

            motionRectLeft = event.getX();
            motionRectTop = event.getY();

            float xUserTouch = event.getX();
            float yUserTouch = event.getY();

            if(DEBUG_TAG) {
                Toast.makeText(context, "x = " + xUserTouch + ", y = " + yUserTouch, Toast.LENGTH_SHORT).show();
            }

            if (kitchen.contains((int)event.getX(), (int)event.getY()) || kitchenAdjunct.contains((int)event.getX(), (int)event.getY()) ) {
                drawKitchen = drawKitchen * (-1);

                // Call onDraw method
                invalidate();
            }

            if (room2.contains((int)event.getX(), (int)event.getY())) {
                drawRoom2 = drawRoom2 * (-1);

                // Call onDraw method
                invalidate();
            }

            if (room1.contains((int)event.getX(), (int)event.getY()) || room1Adjunct.contains((int)event.getX(), (int)event.getY()) ) {
                drawRoom1 = drawRoom1 * (-1);

                // Call onDraw method
                invalidate();
            }

            if (livingRoom.contains((int)event.getX(), (int)event.getY())) {
                drawLivingRoom = drawLivingRoom * (-1);

                // Call onDraw method
                invalidate();
            }

            if (diningRoom.contains((int)event.getX(), (int)event.getY())) {
                drawDiningRoom = drawDiningRoom * (-1);

                // Call onDraw method
                invalidate();
            }

            if (accessHall.contains((int)event.getX(), (int)event.getY())) {
                drawAccessHall = drawAccessHall * (-1);

                // Call onDraw method
                invalidate();
            }

            if (serviceArea.contains((int)event.getX(), (int)event.getY()) || serviceAreaAdjunct.contains((int)event.getX(), (int)event.getY()) ) {
                drawServiceArea = drawServiceArea * (-1);

                // Call onDraw method
                invalidate();
            }

            if (terrace.contains((int)event.getX(), (int)event.getY())) {
                drawTerrace = drawTerrace * (-1);

                // Call onDraw method
                invalidate();
            }

            if (looby.contains((int)event.getX(), (int)event.getY())) {
                drawLooby = drawLooby * (-1);

                // Call onDraw method
                invalidate();
            }

            if(bathroom.contains((int)event.getX(), (int)event.getY())){
                drawBathroom = drawBathroom * (-1);

                // Call onDraw method
                invalidate();
            }

            break;

        case MotionEvent.ACTION_MOVE:

            // Update the motionRect coordinated at every move.
            motionRectRight = event.getX();
            motionRectBottom = event.getY();

            // Create a new motion Rect to be draw at every move.
            motionRect = new Rect((int) motionRectLeft, (int) motionRectTop, (int) motionRectRight, (int) motionRectBottom);

            // Permission to draw the motion Rect
            drawMotionRect = true;

            // Call onDraw method
            invalidate();

            break;

        case MotionEvent.ACTION_UP:

            // Do nothing.

    }

    return true;

}

protected void resizePictureToFitIntoScreen(){

    // O redimensionamento da foto é interessante, pois cada tela de celular
    // tem uma largura e altura, bem como cada foto. Dependendo das dimensões
    // da imagem, resizePictureToFitIntoScreen só um lado (e aplicar a razão largura/altura)
    // ao outro já dá certo. As vezes tem que resizePictureToFitIntoScreen duas vezes.

    differenceInHeight = originalPhoto.getHeight() - myDisplayHeight;
    differenceInWidth = originalPhoto.getWidth() - myDisplayWidth;

    // A largura e altura estão fora da tela.
    if(differenceInHeight > 0 && differenceInWidth > 0){

        // Começamos a resizePictureToFitIntoScreen pelo lado que está mais fora da tela, e depois
        // aplicamos ao outro, se necessário.
        if(differenceInHeight > differenceInWidth) {

            float ratio = (float) myDisplayHeight / originalPhoto.getHeight();

            scaledPhotoHeight_1 = ratio * originalPhoto.getHeight();
            scaledPhotoWidth_1 = ratio * originalPhoto.getWidth();

            // Neste ponto a altura da foto foi redimensionado para ser igual a altura da tela,
            // e a largura seguiu a proporção. Mas será que a largura ficou dentro da tela também?

            float difLargura_2 = scaledPhotoWidth_1 - myDisplayWidth;

            // A altura ficou fora da tela e tem que ser redimensionada
            if(difLargura_2 > 0){

                float ratio_2 = (float) myDisplayWidth / scaledPhotoWidth_1;

                scaledPhotoHeight_2 = ratio_2 * scaledPhotoHeight_1;
                scaledPhotoWidth_2 = ratio_2 * scaledPhotoWidth_1;

                // Fim, ambas as dimensões foram redimensionadas

            }

            else{

                scaledPhotoHeight_2 = scaledPhotoHeight_1;
                scaledPhotoWidth_2 = scaledPhotoWidth_1;

            }

        } else{

            float ratio = (float) myDisplayWidth / originalPhoto.getWidth();

            scaledPhotoHeight_1 = ratio * originalPhoto.getHeight();
            scaledPhotoWidth_1 = ratio * originalPhoto.getWidth();

            // Neste ponto a largura da foto foi redimensionado para ser igual a largura da tela,
            // e a altura seguiu a proporção. Mas será que a altura ficou dentro da tela também?

            float difAltura_2 = scaledPhotoHeight_1 - myDisplayHeight;

            // A altura ficou fora da tela e tem que ser redimensionada
            if(difAltura_2 > 0){

                float ratio_2 = (float) myDisplayHeight / scaledPhotoHeight_1;

                scaledPhotoHeight_2 = ratio_2 * scaledPhotoHeight_1;
                scaledPhotoWidth_2 = ratio_2 * scaledPhotoWidth_1;

                // Fim, ambas as dimensões foram redimensionadas

            }

            else{

                scaledPhotoHeight_2 = scaledPhotoHeight_1;
                scaledPhotoWidth_2 = scaledPhotoWidth_1;

            }

        }

        // Só 01 dimensão precisa ser ajustada
    } else if(differenceInHeight > 0 || differenceInWidth > 0){

        // Qual que tem que ser ajustada?
        if(differenceInHeight > 0) {

            float ratio = (float) myDisplayHeight / originalPhoto.getHeight();

            scaledPhotoHeight_1 = ratio * originalPhoto.getHeight();
            scaledPhotoWidth_1 = ratio * originalPhoto.getWidth();

        } else{

            float ratio = (float) myDisplayWidth / originalPhoto.getWidth();

            scaledPhotoHeight_1 = ratio * originalPhoto.getHeight();
            scaledPhotoWidth_1 = ratio * originalPhoto.getWidth();

        }

        scaledPhotoHeight_2 = scaledPhotoHeight_1;
        scaledPhotoWidth_2 = scaledPhotoWidth_1;

        // Nenhuma dimensão está fora da tela
    } else{

        scaledPhotoHeight_2 = originalPhoto.getHeight();
        scaledPhotoWidth_2 = originalPhoto.getWidth();

    }

    scaledPhoto = Bitmap.createScaledBitmap(originalPhoto, (int) scaledPhotoWidth_2, (int) scaledPhotoHeight_2, false);
    scaledPhotoRatio = (float) scaledPhoto.getHeight() / scaledPhoto.getWidth();

}

}
1
  • 1
    The return value for getWidth and getHeight() is pixel (px). Please learn more about dp and px. Commented Jan 25, 2015 at 11:01

1 Answer 1

3

getWidth() and getHeight() returns in pixel but you put in dp. Depends on the device resoulution, you may get different values.

Difference between px and dp

Basic calculation that I use

ldpi  : 0.75 x
mdpi  : 1x
hdpi  : 1.5x
xdpi  : 2x
xxdpi : 3x
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.