实现效果如下:
需求功能点包含:
1:界面的文字为动态添加;
2:点击界面中的文字,开启编辑模式:可编辑文字内容,可设置字体颜色,字体类型,粗体及对齐等;
3:点击删除从界面上清除文字块;
4:拖动编辑模式下的文字块的四个锚点,可以按文字中心位置缩放,同时工具栏跟随文字缩放移动,始终右对齐;
需求分析和技术实现:
首先得确定如何技术实现,当然实现的方式和方法多种多样。本人给出这样一个解决办法:
1:在Activity中动态AddView方式添加一个TextView,采用相对布局layout, 文本内容系统默认并根据屏幕尺寸计算位置居中;
2:在动态添加的TextView的onTouch事件中通过setLayoutParams 改变leftMargin,topMargin 达到移动位置的目的;
3:单击TextView时隐藏自身,并在TextView所在位置动态AddView一个EditText,并把TextView的属性值例如:大小,位置,颜色等赋值给EditText;
4:在添加EditText的同时动态添加四个锚点,采用相对于EditText的相对布局,布局于EditText的四个角,设置好Margin值,使它看起来像如图所示那样;(锚点为自定义View,可响应Touch事件,供拖拽使用)
5:自定义好文本编辑按钮区域的控件:
6:采用和四个锚点同样的方式AddView到布局系统中;
7:编辑结束,点击EditText以外的区域把当前EditText从布局系统中删除,同时把此时的EditText属性赋值给步骤3隐藏的TextView,
包括位置,大小,颜色等等;
8:移动锚点缩放文字大小的实现:移动偏移时,按一定增量+=或-=原来的FontSize, 以放大为例:计算移动前的文字宽度w1 和移动后的文字宽度w2,(w2-w1)/2为LeftMargin应减少的量,从而相对完美达到了按中心点缩放的目的;
9:因为采用相对布局的缘故,工具栏自动跟随文字的缩放做移动和调整,始终保持和文字的右边线对齐;
10: 代码实现,收工!
技术实现如下:
贴主要步骤代码
1:动态添加一行文本:
private void addTextView() { finishEditText(); TextView showText = new TextView(this); showText.setTextColor(Color.WHITE); showText.setTextSize(defaultFontSize); Typeface typeFace = Typeface.createFromAsset(getAssets(), defaultFontType); showText.setTypeface(typeFace); showText.setOnTouchListener(this); onTextViewClickListener listener = new onTextViewClickListener(); showText.setOnClickListener(listener); showText.setText(getString(R.string.template_insert_default_text)); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); params.leftMargin = (relativeLayout.getMeasuredWidth() - (int) getTextWidth(showText)) / 2; params.topMargin = (relativeLayout.getMeasuredHeight() - marginTopValue) / 2; showText.setLayoutParams(params); //添加文本到主布局 relativeLayout.addView(showText); }
2:文字的移动:relativeLayout 为布局系统对象
public boolean onTouch(View view, MotionEvent event) { final int x = (int) event.getRawX(); final int y = (int) event.getRawY(); switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) view .getLayoutParams(); xDelta = x - params.leftMargin; yDelta = y - params.topMargin; break; case MotionEvent.ACTION_MOVE: RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view .getLayoutParams(); int xDistance = x - xDelta; int yDistance = y - yDelta; layoutParams.leftMargin = xDistance; layoutParams.topMargin = yDistance; view.setLayoutParams(layoutParams); break; } relativeLayout.invalidate(); return false; }
3:文字的缩放:FontSizeDragger为4个锚点
FontSizeDragger.onDraggerMove move = new FontSizeDragger.onDraggerMove() { @Override public void Move(int x, int y, int xOffSet, int yOffSet, FontSizeDragger dragger) { float currentFontSize = editText.getTextSize(); RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) editText .getLayoutParams(); TextPaint mTextPaint =editText.getPaint(); if (dragger.equals(leftTopDragger) || dragger.equals(leftBottomDragger)) {
if (xOffSet < 0) {//放大操作 float x1 = mTextPaint .measureText(editText.getText().toString()); currentFontSize += fontSizeChangeOffSet; editText.setTextSize(TypedValue.COMPLEX_UNIT_PX, currentFontSize); editText.invalidate(); float x2 = mTextPaint .measureText(editText.getText().toString()); layoutParams.leftMargin -= (int) (x2-x1)/2; // layoutParams.topMargin -= getOffSetDraggerY; }
...(省略其他代码)
效果图: