title: Android Fragment with RelativeLayout and CustomView - onDraw is not called
body: <p>I have a fragment with a relative layout - which is correctly displayed.
  Now I try to add a custom view with canvas - where I can dynamically draw on. But the onDraw-method of the custom view is not called if I call the drawConnectionLine method from the custom View. If I do not call the drawConnectionLine method it works.
  I tried to call the drawConnectionLine in the onResume-method after the view is created but it does not help...</p>
  
  <p>How can I dynamically draw on the custom view after initialization without a NullPointerException(because of the onDraw not being executed)?</p>
  
  <p>Here is my fragment-code(<strong>FragmentPlan.java</strong>):</p>
  
  <pre><code>package de.tucais.svm.youplan;
  
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.Map.Entry;
  import java.util.Set;
  
  import android.app.Activity;
  import android.app.Fragment;
  import android.content.ContentValues;
  import android.graphics.Canvas;
  import android.os.Bundle;
  import android.util.Log;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import android.view.ViewGroup.LayoutParams;
  import android.widget.RelativeLayout;
  import android.widget.TextView;
  
  public class FragmentPlan extends Fragment
  {
      // Define logging variables
      private static final String LOGCAT = "YP-FragmentPlan";
      private static final boolean D = true; // control debug-output
  
      Activity parentActivity;
      LibSVM svm = null;
      DatabaseController db;
      Controller controller = null;
      DrawView drawView = null;
      //Canvas drawCanvas = null;
  
      int firstTv_margin_top, firstTv_margin_left, firstTv_margin_right, firstTv_margin_bottom;
      int tv_margin_top, tv_margin_left, tv_margin_right, tv_margin_bottom;
  
      RelativeLayout planLayout = null;
      List&lt;TextView&gt; taskElements = new ArrayList&lt;TextView&gt;();
  
      public FragmentPlan()
      {
  
      }
  
      public void onResume()
      {
          super.onResume();
          computeResult();
      }
  
      @Override    
      public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
      {
          View view = inflater.inflate(R.layout.fragment_plan, container, false);
          controller = new Controller((MainActivity)getActivity());
          planLayout = (RelativeLayout)view.findViewById(R.id.relativeLayout_plan);
  
          // Translate the margin-values from dp to pixel
          firstTv_margin_left = getResources().getDimensionPixelSize(R.dimen.plan_firstTv_margin_left);
          firstTv_margin_top = getResources().getDimensionPixelSize(R.dimen.plan_firstTv_margin_top);
          firstTv_margin_right = getResources().getDimensionPixelSize(R.dimen.plan_firstTv_margin_right);
          firstTv_margin_bottom = getResources().getDimensionPixelSize(R.dimen.plan_firstTv_margin_bottom);
          tv_margin_left = getResources().getDimensionPixelSize(R.dimen.plan_tv_margin_left);
          tv_margin_top = getResources().getDimensionPixelSize(R.dimen.plan_tv_margin_top);
          tv_margin_right = getResources().getDimensionPixelSize(R.dimen.plan_tv_margin_right);
          tv_margin_bottom = getResources().getDimensionPixelSize(R.dimen.plan_tv_margin_bottom);
  
          // Create the DrawView and append it to the RelativeLayout
          drawView = new DrawView((MainActivity)getActivity());
          RelativeLayout.LayoutParams drawViewParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
          drawView.setLayoutParams(drawViewParams);
          drawView.setId(View.generateViewId());
  
          planLayout.addView(drawView);
          //sendViewToBack(drawView);     
          if(D) Log.i(LOGCAT,"drawCanvas created...");
  
          if(D) Log.i(LOGCAT,"onCreateView finished...");
          return view;
      }
  
      private void computeResult()
      {
          List&lt;ContentValues&gt; result = controller.computeSequence();
          //displayResult(result.get(0));
          for(int i=0; i &lt; result.size(); i++)
          {
              displayResultElement(result.get(i));
              if(i &gt; 0)
              {
                  if(D) Log.i(LOGCAT,"tried to draw connection for " + i + " time...");
                  if(D) Log.i(LOGCAT,"DrawCanvas is null: " + drawView.isCanvasNull()); //-&gt; returns true
                  drawView.drawConnectionLine(taskElements, i); //-&gt; this call causes the error
                  if(D) Log.i(LOGCAT,"succesfully drawed connection nr" + i + "...");
              }
          }
      }
  
      private void displayResultElement(ContentValues resultElement)
      {
          // Create a new element
          TextView newElement = new TextView((MainActivity)getActivity());
          newElement.setId(View.generateViewId());
          newElement.setBackground(getResources().getDrawable(R.drawable.shape_circle));
  
          // Fill the new Element with its content
          Set&lt;Entry&lt;String, Object&gt;&gt; s = resultElement.valueSet();
          Iterator&lt;Entry&lt;String, Object&gt;&gt; itr = s.iterator();
          Map.Entry&lt;String, Object&gt; me = (Map.Entry&lt;String, Object&gt;)itr.next();
          newElement.append(me.getKey().toString()+": " + me.getValue().toString());
          while(itr.hasNext())
          {
              me = (Map.Entry&lt;String, Object&gt;)itr.next();
              newElement.append("\n"+me.getKey().toString()+": " + me.getValue().toString());
          }
          // After filling the new element with content append it to its parent view element
          planLayout.addView(newElement);
          // add the element to the list
          taskElements.add(newElement);
          // Position the new element on the screen       
          RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)newElement.getLayoutParams();
          // if there is more than the current element in the list position relative to the predecessor
          if(taskElements.size() &gt; 1)
          {
              params.addRule(RelativeLayout.BELOW, taskElements.get(taskElements.size()-2).getId());
              params.addRule(RelativeLayout.ALIGN_LEFT, taskElements.get(taskElements.size()-2).getId());
              params.setMargins(tv_margin_left, tv_margin_top, tv_margin_right, tv_margin_bottom);
          }
          else
          {
              params.setMargins(firstTv_margin_left, firstTv_margin_top, firstTv_margin_right, firstTv_margin_bottom);
          }       
          newElement.setLayoutParams(params);
      }
  
      private static void sendViewToBack(final View v)
      {
          final ViewGroup parent = (ViewGroup)v.getParent();
          if (parent != null)
          {
              parent.removeView(v);
              parent.addView(v, 0);
          }
      }
  }
  </code></pre>
  
  <p>This is my xml-file for the relativeLayout(<strong>fragment_plan.xml</strong>):</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:id="@+id/relativeLayout_plan"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:layout_margin="2dp"
      tools:context=".MainActivity" &gt;
  
  &lt;/RelativeLayout&gt;
  </code></pre>
  
  <p>Here is my CustomView(<strong>DrawView.java</strong>):</p>
  
  <pre><code>package de.tucais.svm.youplan;
  
  import java.util.List;
  
  import android.content.Context;
  import android.graphics.Canvas;
  import android.graphics.Color;
  import android.graphics.Paint;
  import android.util.Log;
  import android.view.View;
  import android.widget.TextView;
  
  public class DrawView extends View
  {
      // Define logging variables
      private static final String LOGCAT = "YP-DrawView";
      private static final boolean D = true; // control debug-output
  
      private Canvas drawCanvas = null;
  
      public DrawView(final Context context)
      {
          super(context);
          if(D) Log.i(LOGCAT,"DrawView constructor called... ");
      }
  
      @Override
      protected void onMeasure(int w, int h)
      {
          if(D) Log.d(LOGCAT,"onMeasure with w= " + w + " and h= " + h + " called...");
          setMeasuredDimension(w, h);
      }
  
      @Override
      protected void onDraw(Canvas canvas)
      {
          super.onDraw(canvas);
          if(D) Log.i(LOGCAT,"onDraw called... ");
          this.drawCanvas = canvas;
          if(D) Log.d(LOGCAT,"drawCanvas still empty? " + (this.drawCanvas == null));
      }
  
      /*
       * Method which draws a connection line between two graphical elements on the screen
       * @param {List&lt;TextView&gt;} taskElements - a list of all TextView-elements
       * @param {int} nr - the number of the destination element
       */
      public void drawConnectionLine(List&lt;TextView&gt; taskElements, int nr)
      {
          if(D) Log.i(LOGCAT,"drawConnectionLine called... ");
  
          TextView currentElement = taskElements.get(nr);
          TextView prevElement = null;
          try
          {
              prevElement = taskElements.get(nr-1);
          }
          catch(Exception e)
          {
              Log.e(LOGCAT, "No predacessor!!!");
          }
  
          int startX = computeCenter(prevElement);
          int startY = prevElement.getBottom();
          int stopX = computeCenter(currentElement);
          int stopY = currentElement.getTop();
  
          Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
          paint.setColor(Color.BLACK);
          this.drawCanvas.drawLine(startX, startY, stopX, stopY, paint); //-&gt; this.drawCanvas == null =&gt; Why???
      }
  
      private int computeCenter(View element)
      {
          int result = 0;
          if(element != null)
          {
              int right = element.getRight();
              result = right - (element.getWidth()/2);
          }
          return result;
      }
  
      public void emptyCanvas()
      {
          // Clear the canvas
          this.drawCanvas.drawColor(Color.TRANSPARENT);
      }
  
      public boolean isCanvasNull()
      {
          return this.drawCanvas == null;
      }
  }
  </code></pre>
  
  <p>It would be very nice, if someone can explain me, why the onDraw-method of the DrawView is not called when calling the drawConnectionLine method- the reason for a NullPointerException in the FragmentPlan.java line 95.</p>
  
  <p>Thanks in advance!!!</p>