利用安卓原生方式实现图片裁剪功能

原文地址:http://blog.csdn.net/djun100/article/details/9302227

一:主布局界面


二:点击控件触发事件后效果图


三:拍照完之后效果图


四:裁剪界面效果图


五:点击相册后返回的图片效果图


六:裁剪完从相册PICK的保存后的效果图 


下面直接来看下主控制类代码,如下:

  1. package com.example.photocapture;  
  2.   
  3. //下面来看下裁剪中用到的类,大家详细看下头注释:  
  4. /**   
  5.  * 下面这些注释是下载这个类的时候本来就有的,本来要删除的,但看了下竟然是license,吼吼,   
  6.  * 好东西,留在注释里,以备不时之用,大家有需要加license的可以到下面的网址找哦   
  7.  */  
  8.   
  9. //EPL, Eclipse Public License, V1.0 or later, http://www.eclipse.org/legal    
  10. //LGPL, GNU Lesser General Public License, V2.1 or later, http://www.gnu.org/licenses/lgpl.html    
  11. //GPL, GNU General Public License, V2 or later, http://www.gnu.org/licenses/gpl.html    
  12. //AL, Apache License, V2.0 or later, http://www.apache.org/licenses    
  13. //BSD, BSD License, http://www.opensource.org/licenses/bsd-license.php    
  14. /**   
  15.  * A Base64 encoder/decoder.   
  16.  *   
  17.  * <p>   
  18.  * This class is used to encode and decode data in Base64 format as described in RFC 1521.   
  19.  *   
  20.  * <p>   
  21.  * Project home page: <a href="http://www.source-code.biz/base64coder/java/">www.source-code.biz/base64coder/java</a><br>   
  22.  * Author: Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland<br>   
  23.  * Multi-licensed: EPL / LGPL / GPL / AL / BSD.   
  24.  */  
  25.   
  26. /** 
  27.  * 这个类在上面注释的网址中有,大家可以自行下载下,也可以直接用这个, 公开的Base64Coder类(不用深究它是怎么实现的, 
  28.  * 还是那句话,有轮子直接用轮子),好用的要死人了... 小马也很无耻的引用了这个网址下的东东,吼吼... 
  29.  *  
  30.  * @Title: Base64Coder.java 
  31.  * @Package com.xiaoma.piccut.demo 
  32.  * @Description: TODO 
  33.  * @author XiaoMa 
  34.  */  
  35.   
  36. public class Base64Coder {  
  37.   
  38.     // The line separator string of the operating system.  
  39.     private static final String systemLineSeparator = System  
  40.             .getProperty("line.separator");  
  41.   
  42.     // Mapping table from 6-bit nibbles to Base64 characters.  
  43.     private static char[] map1 = new char[64];  
  44.     static {  
  45.         int i = 0;  
  46.         for (char c = 'A'; c <= 'Z'; c++)  
  47.             map1[i++] = c;  
  48.         for (char c = 'a'; c <= 'z'; c++)  
  49.             map1[i++] = c;  
  50.         for (char c = '0'; c <= '9'; c++)  
  51.             map1[i++] = c;  
  52.         map1[i++] = '+';  
  53.         map1[i++] = '/';  
  54.     }  
  55.   
  56.     // Mapping table from Base64 characters to 6-bit nibbles.  
  57.     private static byte[] map2 = new byte[128];  
  58.     static {  
  59.         for (int i = 0; i < map2.length; i++)  
  60.             map2[i] = -1;  
  61.         for (int i = 0; i < 64; i++)  
  62.             map2[map1[i]] = (byte) i;  
  63.     }  
  64.   
  65.     /** 
  66.      * Encodes a string into Base64 format. No blanks or line breaks are 
  67.      * inserted. 
  68.      *  
  69.      * @param s 
  70.      *            A String to be encoded. 
  71.      * @return A String containing the Base64 encoded data. 
  72.      */  
  73.     public static String encodeString(String s) {  
  74.         return new String(encode(s.getBytes()));  
  75.     }  
  76.   
  77.     /** 
  78.      * Encodes a byte array into Base 64 format and breaks the output into lines 
  79.      * of 76 characters. This method is compatible with 
  80.      * <code>sun.misc.BASE64Encoder.encodeBuffer(byte[])</code>. 
  81.      *  
  82.      * @param in 
  83.      *            An array containing the data bytes to be encoded. 
  84.      * @return A String containing the Base64 encoded data, broken into lines. 
  85.      */  
  86.     public static String encodeLines(byte[] in) {  
  87.         return encodeLines(in, 0, in.length, 76, systemLineSeparator);  
  88.     }  
  89.   
  90.     /** 
  91.      * Encodes a byte array into Base 64 format and breaks the output into 
  92.      * lines. 
  93.      *  
  94.      * @param in 
  95.      *            An array containing the data bytes to be encoded. 
  96.      * @param iOff 
  97.      *            Offset of the first byte in <code>in</code> to be processed. 
  98.      * @param iLen 
  99.      *            Number of bytes to be processed in <code>in</code>, starting 
  100.      *            at <code>iOff</code>. 
  101.      * @param lineLen 
  102.      *            Line length for the output data. Should be a multiple of 4. 
  103.      * @param lineSeparator 
  104.      *            The line separator to be used to separate the output lines. 
  105.      * @return A String containing the Base64 encoded data, broken into lines. 
  106.      */  
  107.     public static String encodeLines(byte[] in, int iOff, int iLen,  
  108.             int lineLen, String lineSeparator) {  
  109.         int blockLen = (lineLen * 3) / 4;  
  110.         if (blockLen <= 0)  
  111.             throw new IllegalArgumentException();  
  112.         int lines = (iLen + blockLen - 1) / blockLen;  
  113.         int bufLen = ((iLen + 2) / 3) * 4 + lines * lineSeparator.length();  
  114.         StringBuilder buf = new StringBuilder(bufLen);  
  115.         int ip = 0;  
  116.         while (ip < iLen) {  
  117.             int l = Math.min(iLen - ip, blockLen);  
  118.             buf.append(encode(in, iOff + ip, l));  
  119.             buf.append(lineSeparator);  
  120.             ip += l;  
  121.         }  
  122.         return buf.toString();  
  123.     }  
  124.   
  125.     /** 
  126.      * Encodes a byte array into Base64 format. No blanks or line breaks are 
  127.      * inserted in the output. 
  128.      *  
  129.      * @param in 
  130.      *            An array containing the data bytes to be encoded. 
  131.      * @return A character array containing the Base64 encoded data. 
  132.      */  
  133.     public static char[] encode(byte[] in) {  
  134.         return encode(in, 0, in.length);  
  135.     }  
  136.   
  137.     /** 
  138.      * Encodes a byte array into Base64 format. No blanks or line breaks are 
  139.      * inserted in the output. 
  140.      *  
  141.      * @param in 
  142.      *            An array containing the data bytes to be encoded. 
  143.      * @param iLen 
  144.      *            Number of bytes to process in <code>in</code>. 
  145.      * @return A character array containing the Base64 encoded data. 
  146.      */  
  147.     public static char[] encode(byte[] in, int iLen) {  
  148.         return encode(in, 0, iLen);  
  149.     }  
  150.   
  151.     /** 
  152.      * Encodes a byte array into Base64 format. No blanks or line breaks are 
  153.      * inserted in the output. 
  154.      *  
  155.      * @param in 
  156.      *            An array containing the data bytes to be encoded. 
  157.      * @param iOff 
  158.      *            Offset of the first byte in <code>in</code> to be processed. 
  159.      * @param iLen 
  160.      *            Number of bytes to process in <code>in</code>, starting at 
  161.      *            <code>iOff</code>. 
  162.      * @return A character array containing the Base64 encoded data. 
  163.      */  
  164.     public static char[] encode(byte[] in, int iOff, int iLen) {  
  165.         int oDataLen = (iLen * 4 + 2) / 3// output length without padding  
  166.         int oLen = ((iLen + 2) / 3) * 4// output length including padding  
  167.         char[] out = new char[oLen];  
  168.         int ip = iOff;  
  169.         int iEnd = iOff + iLen;  
  170.         int op = 0;  
  171.         while (ip < iEnd) {  
  172.             int i0 = in[ip++] & 0xff;  
  173.             int i1 = ip < iEnd ? in[ip++] & 0xff : 0;  
  174.             int i2 = ip < iEnd ? in[ip++] & 0xff : 0;  
  175.             int o0 = i0 >>> 2;  
  176.             int o1 = ((i0 & 3) << 4) | (i1 >>> 4);  
  177.             int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);  
  178.             int o3 = i2 & 0x3F;  
  179.             out[op++] = map1[o0];  
  180.             out[op++] = map1[o1];  
  181.             out[op] = op < oDataLen ? map1[o2] : '=';  
  182.             op++;  
  183.             out[op] = op < oDataLen ? map1[o3] : '=';  
  184.             op++;  
  185.         }  
  186.         return out;  
  187.     }  
  188.   
  189.     /** 
  190.      * Decodes a string from Base64 format. No blanks or line breaks are allowed 
  191.      * within the Base64 encoded input data. 
  192.      *  
  193.      * @param s 
  194.      *            A Base64 String to be decoded. 
  195.      * @return A String containing the decoded data. 
  196.      * @throws IllegalArgumentException 
  197.      *             If the input is not valid Base64 encoded data. 
  198.      */  
  199.     public static String decodeString(String s) {  
  200.         return new String(decode(s));  
  201.     }  
  202.   
  203.     /** 
  204.      * Decodes a byte array from Base64 format and ignores line separators, tabs 
  205.      * and blanks. CR, LF, Tab and Space characters are ignored in the input 
  206.      * data. This method is compatible with 
  207.      * <code>sun.misc.BASE64Decoder.decodeBuffer(String)</code>. 
  208.      *  
  209.      * @param s 
  210.      *            A Base64 String to be decoded. 
  211.      * @return An array containing the decoded data bytes. 
  212.      * @throws IllegalArgumentException 
  213.      *             If the input is not valid Base64 encoded data. 
  214.      */  
  215.     public static byte[] decodeLines(String s) {  
  216.         char[] buf = new char[s.length() + 3];  
  217.         int p = 0;  
  218.         for (int ip = 0; ip < s.length(); ip++) {  
  219.             char c = s.charAt(ip);  
  220.             if (c != ' ' && c != '\r' && c != '\n' && c != '\t')  
  221.                 buf[p++] = c;  
  222.         }  
  223.         while ((p % 4) != 0)  
  224.             buf[p++] = '0';  
  225.   
  226.         return decode(buf, 0, p);  
  227.     }  
  228.   
  229.     /** 
  230.      * Decodes a byte array from Base64 format. No blanks or line breaks are 
  231.      * allowed within the Base64 encoded input data. 
  232.      *  
  233.      * @param s 
  234.      *            A Base64 String to be decoded. 
  235.      * @return An array containing the decoded data bytes. 
  236.      * @throws IllegalArgumentException 
  237.      *             If the input is not valid Base64 encoded data. 
  238.      */  
  239.     public static byte[] decode(String s) {  
  240.         return decode(s.toCharArray());  
  241.     }  
  242.   
  243.     /** 
  244.      * Decodes a byte array from Base64 format. No blanks or line breaks are 
  245.      * allowed within the Base64 encoded input data. 
  246.      *  
  247.      * @param in 
  248.      *            A character array containing the Base64 encoded data. 
  249.      * @return An array containing the decoded data bytes. 
  250.      * @throws IllegalArgumentException 
  251.      *             If the input is not valid Base64 encoded data. 
  252.      */  
  253.     public static byte[] decode(char[] in) {  
  254.         return decode(in, 0, in.length);  
  255.     }  
  256.   
  257.     /** 
  258.      * Decodes a byte array from Base64 format. No blanks or line breaks are 
  259.      * allowed within the Base64 encoded input data. 
  260.      *  
  261.      * @param in 
  262.      *            A character array containing the Base64 encoded data. 
  263.      * @param iOff 
  264.      *            Offset of the first character in <code>in</code> to be 
  265.      *            processed. 
  266.      * @param iLen 
  267.      *            Number of characters to process in <code>in</code>, starting 
  268.      *            at <code>iOff</code>. 
  269.      * @return An array containing the decoded data bytes. 
  270.      * @throws IllegalArgumentException 
  271.      *             If the input is not valid Base64 encoded data. 
  272.      */  
  273.     public static byte[] decode(char[] in, int iOff, int iLen) {  
  274.         if (iLen % 4 != 0)  
  275.             throw new IllegalArgumentException(  
  276.                     "Length of Base64 encoded input string is not a multiple of 4.");  
  277.         while (iLen > 0 && in[iOff + iLen - 1] == '=')  
  278.             iLen--;  
  279.         int oLen = (iLen * 3) / 4;  
  280.         byte[] out = new byte[oLen];  
  281.         int ip = iOff;  
  282.         int iEnd = iOff + iLen;  
  283.         int op = 0;  
  284.         while (ip < iEnd) {  
  285.             int i0 = in[ip++];  
  286.             int i1 = in[ip++];  
  287.             int i2 = ip < iEnd ? in[ip++] : 'A';  
  288.             int i3 = ip < iEnd ? in[ip++] : 'A';  
  289.             if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)  
  290.                 throw new IllegalArgumentException(  
  291.                         "Illegal character in Base64 encoded data.");  
  292.             int b0 = map2[i0];  
  293.             int b1 = map2[i1];  
  294.             int b2 = map2[i2];  
  295.             int b3 = map2[i3];  
  296.             if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)  
  297.                 throw new IllegalArgumentException(  
  298.                         "Illegal character in Base64 encoded data.");  
  299.             int o0 = (b0 << 2) | (b1 >>> 4);  
  300.             int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2);  
  301.             int o2 = ((b2 & 3) << 6) | b3;  
  302.             out[op++] = (byte) o0;  
  303.             if (op < oLen)  
  304.                 out[op++] = (byte) o1;  
  305.             if (op < oLen)  
  306.                 out[op++] = (byte) o2;  
  307.         }  
  308.         return out;  
  309.     }  
  310.   
  311.     // Dummy constructor.  
  312.     private Base64Coder() {  
  313.     }  
  314.   
  315. // end class Base64Coder  

  1. package com.example.photocapture;    
  2.    
  3. import java.io.File;    
  4. import android.app.Activity;    
  5. import android.app.AlertDialog;    
  6. import android.content.DialogInterface;    
  7. import android.content.Intent;    
  8. import android.graphics.Bitmap;    
  9. import android.graphics.drawable.BitmapDrawable;    
  10. import android.graphics.drawable.Drawable;    
  11. import android.net.Uri;    
  12. import android.os.Bundle;    
  13. import android.os.Environment;    
  14. import android.provider.MediaStore;    
  15. import android.view.View;    
  16. import android.view.View.OnClickListener;    
  17. import android.widget.Button;    
  18. import android.widget.ImageButton;    
  19. import android.widget.ImageView;    
  20. /**   
  21.  * @Title: PicCutDemoActivity.java   
  22.  * @Package com.xiaoma.piccut.demo   
  23.  * @Description: 图片裁剪功能测试   
  24.  * @author XiaoMa   
  25.  */   
  26. public class MainActivity extends Activity implements OnClickListener {    
  27.    
  28.     private ImageButton ib = null;    
  29.     private ImageView iv = null;    
  30.     private Button btn = null;    
  31.     private String tp = null;    
  32.         
  33.    
  34.     /** Called when the activity is first created. */   
  35.     @Override   
  36.     public void onCreate(Bundle savedInstanceState) {    
  37.         super.onCreate(savedInstanceState);    
  38.         setContentView(R.layout.activity_main);    
  39.         //初始化    
  40.         init();    
  41.     }    
  42.         
  43.     /**   
  44.      * 初始化方法实现   
  45.      */   
  46.     private void init() {    
  47.         ib = (ImageButton) findViewById(R.id.imageButton1);    
  48.         iv = (ImageView) findViewById(R.id.imageView1);    
  49.         btn = (Button) findViewById(R.id.button1);    
  50.         ib.setOnClickListener(this);    
  51.         iv.setOnClickListener(this);    
  52.         btn.setOnClickListener(this);    
  53.     }    
  54.    
  55.         
  56.     /**   
  57.      * 控件点击事件实现   
  58.      *    
  59.      * 因为有朋友问不同控件的背景图裁剪怎么实现,   
  60.      * 我就在这个地方用了三个控件,只为了自己记录学习   
  61.      * 大家觉得没用的可以跳过啦   
  62.      */   
  63.     @Override   
  64.     public void onClick(View v) {    
  65.         switch (v.getId()) {    
  66.         case R.id.imageButton1:    
  67.             ShowPickDialog();    
  68.             break;    
  69.         case R.id.imageView1:    
  70.             ShowPickDialog();    
  71.             break;    
  72.         case R.id.button1:    
  73.             ShowPickDialog();    
  74.             break;    
  75.    
  76.         default:    
  77.             break;    
  78.         }    
  79.     }    
  80.    
  81.     /**   
  82.      * 选择提示对话框   
  83.      */   
  84.     private void ShowPickDialog() {    
  85.         new AlertDialog.Builder(this)    
  86.                 .setTitle("设置头像...")    
  87.                 .setNegativeButton("相册"new DialogInterface.OnClickListener() {    
  88.                     public void onClick(DialogInterface dialog, int which) {    
  89.                         dialog.dismiss();    
  90.                         /**   
  91.                          * 刚开始,我自己也不知道ACTION_PICK是干嘛的,后来直接看Intent源码,   
  92.                          * 可以发现里面很多东西,Intent是个很强大的东西,大家一定仔细阅读下   
  93.                          */   
  94.                         Intent intent = new Intent(Intent.ACTION_PICK, null);    
  95.                             
  96.                         /**   
  97.                          * 下面这句话,与其它方式写是一样的效果,如果:   
  98.                          * intent.setData(MediaStore.Images.Media.EXTERNAL_CONTENT_URI);   
  99.                          * intent.setType(""image/*");设置数据类型   
  100.                          * 如果朋友们要限制上传到服务器的图片类型时可以直接写如:"image/jpeg 、 image/png等的类型"   
  101.                          * 这个地方小马有个疑问,希望高手解答下:就是这个数据URI与类型为什么要分两种形式来写呀?有什么区别?   
  102.                          */   
  103.                         intent.setDataAndType(    
  104.                                 MediaStore.Images.Media.EXTERNAL_CONTENT_URI,    
  105.                                 "image/*");    
  106.                         startActivityForResult(intent, 1);    
  107.    
  108.                     }    
  109.                 })    
  110.                 .setPositiveButton("拍照"new DialogInterface.OnClickListener() {    
  111.                     public void onClick(DialogInterface dialog, int whichButton) {    
  112.                         dialog.dismiss();    
  113.                         /**    
  114.                          * 下面这句还是老样子,调用快速拍照功能,至于为什么叫快速拍照,大家可以参考如下官方    
  115.                          * 文档,you_sdk_path/docs/guide/topics/media/camera.html    
  116.                          * 我刚看的时候因为太长就认真看,其实是错的,这个里面有用的太多了,所以大家不要认为    
  117.                          * 官方文档太长了就不看了,其实是错的,这个地方小马也错了,必须改正    
  118.                          */    
  119.                         Intent intent = new Intent(    
  120.                                 MediaStore.ACTION_IMAGE_CAPTURE);    
  121.                         //下面这句指定调用相机拍照后的照片存储的路径    
  122.                         intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri    
  123.                                 .fromFile(new File(Environment    
  124.                                         .getExternalStorageDirectory(),    
  125.                                         "xiaoma.jpg")));    
  126.                         startActivityForResult(intent, 2);    
  127.                     }    
  128.                 }).show();    
  129.     }    
  130.    
  131.     @Override   
  132.     protected void onActivityResult(int requestCode, int resultCode, Intent data) {    
  133.         switch (requestCode) {    
  134.         // 如果是直接从相册获取    
  135.         case 1:    
  136.             startPhotoZoom(data.getData());    
  137.             break;    
  138.         // 如果是调用相机拍照时    
  139.         case 2:    
  140.             File temp = new File(Environment.getExternalStorageDirectory()    
  141.                     + "/xiaoma.jpg");    
  142.             startPhotoZoom(Uri.fromFile(temp));    
  143.             break;    
  144.         // 取得裁剪后的图片    
  145.         case 3:    
  146.             /**   
  147.              * 非空判断大家一定要验证,如果不验证的话,   
  148.              * 在剪裁之后如果发现不满意,要重新裁剪,丢弃   
  149.              * 当前功能时,会报NullException,小马只   
  150.              * 在这个地方加下,大家可以根据不同情况在合适的   
  151.              * 地方做判断处理类似情况   
  152.              *    
  153.              */   
  154.             if(data != null){    
  155.                 setPicToView(data);    
  156.             }    
  157.             break;    
  158.         default:    
  159.             break;    
  160.    
  161.         }    
  162.         super.onActivityResult(requestCode, resultCode, data);    
  163.     }    
  164.         
  165.     /**   
  166.      * 裁剪图片方法实现   
  167.      * @param uri   
  168.      */   
  169.     public void startPhotoZoom(Uri uri) {    
  170.         /*   
  171.          * 至于下面这个Intent的ACTION是怎么知道的,大家可以看下自己路径下的如下网页   
  172.          * yourself_sdk_path/docs/reference/android/content/Intent.html   
  173.          * 直接在里面Ctrl+F搜:CROP ,之前小马没仔细看过,其实安卓系统早已经有自带图片裁剪功能,   
  174.          * 是直接调本地库的,小马不懂C C++  这个不做详细了解去了,有轮子就用轮子,不再研究轮子是怎么   
  175.          * 制做的了...吼吼   
  176.          */   
  177.         Intent intent = new Intent("com.android.camera.action.CROP");    
  178.         intent.setDataAndType(uri, "image/*");    
  179.         //下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪    
  180.         intent.putExtra("crop""true");    
  181.         // aspectX aspectY 是宽高的比例    
  182.         intent.putExtra("aspectX"1);    
  183.         intent.putExtra("aspectY"1);    
  184.         // outputX outputY 是裁剪图片宽高    
  185.         intent.putExtra("outputX"150);    
  186.         intent.putExtra("outputY"150);    
  187.         intent.putExtra("return-data"true);    
  188.         startActivityForResult(intent, 3);    
  189.     }    
  190.         
  191.     /**    
  192.      * 保存裁剪之后的图片数据    
  193.      * @param picdata    
  194.      */    
  195.     private void setPicToView(Intent picdata) {    
  196.         Bundle extras = picdata.getExtras();    
  197.         if (extras != null) {    
  198.             Bitmap photo = extras.getParcelable("data");    
  199.             Drawable drawable = new BitmapDrawable(photo);    
  200.                 
  201.             /**   
  202.              * 下面注释的方法是将裁剪之后的图片以Base64Coder的字符方式上   
  203.              * 传到服务器,QQ头像上传采用的方法跟这个类似   
  204.              */   
  205.                 
  206.             /*ByteArrayOutputStream stream = new ByteArrayOutputStream();   
  207.             photo.compress(Bitmap.CompressFormat.JPEG, 60, stream);   
  208.             byte[] b = stream.toByteArray();   
  209.             // 将图片流以字符串形式存储下来   
  210.                
  211.             tp = new String(Base64Coder.encodeLines(b));   
  212.             这个地方大家可以写下给服务器上传图片的实现,直接把tp直接上传就可以了,   
  213.             服务器处理的方法是服务器那边的事了,吼吼   
  214.                
  215.             如果下载到的服务器的数据还是以Base64Coder的形式的话,可以用以下方式转换   
  216.             为我们可以用的图片类型就OK啦...吼吼   
  217.             Bitmap dBitmap = BitmapFactory.decodeFile(tp);   
  218.             Drawable drawable = new BitmapDrawable(dBitmap);   
  219.             */   
  220.             ib.setBackgroundDrawable(drawable);    
  221.             iv.setBackgroundDrawable(drawable);    
  222.         }    
  223.     }    
  224.    
  225. }   

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:paddingBottom="@dimen/activity_vertical_margin"  
  6.     android:paddingLeft="@dimen/activity_horizontal_margin"  
  7.     android:paddingRight="@dimen/activity_horizontal_margin"  
  8.     android:paddingTop="@dimen/activity_vertical_margin"  
  9.     tools:context=".MainActivity" >  
  10.   
  11.     <TextView  
  12.         android:id="@+id/textView1"  
  13.         android:layout_width="wrap_content"  
  14.         android:layout_height="wrap_content"  
  15.         android:text="@string/hello_world" />  
  16.   
  17.     <Button  
  18.         android:id="@+id/button1"  
  19.         style="?android:attr/buttonStyleSmall"  
  20.         android:layout_width="wrap_content"  
  21.         android:layout_height="wrap_content"  
  22.         android:layout_alignLeft="@+id/textView1"  
  23.         android:layout_alignParentBottom="true"  
  24.         android:layout_marginBottom="42dp"  
  25.         android:text="Button" />  
  26.   
  27.     <ImageView  
  28.         android:id="@+id/imageView1"  
  29.         android:layout_width="wrap_content"  
  30.         android:layout_height="wrap_content"  
  31.         android:layout_below="@+id/textView1"  
  32.         android:layout_centerHorizontal="true"  
  33.         android:layout_marginTop="68dp"  
  34.         android:src="@drawable/ic_launcher" />  
  35.   
  36.     <ImageButton  
  37.         android:id="@+id/imageButton1"  
  38.         android:layout_width="wrap_content"  
  39.         android:layout_height="wrap_content"  
  40.         android:layout_alignTop="@+id/button1"  
  41.         android:layout_toRightOf="@+id/imageView1"  
  42.         android:src="@drawable/ic_launcher" />  
  43.   
  44. </RelativeLayout>  

Base64算法大家可以参考我转载的另一篇文章,其作用有详细解释。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值