欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2024-02-11 21:00:46
本文实例讲述了android编程实现支持拖动改变位置的图片中叠加文字功能。分享给大家供大家参考,具体如下: 之所以做了这么一个demo,是因为最近项目中有一个奇葩的需求:...

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

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

首先上demo效果图:

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

功能:

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

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

activity:

/**
 * 将文字写在图片中(截图方式),支持拖动文字。<br/>
 * 说明:很明显,截图方式会降低图片的质量。如果需要保持图片质量可以使用canvas的方式,将文字直接绘制在图片之上(不过,使用此方式要实现文字拖动较为复杂)。
 */
public class mainactivity extends appcompatactivity {
  //图片组件
  private imageview imageview;
  //位于图片中的文本组件
  private textview tvinimage;
  //图片和文本的父组件
  private view containerview;
  //父组件的尺寸
  private float imagewidth, imageheight, imagepositionx, imagepositiony;
  @override
  protected void oncreate(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(new viewtreeobserver.ongloballayoutlistener() {
      @override
      public void ongloballayout() {
        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(new textwatcher() {
      @override
      public void beforetextchanged(charsequence s, int start, int count, int after) {
      }
      @override
      public void ontextchanged(charsequence s, int start, int before, int count) {
        if (s.tostring().equals("")) {
          tvinimage.setvisibility(view.invisible);
        } else {
          tvinimage.setvisibility(view.visible);
          tvinimage.settext(s);
        }
      }
      @override
      public void aftertextchanged(editable s) {
      }
    });
    final gesturedetector gesturedetector = new gesturedetector(this, new simplegesturelistenerimpl());
    //移动
    tvinimage.setontouchlistener(new view.ontouchlistener() {
      @override
      public boolean ontouch(view v, motionevent event) {
        gesturedetector.ontouchevent(event);
        return true;
      }
    });
  }
  //确认,生成图片
  public void confirm(view view) {
    bitmap bm = loadbitmapfromview(containerview);
    string filepath = environment.getexternalstoragedirectory() + file.separator + "image_with_text.jpg";
    try {
      bm.compress(bitmap.compressformat.jpeg, 100, new fileoutputstream(filepath));
      toast.maketext(this, "图片已保存至:sd卡根目录/image_with_text.jpg", toast.length_long).show();
    } catch (filenotfoundexception e) {
      e.printstacktrace();
    }
  }
  //以图片形式获取view显示的内容(类似于截图)
  public static bitmap loadbitmapfromview(view view) {
    bitmap bitmap = bitmap.createbitmap(view.getwidth(), view.getheight(), bitmap.config.argb_8888);
    canvas canvas = new canvas(bitmap);
    view.draw(canvas);
    return bitmap;
  }
  private int count = 0;
  //tvinimage的x方向和y方向移动量
  private float mdx, mdy;
  //移动
  private class simplegesturelistenerimpl extends gesturedetector.simpleongesturelistener {
    @override
    public boolean onscroll(motionevent e1, motionevent e2, float distancex, float distancey) {
      //向右移动时,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);
      }
      return true;
    }
  }
  //计算正确的显示位置(不能超出边界)
  private float calposition(float min, float max, float current) {
    if (current < min) {
      return min;
    }
    if (current > max) {
      return max;
    }
    return current;
  }
  //获取压缩后的bitmap
  private bitmap getscaledbitmap(int resid) {
    bitmapfactory.options opt = new bitmapfactory.options();
    opt.injustdecodebounds = true;
    bitmapfactory.decoderesource(getresources(), resid, opt);
    opt.insamplesize = utility.calculateinsamplesize(opt, 600, 800);
    opt.injustdecodebounds = false;
    return bitmapfactory.decoderesource(getresources(), resid, opt);
  }
}

一个工具类:

public class utility {
  //计算 insamplesize 值,压缩图片
  public static int calculateinsamplesize(bitmapfactory.options options, int reqwidth, int reqheight) {
    // raw height and width of image
    final int height = options.outheight;
    final int width = options.outwidth;
    int insamplesize = 1;
    if (height > reqheight || width > reqwidth) {
      final int halfheight = height / 2;
      final int halfwidth = 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;
      }
    }
    return insamplesize;
  }
}

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/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" />
  </relativelayout>
  <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="生成图片" />
</linearlayout>

更多关于android相关内容感兴趣的读者可查看本站专题:《android图形与图像处理技巧总结》、《android开发入门与进阶教程》、《android调试技巧与常见问题解决方法汇总》、《android基本组件用法总结》、《android视图view技巧总结》、《android布局layout技巧总结》及《android控件用法总结

希望本文所述对大家android程序设计有所帮助。