Skip to content

Commit ece506a

Browse files
author
miuyongjun
committed
增加双手触摸
增加选中排到最前处理
1 parent cb73488 commit ece506a

File tree

4 files changed

+138
-20
lines changed

4 files changed

+138
-20
lines changed

app/src/main/java/miaoyongjun/sticker/MainActivity.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ protected void onCreate(Bundle savedInstanceState) {
3030
cleanTv = (TextView) findViewById(R.id.cleanTv);
3131
nextTv = (TextView) findViewById(R.id.nextTv);
3232
stickerView = (StickerView) findViewById(R.id.stickerView);
33-
33+
stickerView.setMinStickerSizeScale(0.9f);
3434
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
3535
linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
3636
recyclerView.setLayoutManager(linearLayoutManager);
@@ -51,7 +51,7 @@ public void onClick(View v) {
5151
nextTv.setOnClickListener(new View.OnClickListener() {
5252
@Override
5353
public void onClick(View v) {
54-
BitmapUtil.FINAL_BITMAP = stickerView.getFinalStickerView();
54+
BitmapUtil.FINAL_BITMAP = stickerView.saveSticker();
5555
Intent intent = new Intent(MainActivity.this, PictureActivity.class);
5656
startActivity(intent);
5757
}

stickerview/src/main/java/miaoyongjun/stickerview/Sticker.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
import android.graphics.Bitmap;
44
import android.graphics.Matrix;
55
import android.graphics.Path;
6-
6+
/**
7+
* Author: miaoyongjun
8+
* Date : 17/8/1
9+
*/
710

811
public class Sticker {
912

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package miaoyongjun.stickerview;
2+
3+
import android.support.annotation.Nullable;
4+
import android.view.MotionEvent;
5+
6+
/**
7+
* Author: miaoyongjun
8+
* Date : 17/8/6
9+
*/
10+
11+
public class StickerUtil {
12+
13+
static float calculateRotation(@Nullable MotionEvent event) {
14+
if (event == null || event.getPointerCount() < 2) {
15+
return 0f;
16+
}
17+
return calculateRotation(event.getX(0), event.getY(0), event.getX(1), event.getY(1));
18+
}
19+
20+
static float calculateRotation(float x1, float y1, float x2, float y2) {
21+
double x = x1 - x2;
22+
double y = y1 - y2;
23+
double radians = Math.atan2(y, x);
24+
return (float) Math.toDegrees(radians);
25+
}
26+
27+
static float calculateDistance(@Nullable MotionEvent event) {
28+
if (event == null || event.getPointerCount() < 2) {
29+
return 0f;
30+
}
31+
return calculateDistance(event.getX(0), event.getY(0), event.getX(1), event.getY(1));
32+
}
33+
34+
static float calculateDistance(float x1, float y1, float x2, float y2) {
35+
double x = x1 - x2;
36+
double y = y1 - y2;
37+
return (float) Math.sqrt(x * x + y * y);
38+
}
39+
}

stickerview/src/main/java/miaoyongjun/stickerview/StickerView.java

Lines changed: 93 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,18 @@
1414
import android.graphics.RectF;
1515
import android.graphics.Region;
1616
import android.support.annotation.DrawableRes;
17+
import android.support.annotation.Nullable;
18+
import android.support.v4.view.MotionEventCompat;
1719
import android.support.v7.widget.AppCompatImageView;
1820
import android.util.AttributeSet;
1921
import android.view.MotionEvent;
2022

2123
import java.util.ArrayList;
22-
24+
import java.util.Collections;
25+
/**
26+
* Author: miaoyongjun
27+
* Date : 17/8/1
28+
*/
2329

2430
public class StickerView extends AppCompatImageView {
2531

@@ -174,12 +180,17 @@ private void drawBtn(Sticker sticker, Canvas canvas) {
174180
public boolean onTouchEvent(MotionEvent event) {
175181
float evX = event.getX(0);
176182
float evY = event.getY(0);
177-
178-
switch (event.getAction()) {
183+
int action = MotionEventCompat.getActionMasked(event);
184+
switch (action) {
179185
case MotionEvent.ACTION_POINTER_DOWN:
180-
//然并卵的代码
181-
evX = event.getX(event.getPointerCount() - 1);
182-
evY = event.getY(event.getPointerCount() - 1);
186+
midPoint = calculateMidPoint(event);
187+
oldDistance = StickerUtil.calculateDistance(event);
188+
oldRotation = StickerUtil.calculateRotation(event);
189+
if (touchInsideSticker(event.getX(0), event.getY(0))
190+
&& touchInsideSticker(event.getX(1), event.getY(1))) {
191+
state = TouchState.DOUBLE_TOUCH;
192+
}
193+
break;
183194
case MotionEvent.ACTION_DOWN:
184195
if (touchInsideDeleteButton(evX, evY)) {
185196
state = TouchState.PRESS_DELETE;
@@ -194,13 +205,17 @@ public boolean onTouchEvent(MotionEvent event) {
194205
} else {
195206
state = TouchState.TOUCHING_OUTSIDE;
196207
}
208+
197209
break;
198210
case MotionEvent.ACTION_MOVE:
199211
float dx = evX - lastPoint.x;
200212
float dy = evY - lastPoint.y;
201213
if (state == TouchState.PRESS_SCALE_AND_ROTATE) {
202214
rotateAndScale(evX, evY);
203215
}
216+
if (state == TouchState.DOUBLE_TOUCH) {
217+
rotateAndScaleDoubleTouch(event);
218+
}
204219
if (state == TouchState.TOUCHING_INSIDE) {
205220
translate(dx, dy);
206221
}
@@ -221,40 +236,99 @@ public boolean onTouchEvent(MotionEvent event) {
221236
invalidate();
222237
}
223238
break;
239+
case MotionEvent.ACTION_POINTER_UP:
240+
oldDistance = 0;
241+
oldRotation = 0;
242+
break;
224243
}
225244
lastPoint.x = evX;
226245
lastPoint.y = evY;
227246
return true;
228247
}
229248

249+
private void rotateAndScaleDoubleTouch(MotionEvent event) {
250+
if (event.getPointerCount() < 2) {
251+
return;
252+
}
253+
//双手旋转时根据映射出的四个点坐标来判断最小值的临界点
254+
float centerX = (currentSticker.getDst()[0] + currentSticker.getDst()[4]) / 2;
255+
float centerY = (currentSticker.getDst()[1] + currentSticker.getDst()[5]) / 2;
256+
float rightBottomX = currentSticker.getDst()[4];
257+
float rightBottomY = currentSticker.getDst()[5];
258+
259+
float pathMeasureLength = getPathMeasureLength(centerX, centerY, rightBottomX, rightBottomY);
260+
float newDistance = StickerUtil.calculateDistance(event);
261+
float newRotation = StickerUtil.calculateRotation(event);
262+
if (oldDistance != 0) {
263+
Matrix matrix = currentSticker.getMatrix();
264+
//可以放大 不能缩小
265+
if ((newDistance - oldDistance) > 0) {
266+
matrix.postScale(newDistance / oldDistance, newDistance / oldDistance, midPoint.x,
267+
midPoint.y);
268+
} else if (pathMeasureLength > currentSticker.getMinStickerSize()) {
269+
matrix.postScale(newDistance / oldDistance, newDistance / oldDistance, midPoint.x,
270+
midPoint.y);
271+
}
272+
matrix.postRotate(newRotation - oldRotation, midPoint.x, midPoint.y);
273+
currentSticker.converse();
274+
}
275+
oldDistance = newDistance;
276+
oldRotation = newRotation;
277+
}
278+
230279
private void rotateAndScale(float evX, float evY) {
231280
float[] src = currentSticker.getRotateSrcPts();
232281
float[] dst = new float[4];
233282
float centerX = (currentSticker.getDst()[0] + currentSticker.getDst()[4]) / 2;
234283
float centerY = (currentSticker.getDst()[1] + currentSticker.getDst()[5]) / 2;
235284

236285
//获取到触摸点到中心点距离 计算到中心点的距离比例得到X和Y的比例 通过相似三角形计算出最终结果
237-
Path path = new Path();
238-
path.moveTo(centerX, centerY);
239-
path.lineTo(evX, evY);
240-
PathMeasure pathMeasure = new PathMeasure(path, false);
241-
if (pathMeasure.getLength() < currentSticker.getMinStickerSize()) {
242-
evX = currentSticker.getMinStickerSize() * (evX - centerX) / pathMeasure.getLength() + centerX;
243-
evY = currentSticker.getMinStickerSize() * (evY - centerY) / pathMeasure.getLength() + centerY;
286+
float pathMeasureLength = getPathMeasureLength(centerX, centerY, evX, evY);
287+
if (pathMeasureLength < currentSticker.getMinStickerSize()) {
288+
evX = currentSticker.getMinStickerSize() * (evX - centerX) / pathMeasureLength + centerX;
289+
evY = currentSticker.getMinStickerSize() * (evY - centerY) / pathMeasureLength + centerY;
244290
}
245-
246291
dst[0] = centerX;
247292
dst[1] = centerY;
248293
dst[2] = evX;
249294
dst[3] = evY;
250-
251295
Matrix matrix = currentSticker.getMatrix();
252296
matrix.reset();
253297
//并不是将图片从一组点变成另一组点 而是获取这两个组的点变换的matrix
254298
matrix.setPolyToPoly(src, 0, dst, 0, 2);
255299
currentSticker.converse();
256300
}
257301

302+
private float getPathMeasureLength(float moveX, float moveY, float lineX, float lineY) {
303+
Path path = new Path();
304+
path.moveTo(moveX, moveY);
305+
path.lineTo(lineX, lineY);
306+
PathMeasure pathMeasure = new PathMeasure(path, false);
307+
return pathMeasure.getLength();
308+
}
309+
310+
private float oldDistance = 0f;
311+
private float oldRotation = 0f;
312+
private PointF midPoint = new PointF();
313+
314+
315+
protected PointF calculateMidPoint(@Nullable MotionEvent event) {
316+
if (event == null || event.getPointerCount() < 2) {
317+
midPoint.set(0, 0);
318+
return midPoint;
319+
}
320+
try {
321+
float x = (event.getX(0) + event.getX(1)) / 2;
322+
float y = (event.getY(0) + event.getY(1)) / 2;
323+
midPoint.set(x, y);
324+
} catch (IllegalArgumentException e) {
325+
e.printStackTrace();
326+
}
327+
328+
return midPoint;
329+
}
330+
331+
258332
private boolean touchInsideRotateButton(float evX, float evY) {
259333
return currentSticker != null && new RectF(currentSticker.getDst()[4] - btnRotateBitmap.getWidth() / 2, currentSticker.getDst()[5] - btnRotateBitmap.getHeight() / 2, currentSticker.getDst()[4] + btnRotateBitmap.getWidth() / 2, currentSticker.getDst()[5] + btnRotateBitmap.getHeight() / 2).contains(evX, evY);
260334
}
@@ -278,14 +352,16 @@ private boolean touchInsideSticker(float evX, float evY) {
278352
region.setPath(sticker.getBoundPath(), new Region(0, 0, getMeasuredWidth(), getMeasuredHeight()));
279353
if (region.contains((int) evX, (int) evY)) {
280354
currentSticker = sticker;
355+
int index = mStickers.indexOf(currentSticker);
356+
Collections.swap(mStickers, index, mStickers.size() - 1);
281357
return true;
282358
}
283359
}
284360
return false;
285361
}
286362

287363
private enum TouchState {
288-
TOUCHING_INSIDE, TOUCHING_OUTSIDE, PRESS_DELETE, PRESS_SCALE_AND_ROTATE;
364+
TOUCHING_INSIDE, TOUCHING_OUTSIDE, PRESS_DELETE, PRESS_SCALE_AND_ROTATE, DOUBLE_TOUCH;
289365
}
290366

291367
public int getMaxStickerCount() {
@@ -365,7 +441,7 @@ public int dip2px(Context c, float dpValue) {
365441
return (int) (dpValue * scale + 0.5f);
366442
}
367443

368-
public Bitmap getFinalStickerView() {
444+
public Bitmap saveSticker() {
369445
currentSticker = null;
370446
Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),
371447
Bitmap.Config.ARGB_8888);

0 commit comments

Comments
 (0)