canvas教程

Android编程实现支持拖动改变位置的图片中叠加文字功能示例

字号+ 作者:H5之家 来源:H5之家 2017-02-28 15:02 我要评论( )

本文详细介绍了Android编程实现支持拖动改变位置的图片中叠加文字功能的实例代码,有兴趣的同学可以将代码拿过去使用。

本文详细介绍了Android编程实现支持拖动改变位置的图片中叠加文字功能的实例代码,有兴趣的同学可以将代码拿过去使用。

本文实例讲述了Android编程实现支持拖动改变位置的图片中叠加文字功能。分享给大家供大家参考,具体如下:

之所以做了这么一个Demo,是因为最近项目中有一个奇葩的需求:用户拍摄照片后,分享到微信的同时添加备注,想获取用户在微信的弹出框输入的内容,保存在自己的服务器上。而事实上,这个内容程序是无法获取的,因此采取了一个折衷方案,将文字直接写在图片上。

首先上Demo效果图:

功能:

1.用户自由输入内容,可手动换行,并且行满也会自动换行。
2.可拖动改变图片中文本位置(文字不会超出图片区域)。
3.点击“生成图片”按钮之后,生成一张带有文字的图片文件。

代码不多,直接全部贴上了:

Activity:

 代码如下复制代码

/**

 * 将文字写在图片中(截图方式),支持拖动文字。

 * 说明:很明显,截图方式会降低图片的质量。如果需要保持图片质量可以使用canvas的方式,将文字直接绘制在图片之上(不过,使用此方式要实现文字拖动较为复杂)。

 */

publicclassMainActivityextendsAppCompatActivity {

  //图片组件

  privateImageView imageView;

  //位于图片中的文本组件

  privateTextView tvInImage;

  //图片和文本的父组件

  privateView containerView;

  //父组件的尺寸

  privatefloatimageWidth, imageHeight, imagePositionX, imagePositionY;

  @Override

  protectedvoidonCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.image_with_text);

    imageView = (ImageView) findViewById(R.id.writeText_img);

    EditText editText = (EditText) findViewById(R.id.writeText_et);

    tvInImage = (TextView) findViewById(R.id.writeText_image_tv);

    containerView = findViewById(R.id.writeText_img_rl);

    imageView.getViewTreeObserver().addOnGlobalLayoutListener(newViewTreeObserver.OnGlobalLayoutListener() {

      @Override

      publicvoidonGlobalLayout() {

        imageView.getViewTreeObserver().removeOnGlobalLayoutListener(this);

        imagePositionX = imageView.getX();

        imagePositionY = imageView.getY();

        imageWidth = imageView.getWidth();

        imageHeight = imageView.getHeight();

        //设置文本大小

        tvInImage.setMaxWidth((int) imageWidth);

      }

    });

    imageView.setImageBitmap(getScaledBitmap(R.mipmap.test_img));

    //输入框

    editText.addTextChangedListener(newTextWatcher() {

      @Override

      publicvoidbeforeTextChanged(CharSequence s,intstart,intcount,intafter) {

      }

      @Override

      publicvoidonTextChanged(CharSequence s,intstart,intbefore,intcount) {

        if(s.toString().equals("")) {

          tvInImage.setVisibility(View.INVISIBLE);

        }else{

          tvInImage.setVisibility(View.VISIBLE);

          tvInImage.setText(s);

        }

      }

      @Override

      publicvoidafterTextChanged(Editable s) {

      }

    });

    finalGestureDetector gestureDetector =newGestureDetector(this,newSimpleGestureListenerImpl());

    //移动

    tvInImage.setOnTouchListener(newView.OnTouchListener() {

      @Override

      publicbooleanonTouch(View v, MotionEvent event) {

        gestureDetector.onTouchEvent(event);

        returntrue;

      }

    });

  }

  //确认,生成图片

  publicvoidconfirm(View view) {

    Bitmap bm = loadBitmapFromView(containerView);

    String filePath = Environment.getExternalStorageDirectory() + File.separator +"image_with_text.jpg";

    try{

      bm.compress(Bitmap.CompressFormat.JPEG,100,newFileOutputStream(filePath));

      Toast.makeText(this,"图片已保存至:SD卡根目录/image_with_text.jpg", Toast.LENGTH_LONG).show();

    }catch(FileNotFoundException e) {

      e.printStackTrace();

    }

  }

  //以图片形式获取View显示的内容(类似于截图)

  publicstaticBitmap loadBitmapFromView(View view) {

    Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);

    Canvas canvas =newCanvas(bitmap);

    view.draw(canvas);

    returnbitmap;

  }

  privateintcount =0;

  //tvInImage的x方向和y方向移动量

  privatefloatmDx, mDy;

  //移动

  privateclassSimpleGestureListenerImplextendsGestureDetector.SimpleOnGestureListener {

    @Override

    publicbooleanonScroll(MotionEvent e1, MotionEvent e2,floatdistanceX,floatdistanceY) {

      //向右移动时,distanceX为负;向左移动时,distanceX为正

      //向下移动时,distanceY为负;向上移动时,distanceY为正

      count++;

      mDx -= distanceX;

      mDy -= distanceY;

      //边界检查

      mDx = calPosition(imagePositionX - tvInImage.getX(), imagePositionX + imageWidth - (tvInImage.getX() + tvInImage.getWidth()), mDx);

      mDy = calPosition(imagePositionY - tvInImage.getY(), imagePositionY + imageHeight - (tvInImage.getY() + tvInImage.getHeight()), mDy);

      //控制刷新频率

      if(count %5==0) {

        tvInImage.setX(tvInImage.getX() + mDx);

        tvInImage.setY(tvInImage.getY() + mDy);

      }

      returntrue;

    }

  }

  //计算正确的显示位置(不能超出边界)

  privatefloatcalPosition(floatmin,floatmax,floatcurrent) {

    if(current < min) {

      returnmin;

    }

    if(current > max) {

      returnmax;

    }

    returncurrent;

  }

  //获取压缩后的bitmap

  privateBitmap getScaledBitmap(intresId) {

    BitmapFactory.Options opt =newBitmapFactory.Options();

    opt.inJustDecodeBounds =true;

    BitmapFactory.decodeResource(getResources(), resId, opt);

    opt.inSampleSize = Utility.calculateInSampleSize(opt,600,800);

    opt.inJustDecodeBounds =false;

    returnBitmapFactory.decodeResource(getResources(), resId, opt);

  }

}

一个工具类:

 代码如下复制代码

publicclassUtility {

  //计算 inSampleSize 值,压缩图片

  publicstaticintcalculateInSampleSize(BitmapFactory.Options options,intreqWidth,intreqHeight) {

    // Raw height and width of image

    finalintheight = options.outHeight;

    finalintwidth = options.outWidth;

    intinSampleSize =1;

    if(height > reqHeight || width > reqWidth) {

      finalinthalfHeight = height /2;

      finalinthalfWidth = width /2;

      // Calculate the largest inSampleSize value that is a power of 2 and keeps both

      // height and width larger than the requested height and width.

      while((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {

        inSampleSize *=2;

      }

    }

    returninSampleSize;

  }

}

布局文件:

 代码如下复制代码

<LinearLayoutxmlns:android=""

  android:layout_width="match_parent"

  android:layout_height="match_parent"

  android:orientation="vertical"

  android:padding="10dp">

  <RelativeLayout

    android:id="@+id/writeText_img_rl"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_gravity="center_horizontal">

    <ImageView

      android:id="@+id/writeText_img"

      android:layout_width="wrap_content"

      android:layout_height="wrap_content"

      android:maxHeight="360dp"

      android:adjustViewBounds="true"

      android:contentDescription="@null"/>

    <TextView

      android:id="@+id/writeText_image_tv"

      android:layout_width="wrap_content"

      android:layout_height="wrap_content"

      android:visibility="invisible"

      android:layout_centerInParent="true"

      android:background="#79652a"

      android:clickable="true"

      android:padding="4dp"

      android:textColor="@android:color/white"

      android:textSize="15sp"/>

  

  <EditText

    android:id="@+id/writeText_et"

    android:layout_width="match_parent"

    android:layout_height="wrap_content"

    android:layout_marginTop="8dp"

    android:hint="添加备注"/>

  <Button

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:onClick="confirm"

    android:text="生成图片"/>

没有了

小编推荐的这篇文章介绍了Android基础之startActivityForResult()的用法详解,对初学android的同学来说非常有用,有需要的同学可以参考一下。

安卓开发中一个很基础的操作就是打开一个 Activity ,另一个很必要的操作就是,打开一个 Activity ,在打开的 Activity 中操作之后并获得返回结果。

两个 Activity

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • Android倾斜、描边、自定义字体的TextView

    Android倾斜、描边、自定义字体的TextView

    2017-02-26 11:03

  • Android中圆角矩形和圆形的多种实现方式

    Android中圆角矩形和圆形的多种实现方式

    2017-02-24 12:03

  • 【自定义控件系列一】android画图类---Canvas浅谈

    【自定义控件系列一】android画图类---Canvas浅谈

    2017-02-24 09:55

  • 搭建qt for android环境

    搭建qt for android环境

    2017-02-22 12:04

网友点评