如何将 2D 图元绘制到作为布局子成员的 SurfaceView?
How do I draw 2D primtives to a SurfaceView that's a submember of my layout?
我正在学习 Android 和 Java。我熟悉其他语言的图形和编程。
我有一个简单的布局,在 RelativeLayout 中包含一些按钮、文本视图和 SurfaceView,如下所示:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Quit"
android:id="@+id/buttonShutdown"
android:layout_below="@+id/textView2"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:onClick="shutdown"/>
<SurfaceView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/surfaceView"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/buttonShutdown"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
然后我有一个简单的 MainActivity.java 是这样的:
public class MainActivity extends AppCompatActivity
{
SurfaceView surfaceView;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
holder = surfaceView.getHolder();
holder.getSurface();
}
protected void shutdown(View view)
{
System.exit(0);
}
}
显然我的代码还有一些内容,因为我有几个按钮和几个文本视图,但重点是我有一个包含多个小部件的布局,而 SurfaceView 只是其中之一。
我见过许多绘制到表面视图的示例,但它们似乎都占据了整个屏幕和内容。
我怎样才能简单地在我的 SurfaceView 上绘制二维线和东西而不删除我的其余代码或布局小部件?
我已经为此工作了好几天,我从来没有花这么多精力在任何其他 language/framework 上来简单地画一些二维线!
我将非常感谢任何适用于与我现有布局的工作示例。
更新:
澄清一下,我遇到的问题是如何在 surfaceView 上获取句柄以获得处理程序以便在其上获取 canvas。一旦获得 canvas 界面,我就可以锁定、绘制和解锁。但是我不知道如何将 Canvas 附加到 surfaceView。
更新:
我想我现在有一个表面视图的支架,但我如何获得它的 canvas?
非常感谢,
杰西
好吧,经过多次拉扯,我开始工作了。
现在请各位大人注意:这是一个非常非常简单的教育演示,用于在表面视图中的屏幕上绘制线条的最少代码。我也知道 holder.getSurface();需要一些时间才能活跃起来,因此无法立即进行绘制。这就是它在 onClick 中的原因。我也知道 SurfaceView 渲染应该从它自己的线程完成,并且应该设置 3 个回调。
这只是一个简单的示例,所以请不要因为我没有编写理想的成熟应用而责备我!谢谢你。
我的MainActivity.java:
package com.gladeworks.gwscope ;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity
{
TextView textView = null;
SurfaceView surfaceView;
SurfaceHolder holder;
Canvas canvas;
Paint paint;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
textView.setText("Press the Draw button!");
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
holder = surfaceView.getHolder();
holder.getSurface();
paint = new Paint();
final Button buttonDraw = (Button) findViewById(R.id.buttonDraw);
buttonDraw.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
draw(view);
}
});
}
protected void draw(View view) //This gets called when the Draw button is clicked.
{
paint.setColor(Color.GREEN);
paint.setStrokeWidth(5);
canvas = holder.lockCanvas();
if (canvas == null) {
textView.setText("Canvas is still null");
} else {
canvas.drawRGB(32, 32, 255); //Clear the canvas to light blue
canvas.drawLine(0,0,1000,1000,paint);//Draw a line from top left corner down and right.
holder.unlockCanvasAndPost(canvas);
textView.setText("Done drawing!");
}
}
}
这是我的 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.gladeworks.gwscope.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Uninitialized"
android:id="@+id/textView"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignBottom="@+id/buttonExit"
android:layout_toLeftOf="@+id/buttonExit"
android:layout_toStartOf="@+id/buttonExit"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Quit"
android:id="@+id/buttonExit"
android:layout_alignTop="@+id/buttonDraw"
android:layout_toLeftOf="@+id/buttonDraw"
android:layout_toStartOf="@+id/buttonDraw"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Draw"
android:id="@+id/buttonDraw"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/buttonExit"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"/>
</RelativeLayout>
需要改进的地方:
画线代码应该在它自己的线程中,这样它就不会阻塞用户界面线程。
按钮和其他东西的标签实际上应该在资源文件中定义,以便于翻译工作。
canvas 和 SurfaceView 应该设置回调以处理创建、更改和销毁。
但这应该为初学者提供一条清晰的路径,以了解将线条图形绘制到 SurfaceView 所需的步骤顺序。
我正在学习 Android 和 Java。我熟悉其他语言的图形和编程。
我有一个简单的布局,在 RelativeLayout 中包含一些按钮、文本视图和 SurfaceView,如下所示:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Quit"
android:id="@+id/buttonShutdown"
android:layout_below="@+id/textView2"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:onClick="shutdown"/>
<SurfaceView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/surfaceView"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/buttonShutdown"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
然后我有一个简单的 MainActivity.java 是这样的:
public class MainActivity extends AppCompatActivity
{
SurfaceView surfaceView;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
holder = surfaceView.getHolder();
holder.getSurface();
}
protected void shutdown(View view)
{
System.exit(0);
}
}
显然我的代码还有一些内容,因为我有几个按钮和几个文本视图,但重点是我有一个包含多个小部件的布局,而 SurfaceView 只是其中之一。
我见过许多绘制到表面视图的示例,但它们似乎都占据了整个屏幕和内容。
我怎样才能简单地在我的 SurfaceView 上绘制二维线和东西而不删除我的其余代码或布局小部件?
我已经为此工作了好几天,我从来没有花这么多精力在任何其他 language/framework 上来简单地画一些二维线!
我将非常感谢任何适用于与我现有布局的工作示例。
更新:
澄清一下,我遇到的问题是如何在 surfaceView 上获取句柄以获得处理程序以便在其上获取 canvas。一旦获得 canvas 界面,我就可以锁定、绘制和解锁。但是我不知道如何将 Canvas 附加到 surfaceView。
更新:
我想我现在有一个表面视图的支架,但我如何获得它的 canvas?
非常感谢,
杰西
好吧,经过多次拉扯,我开始工作了。
现在请各位大人注意:这是一个非常非常简单的教育演示,用于在表面视图中的屏幕上绘制线条的最少代码。我也知道 holder.getSurface();需要一些时间才能活跃起来,因此无法立即进行绘制。这就是它在 onClick 中的原因。我也知道 SurfaceView 渲染应该从它自己的线程完成,并且应该设置 3 个回调。
这只是一个简单的示例,所以请不要因为我没有编写理想的成熟应用而责备我!谢谢你。
我的MainActivity.java:
package com.gladeworks.gwscope ;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity
{
TextView textView = null;
SurfaceView surfaceView;
SurfaceHolder holder;
Canvas canvas;
Paint paint;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
textView.setText("Press the Draw button!");
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
holder = surfaceView.getHolder();
holder.getSurface();
paint = new Paint();
final Button buttonDraw = (Button) findViewById(R.id.buttonDraw);
buttonDraw.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
draw(view);
}
});
}
protected void draw(View view) //This gets called when the Draw button is clicked.
{
paint.setColor(Color.GREEN);
paint.setStrokeWidth(5);
canvas = holder.lockCanvas();
if (canvas == null) {
textView.setText("Canvas is still null");
} else {
canvas.drawRGB(32, 32, 255); //Clear the canvas to light blue
canvas.drawLine(0,0,1000,1000,paint);//Draw a line from top left corner down and right.
holder.unlockCanvasAndPost(canvas);
textView.setText("Done drawing!");
}
}
}
这是我的 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.gladeworks.gwscope.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Uninitialized"
android:id="@+id/textView"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignBottom="@+id/buttonExit"
android:layout_toLeftOf="@+id/buttonExit"
android:layout_toStartOf="@+id/buttonExit"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Quit"
android:id="@+id/buttonExit"
android:layout_alignTop="@+id/buttonDraw"
android:layout_toLeftOf="@+id/buttonDraw"
android:layout_toStartOf="@+id/buttonDraw"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Draw"
android:id="@+id/buttonDraw"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/buttonExit"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"/>
</RelativeLayout>
需要改进的地方: 画线代码应该在它自己的线程中,这样它就不会阻塞用户界面线程。 按钮和其他东西的标签实际上应该在资源文件中定义,以便于翻译工作。 canvas 和 SurfaceView 应该设置回调以处理创建、更改和销毁。
但这应该为初学者提供一条清晰的路径,以了解将线条图形绘制到 SurfaceView 所需的步骤顺序。