Android 사용자 정의 컨트롤 QQ 편집 및 원형 이미지 선택
우선 그림 을 처리 하 는 사용자 정의 컨트롤 을 만들어 서 들 어 오 는 그림 을 사용자 가 선택 한 영역 을 거 쳐 일정한 모양 으로 처리 해 야 합 니 다.
어떤 앱 은 그림 에 사각형 구역 을 그 려 서 선택 한 내용 을 표시 하고,어떤 앱 은 두 손가락 을 확대 해서 축소 하고,그림 을 드래그 해서 그림 을 선택한다.원형 두상 은 그림 을 바 꾸 는 것 이 좋다.
원형 구역 은 크기 를 조절 할 수 있 습 니 다.
이 사용자 정의 View 의 이미지 부분 은 배경 그림,반투명 몽 층,밝 은 색 구역 으로 나 뉘 는데...코드 를 직접 붙 이 는 것 이 좋 겠 습 니 다.
package com.example.jjj.widget;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
public class RoundEditImageView extends View {
private Bitmap bitmap;
RectF clipBounds, dst, src;
Paint clearPaint;
//
private int w, h;
//
private float radius = 150f;
//
private RectF circleBounds;
//
private float max_scale = 2.0f;
//
private float distance;
private float x0, y0;
private boolean doublePoint;
public RoundEditImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public RoundEditImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RoundEditImageView(Context context) {
super(context);
init();
}
private void init() {
clearPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
clearPaint.setColor(Color.GRAY);
clearPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (bitmap != null) {
canvas.drawBitmap(bitmap, null, dst, null);// invalidate dst
}
// , bitmap
int count = canvas.saveLayer(clipBounds, null, Canvas.ALL_SAVE_FLAG);
canvas.drawColor(0x80000000);
canvas.drawCircle(w / 2, h / 2, radius, clearPaint);// ,
canvas.restoreToCount(count);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
this.w = w;
this.h = h;
// view
clipBounds = new RectF(0, 0, w, h);
float l, r, t, b;
if (bitmap != null) {
// , , fitCenter
if (w / (float) h > bitmap.getWidth() / (float) bitmap.getHeight()) {
//
float w_ = h * bitmap.getWidth() / (float) bitmap.getHeight();
l = w / 2f - w_ / 2f;
r = w / 2f + w_ / 2f;
t = 0;
b = h;
} else {
// , view
float h_ = w * bitmap.getHeight() / (float) bitmap.getWidth();
l = 0;
r = w;
t = h / 2f - h_ / 2f;
b = h / 2f + h_ / 2f;
}
dst = new RectF(l, t, r, b);//
src = new RectF(l, t, r, b);//
max_scale = Math.max(max_scale, bitmap.getWidth() / src.width());
}
circleBounds = new RectF(w / 2 - radius, h / 2 - radius, w / 2 + radius, h / 2 + radius);
}
public void setImageBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
invalidate();
}
@Override
public boolean dispatchTouchEvent(MotionEvent e) {
if (e.getPointerCount() > 2) {//
return false;
} else if (e.getPointerCount() == 2) {
doublePoint = true;// , ,
handleDoubleMove(e);
} else {
//
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
x0 = e.getX();
y0 = e.getY();
break;
case MotionEvent.ACTION_MOVE:
if (doublePoint) {
break;
}
float x = e.getX();
float y = e.getY();
float w = dst.width();
float h = dst.height();
// ,
dst.left += x - x0;
if (dst.left > circleBounds.left) {
dst.left = circleBounds.left;
} else if (dst.left < circleBounds.right - w) {
dst.left = circleBounds.right - w;
}
dst.right = dst.left + w;
// ,
dst.top += y - y0;
if (dst.top > circleBounds.top) {
dst.top = circleBounds.top;
} else if (dst.top < circleBounds.bottom - h) {
dst.top = circleBounds.bottom - h;
}
dst.bottom = dst.top + h;
x0 = x;
y0 = y;
invalidate();
break;
case MotionEvent.ACTION_UP:
doublePoint = false;//
break;
}
}
return true;
}
//
private void handleDoubleMove(MotionEvent e) {
switch (e.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_DOWN:
distance = sqrt(e);
Log.d("px", "down:distance=" + distance);
break;
case MotionEvent.ACTION_MOVE:
scale(e);
break;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
}
private void scale(MotionEvent e) {
float dis = sqrt(e);
//
float pX = e.getX(0) / 2f + e.getX(1) / 2f;
float pY = e.getY(0) / 2f + e.getY(1) / 2f;
float scale = dis / distance;
Log.d("px", "move:distance=" + dis + ",scale to" + scale);
float w = dst.width();
float h = dst.height();
if (w * scale < radius * 2 || h * scale < radius * 2 || w * scale > src.width() * max_scale) {
// ,
return;
}
// dst scale
dst.left = (dst.left - pX) * scale + pX;
dst.right = (dst.right - pX) * scale + pX;
dst.top = (dst.top - pY) * scale + pY;
dst.bottom = (dst.bottom - pY) * scale + pY;
//
if (dst.left > circleBounds.left) {
dst.left = circleBounds.left;
dst.right = dst.left + w * scale;
} else if (dst.right < circleBounds.right) {
dst.right = circleBounds.right;
dst.left = dst.right - w * scale;
}
if (dst.top > circleBounds.top) {
dst.top = circleBounds.top;
dst.bottom = dst.top + h * scale;
} else if (dst.bottom < circleBounds.bottom) {
dst.bottom = circleBounds.bottom;
dst.top = dst.bottom - h * scale;
}
invalidate();
distance = dis;
}
private float sqrt(MotionEvent e) {
return (float) Math.sqrt((e.getX(0) - e.getX(1)) * (e.getX(0) - e.getX(1)) + (e.getY(0) - e.getY(1)) * (e.getY(0) - e.getY(1)));
}
// bitmap
public Bitmap extractBitmap(int width) {
Bitmap outBitmap = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(outBitmap);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(Color.GRAY);
canvas.drawCircle(width / 2, width / 2, width / 2, p);
float scale = dst.width() / bitmap.getWidth();
int w = (int) (circleBounds.width() / scale);
int l = (int) ((circleBounds.left - dst.left) / scale);
int r = l + w;
int t = (int) ((circleBounds.top - dst.top) / scale);
int b = t + w;
Rect resRect = new Rect(l, t, r, b);
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, resRect, canvas.getClipBounds(), paint);
return outBitmap;
}
}
Activity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select_header);
RoundEditImageView imageView = (RoundEditImageView) findViewById(R.id.roundEditImageView1);
bitmap = BitmapFactory.decodeFile(imagePath);
imageView.setImageBitmap(bitmap);
}
@Override
public void onClick(View v) {
// 300*300
Bitmap result = imageView.extractBitmap(300);
// png
FileOutputStream out = new FileOutputStream(new File(filePath));
result.compress(Bitmap.CompressFormat.PNG, 100, out);
//
...
}
수 요 는 QQ 를 모방 하 는 것 으로 본인 이 설명 을 잘 못 해서 놀 고 있 습 니 다.이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.