Android 可拖动的文字

·  阅读 315

「这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战

Android 可拖动的文字

目前市面上关于图片编辑的app很多,无论是截图还是专业的图片处理的app,很多都会有添加标签,添加贴纸的功能,笔者在也曾经遇到过几次编辑图片的需求,都不是很专业的图片处理软件,所以花花时间,总能磨出来。该篇文章将讲解如何实现文字的可拖动的效果,并限制它的边界,延伸它的功能。

需求

  • 添加可以自定义的文字

  • 文字可以删除,可以替换

  • 文字需要限制边界

  • 文字可以设置字号

  • 文字需要可以设置对齐方式

  • 文字无需旋转(并非专业的图片处理app)

简单的实现

先看下效果图

09019fd45596604b8d3fbfc4d9566cad.jpeg

实际上所有的效果的代码逻辑非常清晰,只有自定义的View。那么来看看怎么实现的。

1. BaseStickerView类

定义 BaseStickerView 类并继承 ViewGroup,会默认需要创建一个构造方法


public BaseStickerView(Context context) {

super(context);

onInitialize(context);

}

复制代码

在该类中声明贴纸内容、可操作的按钮、帮助类、和缩放比例等属性


/* 贴纸内容 */

private View mContentView;

/* 可操作的按钮 */

private ImageView mRemoveView, mEditView;

/* 帮助类 */

private StickerMoveHelper mMoveHelper;

/* 默认缩放比 */

private float mScale = 1f;

复制代码

在构造方法中进行初始化视图。我们在初始化中,设置背景透明,将贴纸内容添加,初始化可操作的按钮,将可操作的按钮添加到视图。在这个方法中,我们还要初始化帮助类,主要的拖动方法在这个帮助类中进行,这样可以让代码结构更清晰一些。


public void onInitialize(Context context) {

// 背景透明

setBackgroundColor(Color.TRANSPARENT);

// 抽象 创建贴纸的视图,并添加

mContentView = onCreateContentView(context);

if (mContentView == null) return;

addView(mContentView, getContentLayoutParams());

// 创建可操作的图标

mRemoveView = new ImageView(context);

mRemoveView.setScaleType(ImageView.ScaleType.FIT_XY);

mRemoveView.setImageResource(R.drawable.sticker_ic_delete);

mEditView = new ImageView(context);

mEditView.setScaleType(ImageView.ScaleType.FIT_XY);

mEditView.setImageResource(R.drawable.sticker_ic_edit);

mRemoveView.setOnClickListener(this);

mEditView.setOnClickListener(this);

// 将组件view添加到视图

addView(mRemoveView, getAnchorLayoutParams());

addView(mEditView, getAnchorLayoutParams());

// 初始化这个帮助类

mMoveHelper = new StickerMoveHelper(this);

}

复制代码

我们在OnTouch的回调方法中,将事件传递给帮助类,让帮助类去帮我们实现滑动的效果。


@Override

public boolean onTouchEvent(MotionEvent event) {

boolean handled = mMoveHelper.onTouch(this, event, ((ViewGroup) getParent()).getWidth(), ((ViewGroup) getParent()).getHeight(), getWidth(), getHeight(), mScale, true);

return handled | super.onTouchEvent(event);

}

复制代码

2. StickerMoveHelper 帮助类

在移动类中限制了边界,边界即为父容器的宽高。在左上右下的边界均要判断,判断的逻辑也很简单,即超出父容器后,让视图保持不动,不改变x y 值。


public class StickerMoveHelper {

private static final String TAG = "StickerMoveHelper";

private final View mView;

private float mX, mY;

private static final Matrix M = new Matrix();

public StickerMoveHelper(View view) {

mView = view;

}

//isOverflow: 是否根据padding溢出边界

public boolean onTouch(View v, MotionEvent event, float parentWidth, float parentHeight, float width, float height, float scale, boolean isLimitBorder) {

switch (event.getActionMasked()) {

case MotionEvent.ACTION_DOWN:

mX = event.getX();

mY = event.getY();

M.reset();

M.setRotate(v.getRotation());

return true;

case MotionEvent.ACTION_MOVE:

float[] dxy = {event.getX() - mX, event.getY() - mY};

M.mapPoints(dxy);

float x = mView.getTranslationX() + dxy[0];

float y = mView.getTranslationY() + dxy[1];

// 限制边界 (考虑了按钮的宽高, 去掉TEXT_PADDING的计算,则是原先的状态)

if (isLimitBorder) {

if (x < (-StickerConfig.TEXT_PADDING)) x = (-StickerConfig.TEXT_PADDING);

if (x > (parentWidth - width + StickerConfig.TEXT_PADDING))

x = (parentWidth - width + StickerConfig.TEXT_PADDING);

if (y < (-StickerConfig.TEXT_PADDING)) y = -StickerConfig.TEXT_PADDING;

if (y > (parentHeight - height + StickerConfig.TEXT_PADDING))

y = (parentHeight - height + StickerConfig.TEXT_PADDING);

}

v.setTranslationX(x);

v.setTranslationY(y);

return true;

}

return false;

}

}

复制代码

3. StickerView

由于主要的逻辑都在BaseStickerView中,所以StickerView中主要是创建视图,可以创建文字 或者拓展图片。


public class StickerView extends BaseStickerView {

private static final String TAG = "StickerView";

private TextView mTextView;

public StickerView(Context context) {

super(context);

}

@Override

public View onCreateContentView(Context context) {

mTextView = new TextView(context);

mTextView.setPadding(StickerConfig.TEXT_PADDING, StickerConfig.TEXT_PADDING, StickerConfig.TEXT_PADDING, StickerConfig.TEXT_PADDING);

mTextView.setSingleLine();

mTextView.setTextColor(Color.BLACK);

mTextView.setTextSize(50);

return mTextView;

}

public void setText(String text) {

mTextView.setText(text);

}

}

复制代码

4. 使用

主要逻辑都在自定义的类中,使用起来也很方便了。


StickerView stickerView = new StickerView(this);

stickerView.setText("哈哈哈");

container.addView(stickerView);

复制代码
分类:
Android
标签:
分类:
Android
标签: