Android: Define onDraw Canvas Size

15,249

Solution 1

In your View class you need to override the onMeasure() method. This is where you ask for a specific View size. There are some official Android tutorials on this subject and I will edit this post once I'm at my computer with the links.

EDIT:

Take a look at this Android article about creating custom components.. Specifically take a look at the section titled 'Extend onDraw() and onMeasure()'. Quoting:

onMeasure() is a little more involved. onMeasure() is a critical piece of the rendering contract between your component and its container. onMeasure() should be overridden to efficiently and accurately report the measurements of its contained parts. This is made slightly more complex by the requirements of limits from the parent (which are passed in to the onMeasure() method) and by the requirement to call the setMeasuredDimension() method with the measured width and height once they have been calculated. If you fail to call this method from an overridden onMeasure() method, the result will be an exception at measurement time.

Further on in the article:

Your component's onMeasure() method should calculate a measurement width and height which will be required to render the component. It should try to stay within the specifications passed in, although it can choose to exceed them (in this case, the parent can choose what to do, including clipping, scrolling, throwing an exception, or asking the onMeasure() to try again, perhaps with different measurement specifications).

There is an CustomView example available as a demo but unfortunately the developer website has changed (for the worse!) so that it's not available except through download by the SDK Manager. See the page here for more instructions.

Solution 2

For example, 200 width, 150 height. Override onMeasure method in the View.

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(200, 150);
    }

Solution 3

From your description, it seems the issue is that you aren't specifying the size of your DemoView, you are just setting it as the ContentView, which will fill the parent by default.

Specify some LayoutParams when you create your DemoView, or create a ViewGroup to give it a size.

You could also define the layout / sizing via XML, and inflate that. (You should either make it a separate class, or make it public in this case.) Eg.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    Specify container measurements
    ...
    >
    <com.yourpackagename.MainActivity.DemoView
    ...
    Specify layout height / width, etc.
    ...
    />
</LinearLayout>
Share:
15,249
AndrewLugs
Author by

AndrewLugs

Updated on June 04, 2022

Comments

  • AndrewLugs
    AndrewLugs almost 2 years

    I've removed my old code now as it wasn't working as I intended. I was trying to use the onDraw canvas feature within a certain portion of the screen so that I could still have buttons and other text around my drawing.

    ***EDIT***

    I've managed to fix this issue now. A lot of what was suggested was helpful but I just couldn't get it to work with what I wanted. That's probably more my fault than anything else so thanks to all those who offered advice. Here's how I solved the issue.

    *1. First Define a View in the Layout File.

    <view
    class="com.project.MainActivity.Drawing"
    android:id="@+id/drawing_area"
    android:layout_width="700dp"
    android:layout_height="900dp"
    android:layout_centerInParent="true"/>
    

    *2. Then create a separate java class file with the following code:

    public class Drawing extends View {
    Paint paint = new Paint();
    
    public Drawing(Context context) {
    super(context);
    }
    
    public Drawing(Context context, AttributeSet attrs) {
    super(context, attrs);
    }   
    
    @Override
    protected void onDraw(Canvas canvas) {  
    super.onDraw(canvas);
    
    //Draw Image Here//
    
    }
    

    *3. Then call the Drawing from the main activity:

    public class MainActivity extends Activity {
    
    private Drawing mDrawingArea;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.percentage_count_layout);
      mDrawingArea = (Drawing)findViewById(R.id.drawing_area);  
    }
    
  • PrplRugby
    PrplRugby over 11 years
    Would be a good idea to read the image dimensions once and store them in a Rect, rather than during every onDraw call.
  • Raigex
    Raigex over 11 years
    true that would be better.
  • AndrewLugs
    AndrewLugs over 11 years
    Thanks for looking into this. Do you have an example of this you would be able to show me? If I remove the setContentView no Image will load so i'm unsure of how to define the size and have it display without this line of code included.
  • AndrewLugs
    AndrewLugs over 11 years
    Thanks for looking into this. Do you have an example of this you would be able to show me? If I remove the setContentView no Image will load so i'm unsure of how to define the size and have it display without this line of code included. A few lines of code as an example would be really helpful.