ToggleButton画布上绘制的文本和线条显示在屏幕上,但不显示在屏幕截图

时间:2016-10-13 08:42:55

标签: android canvas bitmap screenshot togglebutton

我创建了一个扩展MyToggleButton的视图ToogleButton。我覆盖了Togglebutton的onDraw方法,在按钮上画一条线并旋转它的文字。

以下是MyToggleButton

package com.example.gl.myapplication;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.text.TextPaint;
import android.widget.ToggleButton;

public class MyToggleButton extends ToggleButton {

    public float textRotation=0;

    public MyToggleButton(Context context, float rotationValue) {
        super(context);

        textRotation=rotationValue;
    }

    @Override
    protected void onDraw(Canvas canvas){

        TextPaint textPaint = getPaint();
        textPaint.setColor(getCurrentTextColor());
        textPaint.drawableState = getDrawableState();

        canvas.save();

        //paint
        Paint paint = new Paint();
        paint.setColor(Color.BLACK);
        paint.setStrokeWidth(7);
        paint.setStrokeCap(Paint.Cap.ROUND);

        canvas.drawLine(canvas.getWidth() / 2, canvas.getHeight() / 2, (float) (canvas.getHeight() / 2 + 400), (canvas.getHeight() / 2), paint);

        canvas.rotate(textRotation, canvas.getWidth() / 2, canvas.getHeight() / 2);

        getLayout().draw(canvas);

        canvas.restore();

    }


}

之后我想获得截图并查看它,为此我使用按下屏幕上第3个按钮调用的takeScreenshot()方法。屏幕截图代码基于How to programmatically take a screenshot in Android?。 stackoverflow上的其他帖子以及我在周围发现的各种网站和教程中都采用了相同的方法。

以下是我使用的MainActivity

package com.example.gl.myapplication;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AbsListView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Date;

public class MainActivity extends AppCompatActivity {

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

        //add 3 buttons
        addButtons();

    }


    private void addButtons(){

        LinearLayout linear1= (LinearLayout) findViewById(R.id.vert1);

        //MyToggleButton with rotated text
        MyToggleButton btn1 = new MyToggleButton(this,0);
        btn1.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
                LinearLayout.LayoutParams.WRAP_CONTENT));
        btn1.setTextOff("Button 1 not rotated");
        btn1.setTextOn("Button 1 not rotated");
        btn1.setText("Button 1 not rotated");
        linear1.addView(btn1);

        //MyToggleButton with normal text
        MyToggleButton btn2 = new MyToggleButton(this,50);
        btn2.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
                LinearLayout.LayoutParams.WRAP_CONTENT));
        btn2.setTextOff("Button 2 rotated");
        btn2.setTextOn("Button 2 rotated");
        btn2.setText("Button 2 rotated");
        linear1.addView(btn2);

        //button to create screenshot
        Button btn3 = new Button(this);
        btn3.setText("Create bitmap");
        btn3.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                takeScreenshot();

            }
        });
        linear1.addView(btn3);



    }

    //Screenshotcreator
        private void takeScreenshot() {
            try {
                View v1 = getWindow().getDecorView().getRootView();

                // create bitmap screen capture
                v1.setDrawingCacheEnabled(true);
                Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());

                v1.setDrawingCacheEnabled(false);

                ImageView imageView1 =(ImageView) findViewById(R.id.imageView1);
                imageView1.setImageBitmap(bitmap);


            } catch (Throwable e) {
                e.printStackTrace();
            }
        }


    }

以下是MainActivity

的布局
<?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.example.gl.myapplication.MainActivity"
    android:id="@+id/relative1">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/vert1">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="250dp"
            android:id="@+id/imageView1" />
    </LinearLayout>
</RelativeLayout>

问题是虽然屏幕上的一切看起来都不错,但屏幕截图的位图缺少绘制的线条和旋转的文本。

You can see the problem here. Screen is OK, screenshot is not.

位图中出现奇怪结果的原因是什么?

请注意屏幕截图中缺少设备back-home-recents按钮,以及状态栏信息(时间等)。我怀疑这是否与我的问题有关。这些元素不属于我的应用程序,因此预期它们不会出现在我使用v1 = getWindow().getDecorView().getRootView();获取的视图中但是我绘制旋转文本的画布和行确实属于该视图。 / p>

我的问题是:为什么画线和旋转的文字没有出现在屏幕截图上,我如何修改我的代码以获取它们的截图?

我不想做需要root设备的事情,也不能使用MediaProjection API,因为这是在API 21中添加的,但我希望我的应用程序也可以在android 4.4(API 19)上运行。最后,我知道存在外部库,例如Android Screenshot Library或https://android-arsenal.com/details/1/2793,但我不想使用任何外部库。

P.S。也许这是相关的:Surfaceview screenshot with line/ellipse drawn over it

1 个答案:

答案 0 :(得分:1)

问题是btn1.isDrawingChaceEnabled()btn2.isDrawingChaceEnabled()都返回false

即使您在RootView上调用setDrawingCacheEnabled(true),也不会在其所有子视图上递归设置为true(我使用Log.d进行了测试)。
这意味着您的ToggleButton的绘图缓存将为空,如android.view.View.getDrawingCache() javadoc中所述。

/**
 * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
 *
 * @return A non-scaled bitmap representing this view or null if cache is disabled.
 *
 * @see #getDrawingCache(boolean)
 */

因此,请确保为您感兴趣的每个观看次数设置setDrawingCacheEnabled(true) 例如,我在您的代码中添加了以下行:
在MainActivity中

    btn1.setDrawingCacheEnabled(true);
    btn2.setDrawingCacheEnabled(true);

And it looks like this