以编程方式截取屏幕截图时,Cardview 会丢失其半径

Cardview loses its radius when taken a screenshot programmatically

我在 cardview 中有约束布局。卡片视图在屏幕上看起来不错。只有当截屏时,它才会呈现为位图,这就是它失去角落的时候。我添加了位图视图的图片。约束布局与圆角重叠。我需要边到边的圆度。

下面是模拟器正确显示圆角的截图:

这是渲染到位图的视图:

下面是我的示例代码。

public class MainActivity extends AppCompatActivity {

    private CardView cardView;
    private Button button;
    private ConstraintLayout parentLayoutA;
    private ConstraintLayout layoutB;
    private ConstraintLayout childLayout;
    private ConstraintSet innerSet;
    private ConstraintSet outerSet;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        CreateCardViewProgrammatically();
    }


    public void CreateCardViewProgrammatically(){

        cardView = new CardView(this);
        childLayout = new ConstraintLayout(this);
        parentLayoutA = new ConstraintLayout(this);
        layoutB = new ConstraintLayout(this);
        button = new Button(this);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            layoutB.setClipToOutline(true);
        }

        cardView.setRadius(150);

        button.setText("Click!!");
        button.setTextColor(Color.BLACK);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               takeScreenShot();
            }
        });

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            parentLayoutA.setId(View.generateViewId());
            layoutB.setId(View.generateViewId());
            childLayout.setId(View.generateViewId());
            cardView.setId(View.generateViewId());
            button.setId(View.generateViewId());
        }

        innerSet = new ConstraintSet();
        outerSet = new ConstraintSet();

        ConstraintLayout.LayoutParams parentParams = new ConstraintLayout.LayoutParams(
                ConstraintLayout.LayoutParams.MATCH_PARENT,
                ConstraintLayout.LayoutParams.MATCH_PARENT
        );

        layoutB.setLayoutParams(parentParams);
        childLayout.setLayoutParams(parentParams);
        cardView.setCardElevation(0);
        cardView.setPadding(50,50,50,50);

        parentLayoutA.addView(layoutB);
        layoutB.addView(cardView);
        cardView.addView(childLayout);
        childLayout.addView(button);

        innerSet.centerHorizontally(button.getId(), ConstraintSet.PARENT_ID);
        innerSet.centerVertically(button.getId(), ConstraintSet.PARENT_ID);
        innerSet.constrainHeight(button.getId(), 200);

        outerSet.connect(cardView.getId(), ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END, 200);
        outerSet.connect(cardView.getId(), ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START, 200);
        outerSet.centerHorizontally(cardView.getId(), ConstraintSet.PARENT_ID);
        outerSet.centerVertically(cardView.getId(), ConstraintSet.PARENT_ID);
        outerSet.constrainHeight(cardView.getId(), 1500);

        innerSet.applyTo(childLayout);
        outerSet.applyTo(layoutB);

        setContentView(parentLayoutA);

        parentLayoutA.setBackgroundColor(Color.YELLOW);
        layoutB.setBackgroundColor(Color.MAGENTA);
        cardView.setCardBackgroundColor(Color.GREEN);
        childLayout.setBackgroundColor(Color.BLUE);
    }

    public void takeScreenShot() {
        imageFromView(parentLayoutA);
    }

    public Bitmap imageFromView(View view) {

        DisplayMetrics metrics = this.getApplication().getResources().getDisplayMetrics();
        int width = view.getWidth() > 0 ? view.getWidth() : metrics.widthPixels;
        int height = view.getHeight() > 0 ? view.getHeight() : metrics.heightPixels;

        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        view.draw(canvas);

        return bitmap;
    }

从你的代码来看,我不清楚你想要完成什么。但是,如果您更改以下行

cardView.setCardBackgroundColor(Color.GREEN);

cardView.setCardBackgroundColor(Color.BLUE);

并删除行

childLayout.setBackgroundColor(Color.BLUE);

您会看到您的屏幕图像按照我认为您想要的方式捕获。


根本问题是圆角裁剪取决于硬件层,该硬件层为视图显示系统生成的 canvas 启用,但在您生成自己的位图和 canvas.您可以使用 Canvas#isHardwareAccelerated()

进行检查

看看Taking Screenshot Programmatically Using PixelCopy Api for an approach that you might be able to take. Also, see PixelCopy

Here 是 GitHub 上的一个小项目,演示如何着手捕获布局。这个演示应用程序只是使用问题中的代码来显示布局,捕获布局并在 ImageView 中重新显示它。重新显示中的 TextView 仅显示 "Captured!"