onDraw() not being called <p>I am working on fixing someone's Android app. It was originally made for 2.1 and I am trying to get it work to 4.0+. Unfortunately the person who made the app is not around so I am stuck with his code.</p> <p>The app implements custom sliders, a horizontal and vertical. I got the vertical slider fixed, but I cannot get the horizontal slider to work. It is not calling <code>onDraw()</code>: When the view loads, <code>onDraw()</code> gets called and I see both of my sliders initialized, then when I move my horizontal slider it moves and calls <code>onDraw()</code> once, but never again will it call it, unlike the vertical slider which does call it.</p> <p>Here is the code:</p> <pre><code>public class PanSeekBar extends RelativeLayout { private RelativeLayout layout1; public ImageView track; public ImageView thumb; public boolean initialized = false; public int thumbDownPosX = 0; public int thumbDownPosY = 0; public int thumbLeft = 0; public int thumbTop = 0; public int thumbRight = 0; public int thumbBottom = 0; private int max = 100; public boolean touched = false; public PanSeekBar(Context context) { super(context); initialize(context); // TODO Auto-generated constructor stub }// End of PanSeekBar Constructor private void initialize(Context context) { Log.d("initialize (PanSeekBar)", "initialize"); setWillNotDraw(false); LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view1 = inflater.inflate(R.layout.pan_seekbar, this); layout1 = (RelativeLayout) view1.findViewById(R.id.ps_layout1); track = (ImageView) layout1.findViewById(R.id.ps_track); thumb = (ImageView) layout1.findViewById(R.id.ps_thumb); thumb.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { initialized = true; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.d("onTouch (PanSeekBar)", "Action Down"); thumbDownPosX = (int) event.getX(); thumbDownPosY = (int) event.getY(); thumbLeft = thumb.getLeft(); thumbTop = thumb.getTop(); thumbRight = thumb.getRight(); thumbBottom = thumb.getBottom(); touched = true; break; case MotionEvent.ACTION_MOVE: // Log.d("onTouch (PanSeekBar)", "Action Move"); int left = (int) (thumb.getLeft() + event.getX() - thumbDownPosX); if (left &lt; 0) { left = 0; Log.d("onTouch (PanSeekBar)", "left &lt; 0: " + left); } else if (left &gt;= track.getWidth() - thumb.getWidth()) { left = track.getWidth() - thumb.getWidth(); Log.d("onTouch (PanSeekBar)", "left &gt;= track.getWidth(): " + left); } int top = thumb.getTop(); int right = left + thumb.getWidth(); int bottom = top + thumb.getHeight(); thumbLeft = left; thumbTop = top; thumbRight = right; thumbBottom = bottom; Log.d("onTouch (PanSeekBar)", "Action Move -- thumb layout: " + thumbLeft + ", " + thumbTop + ", " + thumbRight + ", " + thumbBottom); layout1.invalidate(); // thumb.invalidate(); break; case MotionEvent.ACTION_UP: Log.d("onTouch (PanSeekBar)", "Action Up"); touched = false; break; }// End of switch return true; }// End of onTouch }); }// End of initialize @Override protected void onDraw(Canvas canvas) { Log.d("onDraw (PanSeekBar)", "onDraw"); super.onDraw(canvas); if (initialized) { thumb.layout(thumbLeft, thumbTop, thumbRight, thumbBottom); Log.d("onDraw (PanSeekBar)", "thumb layout: " + thumbLeft + ", " + thumbTop + ", " + thumbRight + ", " + thumbBottom); } }// End of onDraw }// End of PanSeekBar </code></pre> <p>Here is the code for the vertical slider that does work:</p> <pre><code>public class MySeekBar extends RelativeLayout { private RelativeLayout layout1; public ImageView track; public ImageView thumb; private MyToast toast; private MyToast toast2; private MyToast toast3; private int globalMaxValue; private int globalProgress; private boolean initialized = false; public int thumbDownPosX = 0; public int thumbDownPosY = 0; public int thumbLeft = 0; public int thumbTop = 0; public int thumbRight = 0; public int thumbBottom = 0; private int globalSetProgress = 0; private int globalConfigType = 1; // Margin top in custom_seekbar.xml private int marginTop = 20; public boolean touched = false; public MySeekBar(Context context) { super(context); // TODO Auto-generated constructor stub initialize(context); }// End of MySeekBar public void initialize(Context context) { Log.d("initialize (MySeekBar)", "initialize"); setWillNotDraw(false); LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view1 = inflater.inflate(R.layout.custom_seekbar, this); layout1 = (RelativeLayout) view1.findViewById(R.id.al_cs_layout1); track = (ImageView) layout1.findViewById(R.id.cs_track); thumb = (ImageView) layout1.findViewById(R.id.cs_thumb); // Gets marginTop MarginLayoutParams params = (MarginLayoutParams) track .getLayoutParams(); Log.d("initialize (MySeekBar)", "current margintop = " + marginTop); marginTop = params.topMargin; Log.d("initialize (MySeekBar)", "new margintop = " + marginTop); // int marginTopPixelSize = params.topMargin; // Log.d("initialize (MySeekBar)","debug = "+marginTopPixelSize); // Jared // When creating MyToast, setting width causes issues. toast = new MyToast(context); toast.setText(""); toast.setBackgroundColor(Color.LTGRAY); toast.setTextColor(Color.BLACK); toast.setPadding(1, 1, 1, 1); toast.setVisibility(View.INVISIBLE); toast.setTextSize(10f); // toast.setWidth(40); toast2 = new MyToast(context); toast2.setTextSize(12f); toast2.setTextColor(Color.rgb(192, 255, 3)); // toast2.setWidth(40); toast2.setPadding(10, 1, 1, 1); // toast2.setBackgroundColor(Color.BLACK); toast2.setVisibility(View.INVISIBLE); toast3 = new MyToast(context); toast3.setText("CH"); toast3.setTextSize(15f); toast3.setTextColor(Color.rgb(192, 255, 3)); // toast3.setWidth(40); toast3.setPadding(1, 1, 1, 1); layout1.addView(toast); layout1.addView(toast2); layout1.addView(toast3); thumb.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { initialized = true; // 0=down 1=up 2=move // Log.d("onTouch (MySeekBar)", // Integer.toString(event.getAction())); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.d("onTouch (MySeekBar)", "Action Down"); thumbDownPosX = (int) event.getX(); thumbDownPosY = (int) event.getY(); // Position of thumb touched. Irrelevant to scale // Log.d("onTouch (NewSeekBar)","thumbDownPosX "+thumbDownPosX+" thumbDownPosY "+thumbDownPosY); thumbLeft = thumb.getLeft(); thumbTop = thumb.getTop(); thumbRight = thumb.getRight(); thumbBottom = thumb.getBottom(); touched = true; toast2.setVisibility(View.INVISIBLE); toast3.setVisibility(View.INVISIBLE); toast.setVisibility(View.VISIBLE); // Location/size of the thumb button // Log.d("onTouch (NewSeekBar)","thumbLeft "+thumbLeft+" thumbRight "+thumbRight+" thumbTop "+thumbTop+" thumbBottom "+thumbBottom); break; case MotionEvent.ACTION_MOVE: // Log.d("onTouch (MySeekBar)", "Action Move"); int thumbHeight = thumb.getHeight(); int thumbWidth = thumb.getWidth(); int trackWidth = track.getWidth(); int trackHeight = track.getHeight(); // Location/size of the thumb button and track // Log.d("onTouch (NewSeekBar)","thumbHeight "+thumbHeight+" thumbWidth "+thumbWidth+" trackWidth "+trackWidth+" trackHeight "+trackHeight); int top = (int) (thumb.getTop() + event.getY() - thumbDownPosY); Log.d("onTouch (NewSeekBar)", "top " + top); // Top border if (top &lt; marginTop) { top = marginTop; Log.d("onTouch (NewSeekBar)", "top &lt; marginTop " + top); } else if (top &gt;= trackHeight - thumbHeight + marginTop) { top = trackHeight - thumbHeight + marginTop; Log.d("onTouch (NewSeekBar)", "top &gt;= trackHeight " + top); } thumbLeft = thumb.getLeft(); ; thumbTop = top; thumbRight = thumbLeft + thumbWidth; thumbBottom = top + thumbHeight; // Log.d("onTouch (MySeekBar)", // "thumbTop: "+thumbTop+" thumbBottom: "+thumbBottom); int value = getProgress(); Log.d("onTouch (NewSeekBar)", "getProgress(): " + value); // setdBText(value); // Log.d("onTouch (MySeekBar)", "value: "+value); setProgress(value); // toast.setText(String.valueOf(temp)); // toast2.setText(String.valueOf(temp)); layout1.invalidate(); break; case MotionEvent.ACTION_UP: Log.d("onTouch (MySeekBar)", "Action Up"); toast.setVisibility(View.INVISIBLE); toast2.setVisibility(View.VISIBLE); toast3.setVisibility(View.VISIBLE); touched = false; break; }// End of switch return true; }// End of onTouch }); }// End of initialize @Override protected void onDraw(Canvas canvas) { Log.d("onDraw (MySeekBar)", "onDraw"); super.onDraw(canvas); if (initialized) { thumb.layout(thumbLeft, thumbTop, thumbRight, thumbBottom); Log.d("onDraw (MySeekBar)", "thumb layout: " + thumbLeft + ", " + thumbTop + ", " + thumbRight + ", " + thumbBottom); int top = thumbTop - marginTop; int left = thumbLeft + 4; // toast.layout(left, top, left + toast.getWidth(), top + // toast.getHeight()); top = thumbTop + thumb.getHeight() / 2 - toast2.getHeight() / 2 + 1; left = thumbLeft; toast2.layout(left, top, left + toast2.getWidth(), top + toast2.getHeight()); } }// End of onDraw </code></pre> <p>The XML:</p> <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:id="@+id/test_layout"&gt; &lt;LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" &gt; &lt;com.networksound.Mixer3.NewSeekBar android:id="@+id/newSeekBar1" android:layout_width="wrap_content" android:layout_height="wrap_content" &gt; &lt;/com.networksound.Mixer3.NewSeekBar&gt; &lt;com.networksound.Mixer3.NewSeekBar android:id="@+id/newSeekBar2" android:layout_width="wrap_content" android:layout_height="wrap_content" &gt; &lt;/com.networksound.Mixer3.NewSeekBar&gt; &lt;com.networksound.Mixer3.MySeekBar android:id="@+id/mySeekBar1" android:layout_width="wrap_content" android:layout_height="wrap_content" &gt; &lt;/com.networksound.Mixer3.MySeekBar&gt; &lt;com.networksound.Mixer3.MySeekBar android:id="@+id/mySeekBar2" android:layout_width="wrap_content" android:layout_height="wrap_content" &gt; &lt;/com.networksound.Mixer3.MySeekBar&gt; &lt;/LinearLayout&gt; &lt;LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" &gt; &lt;com.networksound.Mixer3.PanSeekBar android:id="@+id/panSeekBar1" android:layout_width="match_parent" android:layout_height="wrap_content" &gt; &lt;/com.networksound.Mixer3.PanSeekBar&gt; &lt;com.networksound.Mixer3.PanSeekBar android:id="@+id/panSeekBar2" android:layout_width="wrap_content" android:layout_height="wrap_content" &gt; &lt;/com.networksound.Mixer3.PanSeekBar&gt; &lt;/LinearLayout&gt; &lt;/LinearLayout&gt; </code></pre>