Android uses a view from an XML layout to draw a canvas

So basically I want to use an xml layout, but I also want a canvas where I can make graphics. What I did was look at my xml layout, as you can see below. Then in my application I pretended to draw a canvas, but it does not work. I am not sure if my method for solving this is completely wrong or what. So please just take a look at my code and tell me if you see a quick fix or if you have a better method. Thanks in advance, I really appreciate it.

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/bTest" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" /> <View android:id="@+id/vMain" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> 

i.e. xml location

 package sm.view.test; import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Align; import android.os.Bundle; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.View.OnTouchListener; import android.widget.Button; public class ViewActivity extends Activity implements OnTouchListener { /** Called when the activity is first created. */ View v; Button b; boolean isRun =true; SurfaceHolder ourHolder; Thread ourThread; Canvas canvas; boolean isTure = true; TheSurface ourSurfaceView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); b= (Button) findViewById(R.id.bTest); v = (View) findViewById(R.id.vMain); canvas = new Canvas(); ourSurfaceView = new TheSurface(this); ourSurfaceView.setOnTouchListener(this); v.draw(canvas); // v.setBackgroundColor(Color.BLUE); } protected void onPause() { // TODO Auto-generated method stub super.onPause(); ourSurfaceView.pause(); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); ourSurfaceView.resume(); } public boolean onTouch(View arg0, MotionEvent arg1) { // TODO Auto-generated method stub return false; } public class TheSurface extends SurfaceView implements Runnable{ public TheSurface(Context context) { super(context); ourHolder= getHolder(); } public void resume(){ isRun= true; ourThread = new Thread(this); ourThread.start(); } public void pause(){ isRun = false; while(true){ try { ourThread.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } break; } ourThread= null; } public void run() { // TODO Auto-generated method stub Paint textPaint = new Paint(); textPaint.setColor(Color.WHITE); while(isTure){ if(!ourHolder.getSurface().isValid()) continue; //v.draw(canvas); canvas = ourHolder.lockCanvas(); canvas.drawLine(0, 0, canvas.getWidth(), canvas.getHeight(), textPaint); ourHolder.unlockCanvasAndPost(canvas); v.draw(canvas); } } } 

}

+4
source share
2 answers

Start here (and for this you need your input also for the part of the namespace "yourProjectNamespace"):

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/bTest" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" /> <sm.view.test.TheSurface android:id="@+id/vMain" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> 

In your TheSurface

Implement the features described above:

 public TheSurface(Context C){ super(C); // Other setup code you want here } public TheSurface(Context C, AttributeSet attribs){ super(C, attribs); // Other setup code you want here } public TheSurface(Context C, AttributeSet attribs, int defStyle){ super(C, attribs, defStyle); // Other setup code you want here } protected void onDraw(Canvas canvas){ super.onDraw(canvas); Paint textPaint = new Paint(); textPaint.setColor(Color.WHITE); canvas.drawLine(0, 0, canvas.getWidth(), canvas.getHeight(), textPaint); // Other drawing functions here!!! } 

This should make your drawing complete!

Also in my case you do not need to implement this as a SurfaceView, you can just implement it as a view, and it does not need to implement runnable !!!

+1
source

I am not 100% sure, I understand what you are trying to do, but based on the fact that you do not seem to do anything with the canvas after calling View.draw (), I believe that you may be confused. View.draw (Canvas) draws a view onto the canvas, it does not change the view.

However, if you create a canvas from a bitmap, you can set the bitmap as an ImageView image:

 Bitmap bm = Bitmap.createBitmap( x-size, y-size, Config.ARGB_8888); Canvas c = new Canvas(bm); Paint textPaint = new Paint(); textPaint.setColor(Color.WHITE); canvas.drawLine(0, 0, canvas.getWidth(), canvas.getHeight(), textPaint); ImageView iView = (ImageView) view; iView.setImageBitmap(bm); 

However, this is a less correct way than implementing your own view:

 button.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { ((MyView)view).mContextVariable = true; //or false, etc //you might not need this invalidate, because the click event probably causes and invalidate to be called view.invalidate(); } } class MyView extends View { Paint myPaint; boolean mContextVariable; public MyView(Context context) { super(context); textPaint = new Paint(); textPaint.setColor(Color.WHITE); } @Override protected void onDraw(Canvas canvas) { if(mContextVariable) { canvas.drawLine(0, 0, canvas.getWidth(), canvas.getHeight(), textPaint); } else { //draw something else } canvas.drawText("testing", 0,0, textPaint); } } 
0
source

All Articles