Android Java实现ImageView拖拽调整、图片遮罩及JSON动态布局方案
解决方案:ImageView拖拽调整+遮罩合成(Java)
一、实现可拖拽的ImageView
自定义DraggableImageView,通过触摸事件监听实现拖拽功能,利用Matrix控制图片位置:
import android.content.Context; import android.graphics.Matrix; import android.graphics.PointF; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.ImageView; public class DraggableImageView extends ImageView { private final Matrix matrix = new Matrix(); private final Matrix savedMatrix = new Matrix(); private final PointF startPoint = new PointF(); private boolean isDragging = false; public DraggableImageView(Context context) { super(context); init(); } public DraggableImageView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public DraggableImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { setScaleType(ScaleType.MATRIX); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: savedMatrix.set(matrix); startPoint.set(event.getX(), event.getY()); isDragging = true; break; case MotionEvent.ACTION_MOVE: if (isDragging) { float dx = event.getX() - startPoint.x; float dy = event.getY() - startPoint.y; matrix.set(savedMatrix); matrix.postTranslate(dx, dy); setImageMatrix(matrix); } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: isDragging = false; break; } return true; } // 获取当前图片的变换矩阵,用于后续合成 public Matrix getCurrentMatrix() { return new Matrix(matrix); } }
二、实现遮罩合成功能
编写工具类MaskUtils,将拖拽调整后的图片与遮罩图合成,使用PorterDuff.Mode.SRC_IN实现遮罩裁剪效果:
import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; public class MaskUtils { /** * 合成原图与遮罩图 * @param sourceBitmap 拖拽调整后的原图 * @param maskBitmap 遮罩图 * @param matrix 原图的拖拽变换矩阵 * @return 合成后的Bitmap */ public static Bitmap applyMask(Bitmap sourceBitmap, Bitmap maskBitmap, Matrix matrix) { if (sourceBitmap == null || maskBitmap == null) return null; // 创建与原图尺寸一致的空白Bitmap Bitmap resultBitmap = Bitmap.createBitmap(sourceBitmap.getWidth(), sourceBitmap.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(resultBitmap); // 绘制变换后的原图 Paint paint = new Paint(); canvas.drawBitmap(sourceBitmap, matrix, paint); // 设置遮罩合成模式 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); // 将遮罩图缩放到原图尺寸后绘制 canvas.drawBitmap(maskBitmap, null, new Rect(0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight()), paint); paint.setXfermode(null); return resultBitmap; } }
三、在Activity中整合使用
假设布局包含DraggableImageView(id: draggable_img)、遮罩ImageView(id: mask_img)和合成按钮(id: btn_apply_mask):
import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.view.View; import android.widget.ImageView; import androidx.appcompat.app.AppCompatActivity; public class StoryMakerActivity extends AppCompatActivity { private DraggableImageView draggableImageView; private ImageView maskImageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_story_maker); draggableImageView = findViewById(R.id.draggable_img); maskImageView = findViewById(R.id.mask_img); // 示例:加载本地图片(实际替换为相册选择的图片) Bitmap sourceBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.source_img); draggableImageView.setImageBitmap(sourceBitmap); Bitmap maskBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.mask_img); maskImageView.setImageBitmap(maskBitmap); // 合成按钮点击事件 findViewById(R.id.btn_apply_mask).setOnClickListener(v -> applyMaskAndShowResult()); } private void applyMaskAndShowResult() { Bitmap sourceBitmap = ((BitmapDrawable) draggableImageView.getDrawable()).getBitmap(); Bitmap maskBitmap = ((BitmapDrawable) maskImageView.getDrawable()).getBitmap(); Matrix matrix = draggableImageView.getCurrentMatrix(); Bitmap resultBitmap = MaskUtils.applyMask(sourceBitmap, maskBitmap, matrix); if (resultBitmap != null) { // 展示合成后的图片 ImageView resultImg = findViewById(R.id.result_img); resultImg.setImageBitmap(resultBitmap); } } }
关键说明
- 拖拽功能通过
Matrix.postTranslate实现,需将ImageView的缩放类型设为ScaleType.MATRIX以支持自定义变换 - 遮罩合成使用
PorterDuff.Mode.SRC_IN,仅保留遮罩区域内的原图内容 - 若需支持缩放拖拽,可在
DraggableImageView中扩展GestureDetector添加缩放逻辑
内容的提问来源于stack exchange,提问作者vraj kalathiya
相关产品推荐
相关产品推荐

