简体   繁体   中英

How to get a Bitmap from a scaled view in Android

I have a custom view named MyView with scaling correctly enabled, After scaling the view using fingers. I want to get a Bitmap of this resulting View, For that I use the getBitmap () method below. but it doesn't work. it only works if the view is not scaled (scaleFactor = 1,0f), I replaced getWidth (), getHeight () with getWidth () / scaleFactor, getHeight () / scaleFactor but it doesn't work either!

//These two methods are inside the MyView class
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    canvas.save();
    canvas.scale(scaleFactor, scaleFactor);

    canvas.drawPath(path, paint);

    canvas.restore();
}

public Bitmap getBitmap(){
    Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    draw(canvas);

    return bitmap;
}

So how do I get a bitmap from the scaled view (scaleFactor.= 1?0f)?

UPDATE: include full project:

//myview
public class MyView extends View {
    private Path path;
    private Paint paint;
    private ScaleGestureDetector scaleDetector;
    private float scaleFactor = 1.0f;

    public MyView(Context context) {
        super(context);
        init(context);
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context){
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.GREEN);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setStrokeCap(Paint.Cap.ROUND);
        path = new Path();

        //inside window
        path.addRect(300, 300, 600, 600, Path.Direction.CW);

        //outside window
        path.addRect(800, 800, 1000, 1000, Path.Direction.CW);

        //outside window
        path.addRect(1000, 1000, 1200, 1200, Path.Direction.CW);
        scaleDetector = new ScaleGestureDetector(context, new ScaleListener());
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save();
        canvas.scale(scaleFactor, scaleFactor);
        canvas.drawPath(path, paint);
        canvas.restore();
    }

    public Bitmap getBitmap(){
        Bitmap bitmap =
                Bitmap.createBitmap(
                        Math.round(getWidth()*scaleFactor),
                        Math.round(getHeight()*scaleFactor),
                        Bitmap.Config.ARGB_8888);

        Canvas canvas = new Canvas(bitmap);
        draw(canvas);
        return bitmap;
    }

    private class ScaleListener
            extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            scaleFactor *= detector.getScaleFactor();
            // Don't let the object get too small or too large.
            scaleFactor = Math.max(0.1f, Math.min(scaleFactor, 5f));
            invalidate();
            return true;
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        // Let the ScaleGestureDetector inspect all events.
        scaleDetector.onTouchEvent(ev);
        return true;
    }
}

Main activity

public class MainActivity extends AppCompatActivity {

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

        MyView myView = findViewById(R.id.my_view);
        Button button = findViewById(R.id.button);

        button.setOnClickListener(view -> {
            Bitmap bitmap = myView.getBitmap(); //add breakpoint in this line
            int width = bitmap.getWidth();
            int height = bitmap.getHeight();
        });
    }
}

xml

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.abdo.scaledviewtobitmapquestion.MyView
        android:id="@+id/my_view"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:text="Hello World!"
        app:layout_constraintBottom_toTopOf="@id/button"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Get Bitmap"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

In this project I am creating three rectangles, one inside the window and two outside the window, Before running this project I added a breakpoint in this line "Bitmap bitmap = myView.getBitmap ();" (The main activity) When the app is open, I zoom out the window until all 3 rectangles appear in the window, then click the button to see the bitmap of the debugger output.

Surprising, The bitmap does not include the three rectangles. it just captures the rectangle visible in the original window before scaling (scaleFactor = 1).

2 parts to the answer.

  1. scaleFactor > 1.0f is scale up, scaleFactor < 1.0f is scale down

So the calculation should be getWidth() * scaleFactor

eg scaleFactor of 0.5f is half size

  1. The size you need is an int and scaleFactor is a float , so you cannot get and exact width of the required bitmap though should be OK to round up using Math.round()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM