安卓如何使用XML布局中的View来绘制画布(canvas)。

6

基本上,我想使用XML布局,但我也想有一个可以执行图形的画布。我的做法是在XML布局中创建一个视图,如下所示。然后在应用程序中,我让视图绘制画布,但它没有起作用。我不确定我解决这个问题的方法是否完全错误。因此,请查看我的代码并告诉我是否有快速修复或更好的方法。非常感谢您的帮助。

<?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>

那是XML布局。
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);
        }
    }

}

}


你怎么确定它不起作用了呢?我看到一个画布(很可能是白色背景),以及你使用的颜料被设置为Color.White。白色在白色上意味着不可见! - trumpetlicks
背景自动变成黑色,所以显示白线应该会出现。 - steven minkus
1
为什么你创建一个SurfaceView,却从未将其附加到屏幕上呢?这感觉有很多问题。为什么不将你的SurfaceView子类添加到xml布局中呢? - nEx.Software
1
很好知道,在过去当我想要直接进行画布绘制时,我会子类化自己的UIView对象。你可以尝试定义你自己的SurfaceView作为XML文件中的视图,而不是拥有通用视图,你实际上是在尝试将你的表面视图放置到上面,然后在该对象中实现onDraw例程。我肯定已经让这个工作了。 - trumpetlicks
好的,那么在 XML 布局中放置 SurfaceView 子类的 XML 代码是什么?抱歉,我是新手。谢谢大家的回复。 - steven minkus
显示剩余2条评论
2个回答

1

从这里开始(命名空间部分“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> 

在你的TheSurface中,
实现可重写的例程:
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!!!
}

这应该能帮你完成绘图!!!

在我的情况下,你不必将其实现为SurfaceView,你可以将其实现为View,并且它不需要实现runnable!!!


我在那个代码上遇到了错误。我应该使用一些实现来解决吗?我尝试过可重写例程,但是我找不到类似的内容。 - steven minkus
你是否按照答案中所说的放置了命名空间? - trumpetlicks
我做了sm.view.test。电脑说Java代码有问题,甚至无法运行它。 - steven minkus
它抛出的错误在哪里?你是否将我在这里提供的代码设置为SurfaceView的子类或仅仅是View?你是否也将你的变量View v; 改为TheSurface v;? - trumpetlicks
抱歉回复晚了,但我会将下面的内容粘贴到新答案中。感谢您的帮助。 - steven minkus

0

我不确定我完全理解你想要做什么,但基于你在调用 View.draw() 后没有对画布进行任何操作的事实,我相信你可能会感到困惑。View.draw(Canvas) 将 View 绘制到画布上,而不会改变视图。

但是,如果您从位图创建画布,那么您可以将该位图设置为 ImageView 的图像:

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);

然而,这种方法比实现自己的视图不太正确:

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);
        }
    }

基本上,我的需求是一个拥有SurfaceView的XML布局,以便我可以添加画布(Canvas)。该画布将用于显示图形等内容。比如说,就像一个涂鸦应用程序,其中屏幕顶部1/4是用于选择颜色的XML按钮,底部3/4是可用于绘制的画布。你现在明白我想要实现什么了吗? - steven minkus
是的,View.draw() 方法并不是你要找的,相反,你需要重写 onDraw(canvas) 方法并对传递进来的 canvas 进行更改(即手指绘画)。然后只需要根据需要经常重绘视图,它将与已对画布进行的任何更改一同更新。请参考我的第二个代码块以获取示例。 - matt5784
不应该太重要,拥有一个视图和任何你喜欢的按钮或其他内容。视图应该是你自己实现的视图,并且你可以以任何你想要的方式(通过与视图进行触摸交互,例如)将输入带到画布上,然后使用画布重新绘制视图,使其随着画布的变化而更新。 - matt5784

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接