当前位置: 首页 > 知识库问答 >
问题:

如何创建一个可以在屏幕上绘制、保存图像并将其传输到另一个可绘制屏幕的活动?

田镜
2023-03-14

现在,我正在使用CustomView在画布上绘制,我需要将画布(可能作为位图)保存到FileOutputStream中,然后移动到另一个具有相同功能的CustomView。

我不确定我是否应该使用不同的方法来实现它,但是我正在做的任何事情都在我调用start Active(i)时崩溃。

我的理解是,我的CustomView是用onTouch()绘制的,它绘制到路径对象上,然后调用onDraw(canvas),它在画布上绘制路径。(如果我错了,请纠正我)。

此画布是否包含位图对象?还是每次调用onDraw都需要写入在onCreate()期间创建的单独位图?或者我需要为每次调用onDraw()创建一个新的临时位图吗?我看过很多不同的Q

这是我的主要活动:

公共类MainActivity扩展活动{

Bitmap pic;
CustomView mCustomView;
OnTouchListener touchListener;
Button eraseButton;
String [] files = { "File1.png", "File2.png", "File3.png" };

int color = Color.BLACK;

RelativeLayout layout;

private Paint paint = new Paint();
private Path path = new Path();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    layout = (RelativeLayout) findViewById(R.id.layout);
    mCustomView = new CustomView(this);
    //layout.buildDrawingCache(); should I use this?

    layout.addView(mCustomView);

    touchListener = new OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event){
            float eventX = event.getX();
            float eventY = event.getY();

            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                path.moveTo(eventX, eventY);
                break;
            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_UP:
                path.lineTo(eventX, eventY);
                break;
            }
            mCustomView.invalidate();
            return true;    
        }
    };
    mCustomView.setOnTouchListener(touchListener);
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

public boolean onOptionsItemSelected(MenuItem item){
    switch (item.getItemId()) {
      case R.id.black:
          Toast.makeText(this, "You have chosen " + getResources().getString(R.string.black) + ".",
                        Toast.LENGTH_SHORT).show();
          paint.setColor(Color.BLACK);
          color = Color.BLACK;         
          break;
      case R.id.red:
          Toast.makeText(this, "You have chosen " + getResources().getString(R.string.red) + ".",
                        Toast.LENGTH_SHORT).show();
          paint.setColor(Color.RED); 
          color = Color.RED;
          break;
      case R.id.blue:
          Toast.makeText(this, "You have chosen " + getResources().getString(R.string.blue) + ".",
                        Toast.LENGTH_SHORT).show();
          paint.setColor(Color.BLUE); 
          color = Color.BLUE;
          break;
      case R.id.yellow:
          Toast.makeText(this, "You have chosen " + getResources().getString(R.string.yellow) + ".",
                        Toast.LENGTH_SHORT).show();
          paint.setColor(Color.YELLOW); 
          color = Color.YELLOW;
          break;
      case R.id.erase:
          Toast.makeText(this, "You have chosen to clear the screen. The current pen is now Black.", Toast.LENGTH_SHORT).show();
          paint.setColor(Color.BLACK);
          color = Color.BLACK;
          path.reset();
          mCustomView.invalidate();
          item.setChecked(false);
          break;
      case R.id.next:
          nextScreen(); //saves the bitmap, and call startActivity(), crashing now
          return true;
      default:
          return super.onOptionsItemSelected(item);
      }
      item.setChecked(true);
      return true;
}

public void nextScreen(){
    try {
        FileOutputStream out = openFileOutput(files[0], Context.MODE_PRIVATE);
        pic.compress(Bitmap.CompressFormat.PNG, 100, out);
        out.close();
    } catch (Exception e){
        Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
        return;
    }
    Intent i = new Intent(this.getApplicationContext(), SecondActivity.class);
    i.putExtra("filename.png", files);
    startActivity(i);
}

public class CustomView extends View {

    public CustomView(Context context) {
        super(context);
        paint.setAntiAlias(true);
        paint.setColor(color);
        paint.setStyle(Paint.Style.STROKE);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (pic == null){
            pic = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888); //is this correct?
        }
        canvas.drawPath(path, paint);
        canvas.drawBitmap(pic, 0, 0, paint); //is this correct?
    }
}

}

共有1个答案

曹育
2023-03-14

如果要保存视图,应该使用公共位图getDrawingCache(),请参阅参考资料。尝试修改代码:

@Override
    protected void onDraw(Canvas canvas) {
        if (pic == null){
            pic = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888); //is this correct?
        }
        canvas.drawPath(path, paint);
        //canvas.drawBitmap(pic, 0, 0, paint); //is this correct?
    }

public void nextScreen(){
    try {
        Bitmap bitmap = mCustomView.getDrawingCache ();
        FileOutputStream out = openFileOutput(files[0], Context.MODE_PRIVATE);
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
        out.close();
    } catch (Exception e){
        Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
        return;
    }
    Intent i = new Intent(this.getApplicationContext(), SecondActivity.class);
    i.putExtra("filename.png", files);
    startActivity(i);
}
 类似资料:
  • 我必须创建一个新的类来创建一个全新的PaintComponent()吗?或者我会简单地创建一个新的Graphics2D对象,这样我就可以使用不同的字体、颜色等等?我想最让我困惑的是我不能调用不同的draw方法,因为我仍然需要传递g2d作为参数。因此,在我看来,我需要从另一个已经有g2d对象的方法中创建线程。 如果这让我感到困惑,我很抱歉,因为我仍然是Java的初学者。如果你需要更多的信息,尽管告诉

  • 问题内容: 如何从一个活动屏幕导航到另一个活动屏幕?在第一个屏幕中,我有一个按钮,如果我单击该按钮,则必须移至另一个“活动”屏幕。 问题答案:

  • 问题内容: 最近,我对一个奇怪的想法感到震惊,他想从/ dev / urandom中获取输入,将相关字符转换为随机整数,然后使用这些整数作为像素rgb / xy值来绘制到屏幕上。 我已经做过一些研究(在StackOverflow和其他地方),许多建议您可以直接直接写入/ dev / fb0,因为它是设备的文件表示形式。不幸的是,这似乎没有产生任何视觉上明显的结果。 我找到了一个来自QT教程(不再可

  • 我必须在reactjs中从一个屏幕传递数据到另一个屏幕。并在接收端显示数据。 我用路由器在屏幕之间导航也传递数据,但不能显示接收到的数据。下面的代码是我传递数据的地方。 我试图在屏幕2中使用以下代码获得道具

  • 问题内容: 我设法将一个脚本接收到一个字符串,该脚本从iOS应用程序接收设置速度和方向的命令。 问题是我没有实际的设备,所以我的应用程序将命令发送到我构建的一个使用龙卷风的小型python Web套接字服务器… 本质上,我理想中需要的是一种方法: 显示窗口每隔17毫秒,清除一次窗口,读取带有x和y的全局变量,并在x和y处绘制点或圆。 有没有方便的方法可以做到这一点,以便我可以直观地看到发生了什么?

  • 问题内容: 我要执行以下操作: 我希望在短时间内显示许多不同的像素和颜色配置-写入中间文件会太昂贵。 我如何最好地实现Python中的这一目标? 问题答案: 直接回答: 这只能通过特定于操作系统的API来完成。某些操作系统不允许直接更改屏幕上的像素。 在Windows上,您可以使用pywin32库通过调用获取屏幕的设备上下文,然后使用绘制像素。 当然,以这种方式绘制的内容可以随时删除。 正确答案: