title: Partial redraw -> invalidate (Rect rect)
body: <p>In my onDraw I have all code needed to build my entire view but how can I detect if I want to perform only a partial redraw.
  I guess a partial redraw should be triggered by calling canvas.invalidate(Rect rect);
  Right?
  In developer settings of my device I enabled “Show screen updates” but this always tells me that my entire screen is redrawn…</p>
  
  <p>Below you see a screenshot of my app:</p>
  
  <p><img src="https://i.stack.imgur.com/cFMKz.png" alt="Screenshot of app"></p>
  
  <p>As you can see it is a calendar and I want to give the user a visual feedback when an entry is clicked (let’s say a red border around)…</p>
  
  <p>I’ve already seen some samples but they either use a bitmap or lots of member variables to execute just the code needed for redrawing specific region in onDraw…</p>
  
  <p>Can anyone tell me what’s the best way to implement such a feature?</p>
  
  <p>UPDATE:</p>
  
  <p>On my first draw <code>Canvas.getClipBounds()</code> returns the following rect:</p>
  
  <pre><code>Rect(0, 0 - 1200, 1800)
  </code></pre>
  
  <p>when I call <code>invalidate(new Rect(304, 748 - 529, 902))</code> and check <code>getClipBounds()</code> again in <code>onDraw()</code> it still has the same value.</p>
  
  <p>UPDATE2 (my code):</p>
  
  <pre><code>@Override
  public boolean onTouch(View v, MotionEvent event) {
  
      switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN: {
          _pTouchDown = new PointF(event.getX(), event.getY());
  
          downX = event.getX();
          downY = event.getY();
  
          entrySelected = hasTimeRecordAt(downX, downY);
          if (entrySelected != null) {
              Rect rInvalidate = new Rect((int) entrySelected.get_Selected().left, (int) entrySelected.get_Selected().top, (int) entrySelected.get_Selected().right,
                      (int) entrySelected.get_Selected().bottom);
  
              invalidate(rInvalidate);
  
  
          } 
  
          return false;
      }
  </code></pre>
  
  <p>UPDATE 3 (my Layout):</p>
  
  <pre><code>&lt;android.support.v4.widget.DrawerLayout
          xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          android:id="@+id/drawer_layout"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          tools:context=".MultiDayCalendarActivity" &gt;
  
      &lt;LinearLayout
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:layout_weight="1"
          android:orientation="vertical" &gt;
  
          &lt;RelativeLayout
              android:id="@+id/rlStatusline"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="horizontal" &gt;
  
              &lt;TextView
                  android:id="@+id/tvStatusline1"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:layout_alignParentLeft="true"
                  android:text="asdf" &gt;
              &lt;/TextView&gt;
  
              &lt;TextView
                  android:id="@+id/tvStatusline2"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:layout_alignParentRight="true"
                  android:text="1234" &gt;
              &lt;/TextView&gt;
          &lt;/RelativeLayout&gt;
  
          &lt;com.mxp.time.calendar.DayHeader
                  android:id="@+id/dayHeader"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                   /&gt;
  
          &lt;ScrollView
              android:id="@+id/m_svMultiRoot1"
              android:layout_width="match_parent"
              android:layout_height="0dip"
              android:layout_weight="1" &gt;
  
              &lt;com.mxp.time.calendar.Calendar
                  android:id="@+id/calendar"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                   /&gt;
          &lt;/ScrollView&gt;
  
          &lt;LinearLayout
              android:layout_width="fill_parent"
              android:layout_height="1dp"
              android:background="@color/brushBackgroundLight" &gt;
          &lt;/LinearLayout&gt;
  
          &lt;RelativeLayout
              android:id="@+id/rlMenu"
              android:layout_width="match_parent"
              android:layout_height="wrap_content" &gt;
  
              &lt;LinearLayout
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:layout_alignParentLeft="true" &gt;
  
                  &lt;ImageButton
                      android:id="@+id/ibtCreateNewTimeRecord"
                      android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
                      android:src="@drawable/menu" /&gt;
  
                  &lt;ImageButton
                      android:id="@+id/ibtCalendarStopwatch"
                      android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
                      android:src="@drawable/stopwatch" /&gt;
              &lt;/LinearLayout&gt;
  
              &lt;LinearLayout
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:layout_centerHorizontal="true"
                  android:orientation="horizontal" &gt;
  
                  &lt;ImageButton
                      android:id="@+id/ibtCalendarBack"
                      android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
                      android:src="@drawable/previous" /&gt;
  
                  &lt;ImageButton
                      android:id="@+id/ibtCalendarForward"
                      android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
                      android:src="@drawable/next" /&gt;
              &lt;/LinearLayout&gt;
  
              &lt;LinearLayout
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:layout_alignParentRight="true" &gt;
  
                  &lt;ImageButton
                      android:id="@+id/ibtCalendarToday"
                      android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
                      android:src="@drawable/today" /&gt;
  
                  &lt;ImageButton
                      android:id="@+id/ibtGotoJobs"
                      android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
                      android:src="@drawable/jobs" /&gt;
              &lt;/LinearLayout&gt;
          &lt;/RelativeLayout&gt;
      &lt;/LinearLayout&gt;
  
      &lt;FrameLayout
          android:id="@+id/drawer"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:layout_gravity="start" &gt;
      &lt;/FrameLayout&gt;
  
  &lt;/android.support.v4.widget.DrawerLayout&gt;
  </code></pre>
  
  <p>UPDATE4:</p>
  
  <pre><code>setContentView(R.layout.test_calendar);
          // _cal = (Calendar) findViewById(R.id.calendar);
          _cal = new Calendar(this);
  
          _dayHeader = (DayHeader) findViewById(R.id.dayHeader);
  
          final ScrollView sv = (ScrollView) findViewById(R.id.m_svMultiRoot1);
          sv.addView(_cal);
  </code></pre>
  
  <p>same result:</p>
  
  <p>I in onTouch I pass Rect(172, 748 - 265, 902) and in onDraw I get Rect(0, 0 - 720, 1800)</p>
  
  <p>UPDATE 5: </p>
  
  <pre><code>package com.example.testclip;
  
  import android.content.Context;
  import android.graphics.Canvas;
  import android.graphics.Rect;
  import android.graphics.RectF;
  import android.graphics.drawable.Drawable;
  import android.util.Log;
  import android.view.MotionEvent;
  import android.view.View;
  
  class V extends View {
  
  private static final String TAG = "null";
  Rect clip = new Rect();
  
  public V(Context context) {
      super(context);
      int[] colors = { 0xff000000, 0xffff0000, 0xffffffff };
      Drawable d = new android.graphics.drawable.GradientDrawable(android.graphics.drawable.GradientDrawable.Orientation.TOP_BOTTOM, colors);
      setBackgroundDrawable(d);
  }
  
  @Override
  public boolean onTouchEvent(MotionEvent event) {
  
      int x = (int) event.getX();
      int y = (int) event.getY();
      StringBuilder sb = new StringBuilder();
  
      sb.append("left: ");
      sb.append(x);
      sb.append(", top: ");
      sb.append(y);
  
      sb.append("right: ");
      sb.append(x + 10);
      sb.append(", bottom: ");
      sb.append(y + 10);
  
      Log.d(TAG, "onTouchEvent  clip rect: " + sb.toString());
  
      invalidate(x, y, x + 10, y + 10);
  
      return false;
  }
  
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      int w = MeasureSpec.getSize(widthMeasureSpec);
      setMeasuredDimension(w, w * 4);
  }
  
  @Override
  protected void onDraw(Canvas canvas) {
      canvas.getClipBounds(clip);
      StringBuilder sb = new StringBuilder();
  
      sb.append("left: ");
      sb.append(clip.left);
      sb.append(", top: ");
      sb.append(clip.top);
  
      sb.append("right: ");
      sb.append(clip.right);
      sb.append(", bottom: ");
      sb.append(clip.bottom);
  
      Log.d(TAG, "onDraw  clip rect: " + sb.toString());
  }
  }
  </code></pre>
  
  <p>Activity:</p>
  
  <pre><code>package com.example.testclip;
  
  import android.os.Bundle;
  import android.app.Activity;
  import android.view.Menu;
  import android.widget.ScrollView;
  
  public class TestClipMainActivity extends Activity {
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
  //      setContentView(R.layout.activity_test_clip_main);
  
       ScrollView sv = new ScrollView(this);
          V v = new V(this);
          sv.addView(v);
          setContentView(sv);
  }
  
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
      // Inflate the menu; this adds items to the action bar if it is present.
      getMenuInflater().inflate(R.menu.test_clip_main, menu);
      return true;
  }
  
  }
  </code></pre>
  
  <p>This code produces the following output</p>
  
  <p>02-15 10:47:54.011: D/OpenGLRenderer(833): Enabling debug mode 0
  02-15 10:47:54.926: D/dalvikvm(833): threadid=1: still suspended after undo (sc=1 dc=1)
  02-15 10:48:03.806: D/null(833): onDraw  clip rect: left: 0, top: 0right: 720, bottom: 2880
  02-15 10:48:05.381: D/null(833): onDraw  clip rect: left: 0, top: 0right: 720, bottom: 2880
  02-15 10:48:07.181: D/null(833): onTouchEvent  clip rect: left: 409, top: 358right: 419, bottom: 368
  02-15 10:48:09.806: D/null(833): onDraw  clip rect: left: 0, top: 0right: 720, bottom: 2880</p>