abstract class Sizer extends FrameLayout { private static final String TAG = "V"; private float[] points = new float[8]; private Matrix matrix = new Matrix(); private Matrix savedMatrix = new Matrix(); private TextPaint paint = new TextPaint(); private Layout layout; private int action = MotionEvent.ACTION_UP; public Sizer(Context context) { super(context); addView(getMainView(context)); paint.setTextSize(context.getResources().getDimensionPixelSize(android.R.dimen.app_icon_size) * 0.6f); paint.setColor(Color.LTGRAY); paint.setShadowLayer(1, 0, 1, Color.BLACK); } protected abstract View getMainView(Context context); @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { points[0] = points[4] = w * 0.5f; points[1] = points[5] = h * 0.5f; layout = new StaticLayout("drag view\nrotate & scale", paint, w, Layout.Alignment.ALIGN_CENTER, 1, 0, false); } @Override public boolean onTouchEvent(MotionEvent event) { action = event.getAction(); if (action == MotionEvent.ACTION_DOWN) { points[2] = event.getX(); points[3] = event.getY(); savedMatrix.set(matrix); } else { points[6] = event.getX(); points[7] = event.getY(); if (points[3] < getHeight() / 2) { matrix.setTranslate(points[6] - points[2], points[7] - points[3]); } else { matrix.setPolyToPoly(points, 0, points, 4, 2); } matrix.preConcat(savedMatrix); invalidate(); } return true; } @Override protected void dispatchDraw(Canvas canvas) { canvas.save(); canvas.concat(matrix); super.dispatchDraw(canvas); canvas.restore(); if (action == MotionEvent.ACTION_UP) { float dx = paint.getTextSize(); float y = getHeight() * 0.5f; canvas.drawLine(dx, y, getWidth() - dx, y, paint); canvas.translate(0, y - layout.getHeight() * 0.5f); layout.draw(canvas); } } }