3

My activity has a LinearLayout with a single child view. I want both to fill the screen, minus a 12 dp margin.

Unfortunately, the child view is drawn 12 dp too big and gets cut off. Apparently match_parent ignores the layout_margin attribute when calculating the size of the child view. What is the simplest way to fix this?

myActivity.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_margin="12dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <com.myapp.myView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
    />
</LinearLayout>

myActivity.java

package com.myapp;

import android.app.Activity;
import android.os.Bundle;

public class myActivity extends Activity {


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.myActivity);
    }
}

myView.java

package com.myapp;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

public class myView extends View {

    private Paint paint = new Paint();

    public myView(Context context, AttributeSet attrs) {
        super(context, attrs);
        paint.setColor(0xFFFF0000); //red
        paint.setStyle(Paint.Style.STROKE); // for unfilled rectangles
        paint.setStrokeWidth(4);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int size = canvas.getWidth(); // width = height (see onMeasure())
        canvas.drawRect(0, 0, size, size, paint);   
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, widthMeasureSpec);
        // This gives us a square canvas!
    }
}
1''
  • 26,823
  • 32
  • 143
  • 200

1 Answers1

7

Child views can have a margin around them, parent views (or view groups like layouts) can have a padding between their boundaries and their child views. In other words, margin is outside a view, padding is inside.

Also, see this excellent explanation: Difference between a View's Padding and Margin

Example with standard View and padding instead of margin:

I created a little example with a standard view instead of your custom one, and using padding for the LinearLayout as suggested above and it works perfectly (see screenshot):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="12dp"
    android:orientation="vertical" >

    <View
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="#ff0000"/>
</LinearLayout>

screenshot from layout editor

Solution

Turns out, the problem was your using canvas.getWidth() in your custom view's onDraw method. Using the view's getWidth() instead, solved the problem. Finally :-)

Community
  • 1
  • 1
Ridcully
  • 23,362
  • 7
  • 71
  • 86
  • Changing layout_margin to padding leaves me with the same problem, except that the outer layout now fills the entire screen and only the inner layout has the 12dp margin. I'm going to stick with layout_margin. Do you know what is causing my problem? – 1'' Dec 25 '12 at 21:12
  • Perhaps it's the implementation of your custom view? Have you tried a normal `View`? – Ridcully Dec 26 '12 at 09:07
  • I'm drawing lines on a canvas in the child view. If you'd like, I can post a minimal test case. – 1'' Dec 26 '12 at 15:38
  • It would be interesting if and how you implement the onMeasure() method, because that's where the actual size of the view is calculated. – Ridcully Dec 26 '12 at 16:19
  • Funny you should mention that, since I actually have overridden it! See my edited post. – 1'' Dec 26 '12 at 16:23
  • Hm, should probably work, but can you try without the overridden method and just set layout_height to a dedicated height, e.g. 100dp? Just to check if it would work then. – Ridcully Dec 26 '12 at 16:31
  • It's still cut off after those changes. – 1'' Dec 26 '12 at 16:51
  • Hm, perhaps you can post a minimal test case of your view? – Ridcully Dec 26 '12 at 19:14
  • I've created a test layout with a standard View instead of your custom view and the suggested padding instead of margin, and it works perfectly. – Ridcully Dec 27 '12 at 09:10
  • You're right, although there's no way to tell with your particular example since every part of the image looks the same lol. I think the problem is the use of `canvas.getWidth()`. Do you know of an alternate way to get the size of the canvas before drawing on it? – 1'' Dec 27 '12 at 15:39
  • You can try using the View's getWidth() and getHeight(), which should have the correct values after layout is done. – Ridcully Dec 27 '12 at 20:08
  • Wow, you're right! I just had to change `canvas.getWidth()` to `this.getWidth()`! Could you put this answer into your original post so I can accept it? – 1'' Dec 27 '12 at 20:13
  • I updated my answer. I'm glad we finally found a solution for you. Cheers. – Ridcully Dec 27 '12 at 20:30