2012-09-20 52 views
0

我创建了一个名为CustomViewVisual1的自定义视图,该视图在类Particle的屏幕对象上绘制。我在名为LayoutCanvas的类中使用此自定义视图,该类扩展了Activity。即使我调用invalidate并且也尝试过postInvalidate(),LayoutCanvas中的onTouch()或onProgressChanged()事件似乎都不会导致我的视​​图重新绘制。我的对象的值改变了,但我没有重绘! 老实说,我是新来的Android,并没有意识到如何设计我的类和实现什么的任何良好实践,所以如果任何人有更好的解决方案,我想实现,请让我知道。提前致谢!自定义视图不执行onDraw()

这是粒子类:

public class Particle { 
    Rect rect = new Rect(); 
    float similarity; 
    Point p = new Point(); 
    float x; 
    float y; 

    float tx = 240; 
    float ty = 320; 

    Matrix transform = new Matrix(); 

    float r; 
    Paint _paint = new Paint(); 
    Paint tempp = new Paint(); 

    Particle(){} 

    Particle(int width, float similarity){ 
     this.similarity = similarity; 
     x = MyMath.map(similarity, 0, 1, 0, width/2); 
     //y = MyMath.myRandom(-20, 20); 
     y = 0; 
     //p.set((int) MyMath.map(similarity, 0, 1, 0, width/2), (int)MyMath.myRandom(0, 360)); 
     p.set((int)x, (int)y); 
     r = MyMath.myRandom(0, 360); 
     //recalculateCoordinates(); 
     _paint.setColor(Color.WHITE); 
     tempp.setColor(Color.GREEN); 
     //rotate(r); 

    } 


    public void display(Canvas canvas, Paint paint, float scale){ 
     //canvas.drawLine(canvas.getWidth()/2, 0, canvas.getWidth()/2, canvas.getHeight(), _paint); 
     //canvas.drawLine(0, canvas.getHeight()/2, canvas.getWidth(), canvas.getHeight()/2, _paint); 
     canvas.save(); 
     canvas.translate(canvas.getWidth()/2, canvas.getHeight()/2); 
     //canvas.translate(tx, ty); 
     canvas.rotate(r); 
     //canvas.scale(scale, scale); 
     paint.setColor(colorize()); 
     canvas.drawRect(-p.x, p.y, -p.x+10, p.y+10, paint); 
     canvas.restore(); 

     canvas.save(); 
     canvas.translate(canvas.getWidth()/2, canvas.getHeight()/2); 
     canvas.drawLine(0, 0, 200, 0, tempp); 
     canvas.drawText("0'", 100, 8, tempp); 
     canvas.restore(); 

     canvas.save(); 
     canvas.translate(canvas.getWidth()/2, canvas.getHeight()/2); 
     canvas.rotate(45); 
     canvas.drawLine(0, 0, 200, 0, tempp); 
     canvas.drawText("45''", 100, 8, tempp); 
     canvas.restore(); 

     canvas.save(); 
     canvas.translate(canvas.getWidth()/2, canvas.getHeight()/2); 
     canvas.rotate(90); 
     canvas.drawLine(0, 0, 200, 0, tempp); 
     canvas.drawText("90'", 100, 8, tempp); 
     canvas.restore(); 

     canvas.save(); 
     canvas.translate(canvas.getWidth()/2, canvas.getHeight()/2); 
     canvas.rotate(180); 
     canvas.drawLine(0, 0, 200, 0, tempp); 
     canvas.drawText("180'", 100, 8, tempp); 
     canvas.restore(); 
    } 

    public int colorize(){ 
     return Color.argb(100, Math.round(255-MyMath.map(similarity, 0, 1, 0, 255)), 0, Math.round(MyMath.map(similarity, 0, 1, 0, 255))); 
    } 

    public void rotate(float degrees){ 
     transform.setTranslate(120, 160); 
     transform.setRotate(degrees, 0, 0); 

     // Create new float[] to hold the rotated coordinates 
     float[] pts = new float[2]; 

     // Initialize the array with our Coordinate 
     pts[0] = p.x; 
     pts[1] = p.y; 

     // Use the Matrix to map the points 
     transform.mapPoints(pts); 

     p.set((int)pts[0], (int)pts[1]); 
     // NOTE: pts will be changed by transform.mapPoints call 
     // after the call, pts will hold the new cooridnates 

     // Now, create a new Point from our new coordinates 
     //Point newPoint = new Point((int)pts[0], (int)pts[1]); 

     // Return the new point 
     //p.set(newPoint.x, newPoint.y); 
     //return newPoint; 
    } 

    public void translate(int x, int y){ 
     tx = x; 
     ty = y; 
    } 

    public void recalculateCoordinates(){ 
     x = (float) ((x * android.util.FloatMath.cos(r)) - (y * android.util.FloatMath.sin(r))); 
     y = (float) ((x * android.util.FloatMath.sin(r)) - (y * android.util.FloatMath.cos(r))); 
    } 
    /** 
    * @return the similarity 
    */ 
    public float getSimilarity() { 
     return similarity; 
    } 

    /** 
    * @param similarity the similarity to set 
    */ 
    public void setSimilarity(float similarity) { 
     this.similarity = similarity; 
    } 

    /** 
    * @return the x 
    */ 
    public float getX() { 
     return x; 
    } 

    /** 
    * @param x the x to set 
    */ 
    public void setX(float x) { 
     this.x = x; 
    } 

    /** 
    * @return the y 
    */ 
    public float getY() { 
     return y; 
    } 

    /** 
    * @param y the y to set 
    */ 
    public void setY(float y) { 
     this.y = y; 
    } 

    /** 
    * @return the r 
    */ 
    public float getR() { 
     return r; 
    } 

    /** 
    * @param r the r to set 
    */ 
    public void setR(float r) { 
     this.r = r; 
    } 

    public Point getP() { 
     return p; 
    } 

    public void setP(Point p) { 
     this.p = p; 
    } 
    } 

这是CustomViewVisual1类:

public class CustomViewVisual1 extends View implements Runnable{ 
    int width; 
    int height; 
    int x = 0; 
    int y = 0; 
    int canvasScale = 1; 
    int countDraw = 0; 

    Thread t = null; 
    boolean isItOK = false; 

    Paint paint; 
    Particle[] p = new Particle[500]; 

    public CustomViewVisual1(Context context){ 
     super(context); 
     initView(); 
    } 


    public CustomViewVisual1(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     initView(); 
    } 

    private void initView() { 
     // TODO Auto-generated method stub 
     paint = new Paint(); 

     Random r = new Random(); 
     for (int i = 0; i < p.length; i++) { 
      p[i] = new Particle(width, r.nextFloat()); 
     } 
    } 

    @Override 
    protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
     // TODO Auto-generated method stub 
     super.onSizeChanged(w, h, oldw, oldh); 
     width = w; 
     height = h; 
     x = width/2; 
     y = height/2; 
     initView(); 
    } 


    @Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 
     //canvas.translate(width/2, height/2); 
     canvas.drawARGB(255, 0, 0, 0); 
     canvas.scale(canvasScale, canvasScale); 
     for (int i = 0; i < p.length; i++) { 
      p[i].display(canvas, paint, canvasScale); 
     } 

     paint.setColor(Color.WHITE); 
     canvas.drawCircle(x, y, 20, paint); 
     /* 
     paint.setColor(Color.CYAN); 
     canvas.drawRect(0, 0, width, 10, paint); 
     paint.setColor(Color.GREEN); 
     canvas.drawRect(0, height-10, width, height, paint); 
     paint.setColor(Color.YELLOW); 
     canvas.drawRect(0, 0, 10, height, paint); 
     paint.setColor(Color.MAGENTA); 
     canvas.drawRect(width-10, 0, width, height, paint); 
     */ 
     countDraw++; 
     Log.d("How many draw = ", ""+countDraw); 
    } 


    public float getCanvasScale() { 
     return canvasScale; 
    } 


    public void setCanvasScale(int canvasScale) { 
     this.canvasScale = canvasScale; 
    } 

    public void pause() { 
     isItOK = false; 
     while (true) { 
      try { 
       t.join(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      break; 
     } 
     t = null; 
    } 

    public void resume() { 
     isItOK = true; 
     t = new Thread(this); 
     t.start(); 
    } 


    @Override 
    public void run() { 
     // TODO Auto-generated method stub 
    } 
    } 

这是LayoutCanvas类:

public class LayoutCanvas extends Activity implements OnTouchListener{ 

    RelativeLayout rl; 
    SeekBar sb; 
    CustomViewVisual1 cView; 

    /* 
    * (non-Javadoc) 
    * 
    * @see android.app.Activity#onCreate(android.os.Bundle) 
    */ 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     // TODO Auto-generated method stub 
     super.onCreate(savedInstanceState); 
     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); 
     setContentView(R.layout.activity_layout_canvas); 

     cView = new CustomViewVisual1(this); 
     cView.setOnTouchListener(this); 

     rl = (RelativeLayout) findViewById(R.id.lay_canvas); 
     rl.setOnTouchListener(this); 
     rl.setOnLongClickListener(new OnLongClickListener(){ 
      @Override 
      public boolean onLongClick(View v) { 
       // TODO Auto-generated method stub 
       Log.d("on long touch", "keep touching"); 
       return false; 
      }}); 

     sb = (SeekBar) findViewById(R.id.sb_activity_layout_canvas); 
     sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){ 

      @Override 
      public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 
       Log.d("in progress changed", "before if() "+progress); 
       if(progress > 0 && progress <=10){ 
        Log.d("in progress changed", "in if() " + progress); 
        cView.setCanvasScale(progress); 
        cView.invalidate(); 
       } 
      } 

      @Override 
      public void onStartTrackingTouch(SeekBar seekBar) { 
       // TODO Auto-generated method stub 

      } 

      @Override 
      public void onStopTrackingTouch(SeekBar seekBar) { 
       // TODO Auto-generated method stub 

      }}); 

    } 

    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     // TODO Auto-generated method stub 
     Log.d("on touch", "Just touched"); 
     cView.x = (int) event.getX(); 
     cView.y = (int) event.getY(); 
     Log.d("cView x = ", ""+cView.x); 
     Log.d("cView y = ", ""+cView.y); 
     cView.invalidate(); 
     return false; 
    } 



    } 

这是布局的.xml file:

<?xml version="1.0" encoding="utf-8"?> 
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:id="@+id/lay_canvas"> 

     <SeekBar 
      android:id="@+id/sb_activity_layout_canvas" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:layout_above="@+id/button1" 
      android:layout_alignParentLeft="true" 
      android:max="10" /> 

     <Button 
      android:id="@+id/button1" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_alignParentBottom="true" 
      android:layout_alignParentLeft="true" 
      android:layout_toLeftOf="@+id/button2" 
      android:text="Button" /> 

     <Button 
      android:id="@+id/button2" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_alignParentBottom="true" 
      android:layout_centerHorizontal="true" 
      android:text="Button" /> 

     <Button 
      android:id="@+id/button3" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_alignParentBottom="true" 
      android:layout_alignParentRight="true" 
      android:layout_toRightOf="@+id/button2" 
      android:text="Button" /> 

     <com.anvil.thesis.CustomViewVisual1 
      android:id="@+id/myView1" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:layout_above="@+id/sb_activity_layout_canvas" 
      android:layout_alignParentLeft="true" 
      android:layout_alignParentTop="true" /> 

    </RelativeLayout> 
+0

“无论onTouch()或onProgressChanged()事件似乎使我的观点重绘”。似乎会导致?您的CustomViewVisual1.onDraw方法是否被调用? – Simon

+0

我使用了一个变量countDraw ++;和Log.d(“多少画=”,“”+ countDraw);在onDraw()并没有得到任何新的计数,除了一些初始的像2-4 – Arch

回答

2

好的,问题是你有自定义视图的两个实例。第一个是在您致电setContentView(R.layout.activity_layout_canvas);时创建的,并且您的布局文件已膨胀。此实例已添加到您的视图层次结构中。你

cView = new CustomViewVisual1(this); 
cView.setOnTouchListener(this); 

这一个明确创建第二个,但是,永远不会添加到您的视图层次。所以当你在onTouch上拨打cView.invalidate();它不会画,因为cView实际上并不在屏幕上。

你需要做的是让cView引用,用这样的布局膨胀的自定义视图什么:

cView = (CustomViewVisual1)findViewById(R.id.myView1); 
+0

非常感谢CaseyB它的工作! – Arch

相关问题