仿微信图片选择器
来源:互联网 发布:软件工程硕士排名 编辑:程序博客网 时间:2024/04/27 16:01
仿微信图片选择器
源码下载连接:
先上图,后上代码:
打开app后点击添加图片按钮:
获取选择的图片 并返回在gridview中:
实现该功能的重要组成部分有:利用gridview加载本地图片,gridView控件的使用,Intent之间数据的传递,和利用ContentProvider获取图片,和PopupWindow弹出页面的使用,利用Bitmap解决OOM问题。
下面开始贴出代码:
MainActivity文件的代码如下:
`import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.SimpleAdapter;
import android.widget.SimpleAdapter.ViewBinder;
import android.widget.Toast;
public class MainActivity extends Activity {
private ImageButton imageButton_poprecommend_back;private Button button_poprecommend_fabu;private EditText editText_poprecommend;private ImageButton imageButton_poprecommend_tianjia;private GridView gridView_poprecommend;private PopRecommend_ImageAdd_Adapter imageAdapter;private ArrayList<String> shuju = new ArrayList<String>();public static MainActivity activity;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); activity = this; FindId(); Dianji(); shuju = new ArrayList<String>(); Intent intent = this.getIntent(); shuju = intent.getStringArrayListExtra("shuju"); if (shuju != null) { imageAdapter = new PopRecommend_ImageAdd_Adapter(this, shuju); gridView_poprecommend.setAdapter(imageAdapter); }}private void FindId() { imageButton_poprecommend_back = (ImageButton) findViewById(R.id.imagview_poprecommend_back); button_poprecommend_fabu = (Button) findViewById(R.id.button_poprecommend_fabu); editText_poprecommend = (EditText) findViewById(R.id.edittext_poprecommend); imageButton_poprecommend_tianjia = (ImageButton) findViewById(R.id.iamgebutton_poprecommend_tianjiatupian); gridView_poprecommend = (GridView)this.findViewById(R.id.gridview_poprecommend);}private void Dianji() { imageButton_poprecommend_back.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (Activity_Image_Add.imageAdd!=null) Activity_Image_Add.imageAdd.finish(); } }); button_poprecommend_fabu.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (Activity_Image_Add.imageAdd!=null) Activity_Image_Add.imageAdd.finish(); if (editText_poprecommend.getText().toString().equals("")) { Toast.makeText(getApplication(), "发布内容不能为空", Toast.LENGTH_SHORT).show(); } else Toast.makeText(getApplication(), "发布成功", Toast.LENGTH_SHORT).show(); } }); imageButton_poprecommend_tianjia.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(getApplication(), Activity_Image_Add.class); startActivity(intent); } });}
}
`
Activity_Image_Add activity的页面代码:
package com.xiyouliwp.fangweixin;import java.io.File;import java.io.FilenameFilter;import java.util.ArrayList;import java.util.Arrays;import java.util.HashSet;import java.util.LinkedList;import java.util.List;import android.app.Activity;import android.app.ProgressDialog;import android.content.ContentResolver;import android.content.Context;import android.content.Intent;import android.database.Cursor;import android.graphics.Color;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.provider.MediaStore;import android.util.DisplayMetrics;import android.util.Log;import android.view.Gravity;import android.view.KeyEvent;import android.view.LayoutInflater;import android.view.View;import android.view.Window;import android.view.WindowManager;import android.widget.GridView;import android.widget.ImageButton;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.PopupWindow;import android.widget.RelativeLayout;import android.widget.TextView;import android.widget.Toast;/** * 需求:IPet的图片选择器, * Created by lwp940118 on 2016/5/29. * 李文朋 */public class Activity_Image_Add extends Activity implements List_File_PopWind.OnImageDirSelected { private ImageButton imageButton_ImageAdd_back; private ImageButton imageButton_ImageAdd_finish; private GridView gridView_ImageAdd; int totalCount = 0; /** * 存储文件夹中的图片数量 */ private int mPicSize = 0; /** * 图片数量最多的文件夹 */ private File maxImageFile; private RelativeLayout relativeLayout_popwind; /** * 所以图片 */ private List<String> mImags; /** * list存放扫描到的文件夹的信息 */ private List<ImageFolder> imageFolders = new ArrayList<ImageFolder>(); /** * hashset 基于hashmap实现的,利用他可以防止一个文件夹 多次扫描 */ private HashSet<String> mImagePath = new HashSet<String>(); //弹出对话框 进度条 private ProgressDialog mprogressDialog; private TextView textview_ChooseDir; private TextView textview_ImageCount; //定义屏幕的高度 private int screenHeight = 0; /** * 用户选择的图片,存储为图片的完整路径 */ public static List<String> mSelectedImage = new LinkedList<String>(); private ArrayList<String> shuju; private MyAdapter myAdapter; private List_File_PopWind popWind; public static Activity_Image_Add imageAdd; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { //加载的那个对话框 销毁 mprogressDialog.dismiss(); //view绑定数据 dateView(); //初始化Popwind initPopWind(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_image_add); DisplayMetrics displayMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); screenHeight = displayMetrics.heightPixels; Log.e("screenHeight---->", "" + screenHeight); imageAdd = this; findId(); kongJianSheZhi(); getImages(); initEvent(); } // 返回按键调用 public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { if (MainActivity.activity!=null) MainActivity.activity.finish(); shuju = new ArrayList<String>(); for (int i = 0; i < mSelectedImage.size(); i++) shuju.add(mSelectedImage.get(i)); Intent intent = new Intent(getApplicationContext(),MainActivity.class); intent.putStringArrayListExtra("shuju",shuju); startActivity(intent); } return true; } /** * 弹出popwind */ private void initEvent() { relativeLayout_popwind.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { popWind.setAnimationStyle(R.style.AnimBottom); popWind.showAtLocation(Activity_Image_Add.this.findViewById(R.id.imagebutton_imageadd_back), Gravity.BOTTOM, 0, 0); // 设置背景颜色变暗 WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.alpha = 0.3f; getWindow().setAttributes(lp); } }); } /** * 绑定view的数据 */ private void dateView() { if (maxImageFile == null) { Toast.makeText(getApplicationContext(), "没有扫描到图片", Toast.LENGTH_SHORT).show(); return; } //aslist 连接列表与数组,当一个更新时 另一个也自动更新但是没有add 和remove方法 mImags = Arrays.asList(maxImageFile.list()); myAdapter = new MyAdapter(getApplicationContext(), mImags, R.layout.item_gridview_imageadd, maxImageFile.getAbsolutePath()); gridView_ImageAdd.setAdapter(myAdapter); //显示多少张图片 在popwind中 textview_ImageCount.setText(totalCount + "张"); } /** * 初始化popwind的弹出界面 */ private void initPopWind() { popWind = new List_File_PopWind(LinearLayout.LayoutParams.MATCH_PARENT, (int) (screenHeight * 0.7), imageFolders, LayoutInflater.from(getApplicationContext()) .inflate(R.layout.list_dir, null)); popWind.setOnDismissListener(new PopupWindow.OnDismissListener() { @Override public void onDismiss() { // 设置背景颜色变暗 WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.alpha = 1.0f; getWindow().setAttributes(lp); } }); //设置文件夹的回调 popWind.setOnImageDirSelected(this); } /** * 利用contentProvider扫描手机中的图片,并获取jpn最多的那个文件夹 * ContentProvider 为Android四大组件,详情见我的博客 * Android四大组件介绍http://blog.csdn.net/qq_30000411/article/details/51355390 */ private void getImages() { //判断Sd卡的状态 是否可用 if (!Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { Toast.makeText(getApplicationContext(), "没有找到SD", Toast.LENGTH_SHORT).show(); } //显示进度条 加载中... mprogressDialog = ProgressDialog.show(this, null, "图片读取中..."); new Thread(new Runnable() { @Override public void run() { //读取第一张图片 String firstImagePath = null; //EXTERNAL_CONTENT_URI多选 Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; //ContentResolver应用之间数据共享 ContentResolver mResolver = Activity_Image_Add.this.getContentResolver(); //数据查找,找出JPEG和png格式的图片,,,MediaStore为Android手机系统的多媒体数据库 Cursor mCursor = mResolver.query(mImageUri, null, MediaStore.Images.Media.MIME_TYPE + "=? or " + MediaStore.Images.Media.MIME_TYPE + "=?", new String[]{"image/jpeg", "image/png"}, MediaStore.Images.Media.DATE_MODIFIED); //读取图片 while (mCursor.moveToNext()) { //定义图片的路径 String imagePath = mCursor.getString(mCursor.getColumnIndex (MediaStore.Images.Media.DATA)); //获取第一张图片的路径 if (firstImagePath == null) firstImagePath = imagePath; //获取该图片的父路径名 File parentFile = new File(imagePath).getParentFile(); if (parentFile == null) continue; String folderPath = parentFile.getAbsolutePath(); ImageFolder imageFolder = null; //利用hashset防止一个文件夹被多次扫描 if (mImagePath.contains(folderPath)) { continue; } else { mImagePath.add(folderPath); //初始化 ImageFolder imageFolder = new ImageFolder(); imageFolder.setFolderPath(folderPath); imageFolder.setFirstImagePath(imagePath); } int picSize = parentFile.list(new FilenameFilter() { @Override public boolean accept(File dir, String filename) { if (filename.endsWith(".png") || filename.endsWith(".jpg") || filename.endsWith(".jpeg")) return true; return false; } }).length; totalCount += picSize; imageFolder.setImageCount(picSize); imageFolders.add(imageFolder); //更新最大数量文件夹 if (picSize > mPicSize) { mPicSize = picSize; maxImageFile = parentFile; } } mCursor.close(); //扫描完成 hashset释放 mImagePath = null; //通知 线程Handler 图片扫秒完成 handler.sendEmptyMessage(0x110); } }).start(); } private void findId() { gridView_ImageAdd = (GridView) findViewById(R.id.gridview_imageadd); imageButton_ImageAdd_back = (ImageButton) findViewById(R.id.imagebutton_imageadd_back); imageButton_ImageAdd_finish = (ImageButton) findViewById(R.id.imagebutton_imageadd_finish); textview_ChooseDir = (TextView) findViewById(R.id.id_choose_dir); textview_ImageCount = (TextView) findViewById(R.id.id_total_count); relativeLayout_popwind = (RelativeLayout) findViewById(R.id.id_bottom_ly); } private void kongJianSheZhi() { imageButton_ImageAdd_finish.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.e("完成--->","完成"); if (MainActivity.activity!=null) MainActivity.activity.finish(); shuju = new ArrayList<String>(); for (int i = 0; i < mSelectedImage.size(); i++) shuju.add(mSelectedImage.get(i)); Intent intent = new Intent(getApplicationContext(),MainActivity.class); intent.putStringArrayListExtra("shuju",shuju); startActivity(intent); } }); imageButton_ImageAdd_back.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); } @Override public void selected(ImageFolder floder) { maxImageFile = new File(floder.getFolderPath()); mImags = Arrays.asList(maxImageFile.list(new FilenameFilter() { @Override public boolean accept(File dir, String filename) { if (filename.endsWith(".jpg") || filename.endsWith(".png") || filename.endsWith(".jpeg")) return true; return false; } })); /** * 可以看到文件夹的路径和图片的路径分开保存,极大的减少了内存的消耗; */ myAdapter = new MyAdapter(getApplicationContext(), mImags, R.layout.item_gridview_imageadd, maxImageFile.getAbsolutePath()); gridView_ImageAdd.setAdapter(myAdapter); // mAdapter.notifyDataSetChanged(); textview_ImageCount.setText(floder.getImageCount() + "张"); textview_ChooseDir.setText(floder.getFolderName()); popWind.dismiss(); } /** * gridview的定义适配器 */ public class MyAdapter extends CommonAdapter<String> { /** * 文件夹路径 */ private String mDirPath; public MyAdapter(Context context, List<String> mDatas, int itemLayoutId, String dirPath) { super(context, mDatas, itemLayoutId); this.mDirPath = dirPath; } @Override public void convert(final ViewHolder helper, final String item) { //设置no_pic helper.setImageResource(R.id.id_item_image, R.drawable.pictures_no); //设置no_selected helper.setImageResource(R.id.id_item_select, R.drawable.picture_unselected); //设置图片 helper.setImageByUrl(R.id.id_item_image, mDirPath + "/" + item); final ImageView mImageView = helper.getView(R.id.id_item_image); final ImageView mSelect = helper.getView(R.id.id_item_select); mImageView.setColorFilter(null); //设置ImageView的点击事件 mImageView.setOnClickListener(new View.OnClickListener() { //选择,则将图片变暗,反之则反之 @Override public void onClick(View v) { // 已经选择过该图片 if (mSelectedImage.contains(mDirPath + "/" + item)) { mSelectedImage.remove(mDirPath + "/" + item); mSelect.setImageResource(R.drawable.picture_unselected); mImageView.setColorFilter(null); } else {// 未选择该图片 mSelectedImage.add(mDirPath + "/" + item); mSelect.setImageResource(R.drawable.pictures_selected); mImageView.setColorFilter(Color.parseColor("#77000000")); } } }); /** * 已经选择过的图片,显示出选择过的效果 */ if (mSelectedImage.contains(mDirPath + "/" + item)) { mSelect.setImageResource(R.drawable.pictures_selected); mImageView.setColorFilter(Color.parseColor("#77000000")); } } }}
BitmapUtilities问价:用于缩小图片的尺寸,避免OOM问题出现
package com.xiyouliwp.fangweixin;/** * Created by lwp940118 on 2016/5/31. */import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Matrix;public class BitmapUtilities { public BitmapUtilities() { // TODO Auto-generated constructor stub } public static Bitmap getBitmapThumbnail(String path,int width,int height){ Bitmap bitmap = null; //这里可以按比例缩小图片: /*BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inSampleSize = 4;//宽和高都是原来的1/4 bitmap = BitmapFactory.decodeFile(path, opts); */ /*进一步的, 如何设置恰当的inSampleSize是解决该问题的关键之一。BitmapFactory.Options提供了另一个成员inJustDecodeBounds。 设置inJustDecodeBounds为true后,decodeFile并不分配空间,但可计算出原始图片的长度和宽度,即opts.width和opts.height。 有了这两个参数,再通过一定的算法,即可得到一个恰当的inSampleSize。*/ BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, opts); opts.inSampleSize = Math.max((int)(opts.outHeight / (float) height), (int)(opts.outWidth / (float) width)); opts.inJustDecodeBounds = false; bitmap = BitmapFactory.decodeFile(path, opts); return bitmap; } public static Bitmap getBitmapThumbnail(Bitmap bmp,int width,int height){ Bitmap bitmap = null; if(bmp != null ){ int bmpWidth = bmp.getWidth(); int bmpHeight = bmp.getHeight(); if(width != 0 && height !=0){ Matrix matrix = new Matrix(); float scaleWidth = ((float) width / bmpWidth); float scaleHeight = ((float) height / bmpHeight); matrix.postScale(scaleWidth, scaleHeight); bitmap = Bitmap.createBitmap(bmp, 0, 0, bmpWidth, bmpHeight, matrix, true); }else{ bitmap = bmp; } } return bitmap; }}
CommonAdapter文件:超级适配器,也成通配器,可以使用gridview和listview共同使用:
package com.xiyouliwp.fangweixin;import java.util.List;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;/** * 通配器,CommonAdapter通过封装BaseAdapter和RecyclerView.Adapter得到通用的、简单易用的Adapter。 * 作为ListView和GridView的通用适配器。 * 超级适配器 * @param <T> */public abstract class CommonAdapter<T> extends BaseAdapter { protected LayoutInflater mInflater; protected Context mContext; protected List<T> mDatas; protected final int mItemLayoutId; public CommonAdapter(Context context, List<T> mDatas, int itemLayoutId) { this.mContext = context; this.mInflater = LayoutInflater.from(mContext); this.mDatas = mDatas; this.mItemLayoutId = itemLayoutId; } @Override public int getCount() { return mDatas.size(); } @Override public T getItem(int position) { return mDatas.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { final ViewHolder viewHolder = getViewHolder(position, convertView, parent); convert(viewHolder, getItem(position)); return viewHolder.getConvertView(); } public abstract void convert(ViewHolder helper, T item); private ViewHolder getViewHolder(int position, View convertView, ViewGroup parent) { return ViewHolder.get(mContext, convertView, parent, mItemLayoutId, position); }}
DiskLruCache文件:点击获取到的图片的path路径进行解析
package com.xiyouliwp.fangweixin;/** * Created by lwp940118 on 2016/5/31. */import java.io.BufferedOutputStream;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.FilenameFilter;import java.io.IOException;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import java.net.URLEncoder;import java.util.Collections;import java.util.LinkedHashMap;import java.util.Map;import java.util.Map.Entry;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Bitmap.CompressFormat;import android.graphics.BitmapFactory;public class DiskLruCache { private static final String CACHE_FILENAME_PREFIX = "cache_"; private static final int MAX_REMOVALS = 4; private static final int INITIAL_CAPACITY = 32; private static final float LOAD_FACTOR = 0.75f; private final File mCacheDir; private int cacheSize = 0; private int cacheByteSize = 0; private final int maxCacheItemSize = 64; // 64 item default private long maxCacheByteSize = 1024 * 1024 * 5; // 5MB default private CompressFormat mCompressFormat = CompressFormat.JPEG; private int mCompressQuality = 70; private final int IO_BUFFER_SIZE = 4 * 1024; private final Map<String, String> mLinkedHashMap = Collections.synchronizedMap(new LinkedHashMap<String, String>(INITIAL_CAPACITY, LOAD_FACTOR, true)); /** * A filename filter to use to identify the cache filenames which have CACHE_FILENAME_PREFIX prepended. */ private static final FilenameFilter cacheFileFilter = new FilenameFilter() { @Override public boolean accept(File dir, String filename) { return filename.startsWith(CACHE_FILENAME_PREFIX); } }; /** * Used to fetch an instance of DiskLruCache. * * @param context * @param cacheDir * @param maxByteSize * @return */ public static DiskLruCache openCache(Context context, File cacheDir, long maxByteSize) { if (!cacheDir.exists()) { cacheDir.mkdir(); } if (cacheDir.isDirectory() && cacheDir.canWrite()) { return new DiskLruCache(cacheDir, maxByteSize); } return null; } /** * @param cacheDir * @param maxByteSize */ private DiskLruCache(File cacheDir, long maxByteSize) { mCacheDir = cacheDir; maxCacheByteSize = maxByteSize; } /** * Add a bitmap to the disk cache. * * @param key A unique identifier for the bitmap. * @param data The bitmap to store. */ public void put(String key, Bitmap data) { synchronized (mLinkedHashMap) { if (mLinkedHashMap.get(key) == null) { try { final String file = createFilePath(mCacheDir, key); if (writeBitmapToFile(data, file)) { put(key, file); flushCache(); } } catch (final FileNotFoundException e) { } catch (final IOException e) { } } } } private void put(String key, String file) { mLinkedHashMap.put(key, file); cacheSize = mLinkedHashMap.size(); cacheByteSize += new File(file).length(); } /** * Flush the cache, removing oldest entries if the total size is over the specified cache size. Note that this isn't keeping track of stale files in the cache directory that * aren't in the HashMap. If the images and keys in the disk cache change often then they probably won't ever be removed. */ private void flushCache() { Entry<String, String> eldestEntry; File eldestFile; long eldestFileSize; int count = 0; while (count < MAX_REMOVALS && (cacheSize > maxCacheItemSize || cacheByteSize > maxCacheByteSize)) { eldestEntry = mLinkedHashMap.entrySet().iterator().next(); eldestFile = new File(eldestEntry.getValue()); eldestFileSize = eldestFile.length(); mLinkedHashMap.remove(eldestEntry.getKey()); eldestFile.delete(); cacheSize = mLinkedHashMap.size(); cacheByteSize -= eldestFileSize; count++; } } /** * Get an image from the disk cache. * * @param key The unique identifier for the bitmap * @return The bitmap or null if not found */ public Bitmap get(String key) { synchronized (mLinkedHashMap) { try { final String file = mLinkedHashMap.get(key); if (file != null) { return BitmapFactory.decodeFile(file); } else { final String existingFile = createFilePath(mCacheDir, key); if (new File(existingFile).exists()) { put(key, existingFile); return BitmapFactory.decodeFile(existingFile); } } } catch (OutOfMemoryError e) { } return null; } } /** * Checks if a specific key exist in the cache. * * @param key The unique identifier for the bitmap * @return true if found, false otherwise */ public boolean containsKey(String key) { // See if the key is in our HashMap if (mLinkedHashMap.containsKey(key)) { return true; } // Now check if there's an actual file that exists based on the key final String existingFile = createFilePath(mCacheDir, key); if (new File(existingFile).exists()) { // File found, add it to the HashMap for future use put(key, existingFile); return true; } return false; } /** * Removes all disk cache entries from this instance cache dir */ public void clearCache() { DiskLruCache.clearCache(mCacheDir); } /** * Removes all disk cache entries from the application cache directory in the uniqueName sub-directory. * * @param context The context to use * @param uniqueName A unique cache directory name to append to the app cache directory */ public static void clearCache(Context context, String uniqueName) { File cacheDir = getDiskCacheDir(context, uniqueName); clearCache(cacheDir); } /** * Removes all disk cache entries from the given directory. This should not be called directly, call {@link DiskLruCache#clearCache(Context, String)} or * {@link DiskLruCache#clearCache()} instead. * * @param cacheDir The directory to remove the cache files from */ private static void clearCache(File cacheDir) { final File[] files = cacheDir.listFiles(cacheFileFilter); for (int i = 0; i < files.length; i++) { files[i].delete(); } } /** * Get a usable cache directory (external if available, internal otherwise). * * @param context The context to use * @param uniqueName A unique directory name to append to the cache dir * @return The cache dir */ public static File getDiskCacheDir(Context context, String uniqueName) { // Check if media is mounted or storage is built-in, if so, try and use external cache dir // otherwise use internal cache dir final String cachePath = context.getCacheDir().getPath(); return new File(cachePath + File.separator + uniqueName); } /** * Creates a constant cache file path given a target cache directory and an image key. * * @param cacheDir * @param key * @return */ public static String createFilePath(File cacheDir, String key) { try { // Use URLEncoder to ensure we have a valid filename, a tad hacky but it will do for // this example return cacheDir.getAbsolutePath() + File.separator + CACHE_FILENAME_PREFIX + URLEncoder.encode(key.replace("*", ""), "UTF-8"); } catch (final UnsupportedEncodingException e) { } return null; } /** * Create a constant cache file path using the current cache directory and an image key. * * @param key * @return */ public String createFilePath(String key) { return createFilePath(mCacheDir, key); } /** * Sets the target compression format and quality for images written to the disk cache. * * @param compressFormat * @param quality */ public void setCompressParams(CompressFormat compressFormat, int quality) { mCompressFormat = compressFormat; mCompressQuality = quality; } /** * Writes a bitmap to a file. Call {@link DiskLruCache#setCompressParams(CompressFormat, int)} first to set the target bitmap compression and format. * * @param bitmap * @param file * @return */ private boolean writeBitmapToFile(Bitmap bitmap, String file) throws IOException, FileNotFoundException { OutputStream out = null; try { out = new BufferedOutputStream(new FileOutputStream(file), IO_BUFFER_SIZE); return bitmap.compress(mCompressFormat, mCompressQuality, out); } finally { if (out != null) { out.close(); } } }}
ImageFolder文件:图片的信息的定义:
package com.xiyouliwp.fangweixin;/** * 需求:对手机中的图片进行扫描,直接显示在gridview上,并且在扫描结束后得到一个list,,list里面存的是所有包含 * 图片的文件夹 * Created by lwp940118 on 2016/5/29. * 李文朋 */public class ImageFolder { //文件夹的路径 private String folderPath; //第一张图片的文件夹路径 private String firstImagePath; //文件夹名称 private String folderName; //图片的数量 private int imageCount = 0; public int getImageCount() { return imageCount; } public String getFirstImagePath() { return firstImagePath; } public String getFolderName() { return folderName; } public String getFolderPath() { return folderPath; } public void setFirstImagePath(String firstImagePath) { this.firstImagePath = firstImagePath; } public void setFolderPath(String folderPath) { this.folderPath = folderPath; //判断字符/它第一次出现的位置 int start = this.folderPath.lastIndexOf("/"); //得到从/第一次出现的位置开始 到该字符串结束的子串为folderName this.folderName = this.folderPath.substring(start); } public void setImageCount(int imageCount) { this.imageCount = imageCount; }}
ImageLoade文件:缓存图片,使grideview运行流畅
package com.xiyouliwp.fangweixin;import java.lang.reflect.Field;import java.util.LinkedList;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.support.v4.util.LruCache;import android.util.DisplayMetrics;import android.util.Log;import android.view.ViewGroup.LayoutParams;import android.widget.ImageView;public class ImageLoade { /** * 图片缓存的核心类 */ private LruCache<String, Bitmap> mLruCache; /** * 线程池 */ private ExecutorService mThreadPool; /** * 线程池的线程数量,默认为1 */ private int mThreadCount = 1; /** * 队列的调度方式 */ private Type mType = Type.LIFO; /** * 任务队列 */ private LinkedList<Runnable> mTasks; /** * 轮询的线程 */ private Thread mPoolThread; private Handler mPoolThreadHander; /** * 运行在UI线程的handler,用于给ImageView设置图片 */ private Handler mHandler; /** * 引入一个值为1的信号量,防止mPoolThreadHander未初始化完成 */ private volatile Semaphore mSemaphore = new Semaphore(0); /** * 引入一个值为1的信号量,由于线程池内部也有一个阻塞线程,防止加入任务的速度过快,使LIFO效果不明显 */ private volatile Semaphore mPoolSemaphore; private static ImageLoade mInstance; /** * 队列的调度方式 * * @author zhy */ public enum Type { FIFO, LIFO } /** * 单例获得该实例对象 * * @return */ public static ImageLoade getInstance() { if (mInstance == null) { synchronized (ImageLoade.class) { if (mInstance == null) { mInstance = new ImageLoade(1, Type.LIFO); } } } return mInstance; } private ImageLoade(int threadCount, Type type) { init(threadCount, type); } private void init(int threadCount, Type type) { // loop thread mPoolThread = new Thread() { @Override public void run() { Looper.prepare(); mPoolThreadHander = new Handler() { @Override public void handleMessage(Message msg) { mThreadPool.execute(getTask()); try { mPoolSemaphore.acquire(); } catch (InterruptedException e) { } } }; // 释放一个信号量 mSemaphore.release(); Looper.loop(); } }; mPoolThread.start(); // 获取应用程序最大可用内存 int maxMemory = (int) Runtime.getRuntime().maxMemory(); int cacheSize = maxMemory / 8; mLruCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String key, Bitmap value) { return value.getRowBytes() * value.getHeight(); } ; }; mThreadPool = Executors.newFixedThreadPool(threadCount); mPoolSemaphore = new Semaphore(threadCount); mTasks = new LinkedList<Runnable>(); mType = type == null ? Type.LIFO : type; } /** * 加载图片 * * @param path * @param imageView */ public void loadImage(final String path, final ImageView imageView) { // set tag imageView.setTag(path); // UI线程 if (mHandler == null) { mHandler = new Handler() { @Override public void handleMessage(Message msg) { ImgBeanHolder holder = (ImgBeanHolder) msg.obj; ImageView imageView = holder.imageView; Bitmap bm = holder.bitmap; String path = holder.path; if (imageView.getTag().toString().equals(path)) { imageView.setImageBitmap(bm); } } }; } Bitmap bm = getBitmapFromLruCache(path); if (bm != null) { ImgBeanHolder holder = new ImgBeanHolder(); holder.bitmap = bm; holder.imageView = imageView; holder.path = path; Message message = Message.obtain(); message.obj = holder; mHandler.sendMessage(message); } else { addTask(new Runnable() { @Override public void run() { ImageSize imageSize = getImageViewWidth(imageView); int reqWidth = imageSize.width; int reqHeight = imageSize.height; Bitmap bm = decodeSampledBitmapFromResource(path, reqWidth, reqHeight); addBitmapToLruCache(path, bm); ImgBeanHolder holder = new ImgBeanHolder(); holder.bitmap = getBitmapFromLruCache(path); holder.imageView = imageView; holder.path = path; Message message = Message.obtain(); message.obj = holder; // Log.e("TAG", "mHandler.sendMessage(message);"); mHandler.sendMessage(message); mPoolSemaphore.release(); } }); } } /** * 添加一个任务 * * @param runnable */ private synchronized void addTask(Runnable runnable) { try { // 请求信号量,防止mPoolThreadHander为null if (mPoolThreadHander == null) mSemaphore.acquire(); } catch (InterruptedException e) { } mTasks.add(runnable); mPoolThreadHander.sendEmptyMessage(0x110); } /** * 取出一个任务 * * @return */ private synchronized Runnable getTask() { if (mType == Type.FIFO) { return mTasks.removeFirst(); } else if (mType == Type.LIFO) { return mTasks.removeLast(); } return null; } /** * 单例获得该实例对象 * * @return */ public static ImageLoade getInstance(int threadCount, Type type) { if (mInstance == null) { synchronized (ImageLoade.class) { if (mInstance == null) { mInstance = new ImageLoade(threadCount, type); } } } return mInstance; } /** * 根据ImageView获得适当的压缩的宽和高 * * @param imageView * @return */ private ImageSize getImageViewWidth(ImageView imageView) { ImageSize imageSize = new ImageSize(); final DisplayMetrics displayMetrics = imageView.getContext() .getResources().getDisplayMetrics(); final LayoutParams params = imageView.getLayoutParams(); int width = params.width == LayoutParams.WRAP_CONTENT ? 0 : imageView .getWidth(); // Get actual image width if (width <= 0) width = params.width; // Get layout width parameter if (width <= 0) width = getImageViewFieldValue(imageView, "mMaxWidth"); // Check // maxWidth // parameter if (width <= 0) width = displayMetrics.widthPixels; int height = params.height == LayoutParams.WRAP_CONTENT ? 0 : imageView .getHeight(); // Get actual image height if (height <= 0) height = params.height; // Get layout height parameter if (height <= 0) height = getImageViewFieldValue(imageView, "mMaxHeight"); // Check // maxHeight // parameter if (height <= 0) height = displayMetrics.heightPixels; imageSize.width = width; imageSize.height = height; return imageSize; } /** * 从LruCache中获取一张图片,如果不存在就返回null。 */ private Bitmap getBitmapFromLruCache(String key) { return mLruCache.get(key); } /** * 往LruCache中添加一张图片 * * @param key * @param bitmap */ private void addBitmapToLruCache(String key, Bitmap bitmap) { if (getBitmapFromLruCache(key) == null) { if (bitmap != null) mLruCache.put(key, bitmap); } } /** * 计算inSampleSize,用于压缩图片 * * @param options * @param reqWidth * @param reqHeight * @return */ private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // 源图片的宽度 int width = options.outWidth; int height = options.outHeight; int inSampleSize = 1; if (width > reqWidth && height > reqHeight) { // 计算出实际宽度和目标宽度的比率 int widthRatio = Math.round((float) width / (float) reqWidth); int heightRatio = Math.round((float) width / (float) reqWidth); inSampleSize = Math.max(widthRatio, heightRatio); } return inSampleSize; } /** * 根据计算的inSampleSize,得到压缩后图片 * * @param pathName * @param reqWidth * @param reqHeight * @return */ private Bitmap decodeSampledBitmapFromResource(String pathName, int reqWidth, int reqHeight) { // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小 final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(pathName, options); // 调用上面定义的方法计算inSampleSize值 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // 使用获取到的inSampleSize值再次解析图片 options.inJustDecodeBounds = false; Bitmap bitmap = BitmapFactory.decodeFile(pathName, options); return bitmap; } private class ImgBeanHolder { Bitmap bitmap; ImageView imageView; String path; } private class ImageSize { int width; int height; } /** * 反射获得ImageView设置的最大宽度和高度 * * @param object * @param fieldName * @return */ private static int getImageViewFieldValue(Object object, String fieldName) { int value = 0; try { Field field = ImageView.class.getDeclaredField(fieldName); field.setAccessible(true); int fieldValue = (Integer) field.get(object); if (fieldValue > 0 && fieldValue < Integer.MAX_VALUE) { value = fieldValue; Log.e("TAG", value + ""); } } catch (Exception e) { } return value; }}
ImageShowManager文件:图片的一些信息及其缓存情况的设置
package com.xiyouliwp.fangweixin;/** * Created by lwp940118 on 2016/5/31. */import java.io.File;import android.app.ActivityManager;import android.app.Application;import android.content.Context;import android.graphics.Bitmap;import android.os.Looper;import android.support.v4.util.LruCache;public class ImageShowManager { private static ImageShowManager imageManager; private static Application myApp; private LruCache<String, Bitmap> mMemoryCache; private DiskLruCache mDiskCache; // 硬盘缓存区域的大小,可以提升之前浏览过的图片的显示速度 private static final int DISK_CACHE_SIZE = 1024 * 1024 * 20; // 硬盘缓存区域的文件名称 private static final String DISK_CACHE_SUBDIR = "thumbnails"; public static final int bitmap_width = 100; public static final int bitmap_height = 100; public static ImageShowManager from(Context context) { // 如果不在ui线程中,则抛出异常 if (Looper.myLooper() != Looper.getMainLooper()) { throw new RuntimeException("Cannot instantiate outside UI thread."); } if (myApp == null) { myApp = (Application) context.getApplicationContext(); } if (imageManager == null) { imageManager = new ImageShowManager(myApp); } // return imageManager; } /** * 私有的构造器为了保持单例模式 */ private ImageShowManager(Context context) { /********** 初始化内存缓冲区 ******/ int memClass = ((ActivityManager) context .getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass(); memClass = memClass > 32 ? 32 : memClass; // 使用可用内存的1/8作为图片缓存 final int cacheSize = 1024 * 1024 * memClass / 8; mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String key, Bitmap bitmap) { return bitmap.getRowBytes() * bitmap.getHeight(); } }; /********* 初始化硬盘缓冲区 *********/ File cacheDir = DiskLruCache .getDiskCacheDir(context, DISK_CACHE_SUBDIR); mDiskCache = DiskLruCache.openCache(context, cacheDir, DISK_CACHE_SIZE); } /** * 将图片保存至本地缓存 * @param key * @param value */ public void putBitmapToDisk(String key,Bitmap value){ mDiskCache.put(key, value); } /** * 从硬盘缓存中读取图像 * @param url * @return */ public Bitmap getBitmapFormDisk(String url){ return mDiskCache.get(url); } /** * 从内存缓存区中获取bitmap,根据特定的url * @param url * @return */ public Bitmap getBitmapFromMemory(String url){ return mMemoryCache.get(url); } /** * 将新的图片添加至内存缓存区 * @param key * @param value */ public void putBitmapToMemery(String key,Bitmap value){ mMemoryCache.put(key, value); }}
List_File_PopWind文件:弹出窗口的设置及其定义:
package com.xiyouliwp.fangweixin;import java.util.List;import android.content.Context;import android.graphics.drawable.BitmapDrawable;import android.view.MotionEvent;import android.view.View;import android.view.View.OnTouchListener;import android.widget.AdapterView;import android.widget.ListView;import android.widget.PopupWindow;/** * Created by lwp940118 on 2016/5/29. */public class List_File_PopWind extends BasePopupWindowForListView<ImageFolder>{ private ListView mListDir; public List_File_PopWind(int width, int height, List<ImageFolder> datas, View convertView) { super(convertView, width, height, true, datas); } @Override public void initViews() { mListDir = (ListView) findViewById(R.id.listviwe_dir); mListDir.setAdapter(new CommonAdapter<ImageFolder>(context, mDatas, R.layout.list_dir_item) { @Override public void convert(ViewHolder helper, ImageFolder item) { helper.setText(R.id.id_dir_item_name, item.getFolderName()); helper.setImageByUrl(R.id.id_dir_item_image, item.getFirstImagePath()); helper.setText(R.id.id_dir_item_count, item.getImageCount() + "张"); } }); } public interface OnImageDirSelected { void selected(ImageFolder floder); } private OnImageDirSelected mImageDirSelected; public void setOnImageDirSelected(OnImageDirSelected mImageDirSelected) { this.mImageDirSelected = mImageDirSelected; } @Override public void initEvents() { mListDir.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (mImageDirSelected != null) { mImageDirSelected.selected(mDatas.get(position)); } } }); } @Override public void init() { } @Override protected void beforeInitWeNeedSomeParams(Object... params) { }}abstract class BasePopupWindowForListView<T> extends PopupWindow { /** * 布局文件的最外层View */ protected View mContentView; protected Context context; /** * ListView的数据集 */ protected List<T> mDatas; public BasePopupWindowForListView(View contentView, int width, int height, boolean focusable) { this(contentView, width, height, focusable, null); } public BasePopupWindowForListView(View contentView, int width, int height, boolean focusable, List<T> mDatas) { this(contentView, width, height, focusable, mDatas, new Object[0]); } public BasePopupWindowForListView(View contentView, int width, int height, boolean focusable, List<T> mDatas, Object... params) { super(contentView, width, height, focusable); this.mContentView = contentView; context = contentView.getContext(); if (mDatas != null) this.mDatas = mDatas; if (params != null && params.length > 0) { beforeInitWeNeedSomeParams(params); } setBackgroundDrawable(new BitmapDrawable()); setTouchable(true); setOutsideTouchable(true); setTouchInterceptor(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { dismiss(); return true; } return false; } }); initViews(); initEvents(); init(); } protected abstract void beforeInitWeNeedSomeParams(Object... params); public abstract void initViews(); public abstract void initEvents(); public abstract void init(); public View findViewById(int id) { return mContentView.findViewById(id); } protected static int dpToPx(Context context, int dp) { return (int) (context.getResources().getDisplayMetrics().density * dp + 0.5f); }}
PopRecommend_ImageAdd_Adapter文件:返回时存放选择图片的gridview的适配器
package com.xiyouliwp.fangweixin;import java.lang.ref.WeakReference;import java.util.ArrayList;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.Color;import android.graphics.drawable.ColorDrawable;import android.graphics.drawable.Drawable;import android.os.AsyncTask;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;/** * Created by lwp940118 on 2016/5/31. */public class PopRecommend_ImageAdd_Adapter extends BaseAdapter { private Activity uiActivity; private ArrayList<String> paths; private int size; private ImageShowManager imageManager; private LayoutInflater li; public PopRecommend_ImageAdd_Adapter(Activity a, ArrayList<String> paths) { this.uiActivity = a; this.paths = paths; size = paths.size(); imageManager = ImageShowManager.from(uiActivity); li = LayoutInflater.from(uiActivity); } @Override public int getCount() { // TODO Auto-generated method stub return size; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { SurfaceHolder surfaceHolder = new SurfaceHolder(); if (convertView != null) { surfaceHolder = (SurfaceHolder) convertView.getTag(); } else { convertView = li.inflate(R.layout.item_gridview_poprecommend, null); surfaceHolder.iv = (ImageView) convertView .findViewById(R.id.imageView1); } convertView.setTag(surfaceHolder); String path = paths.get(position); // 首先检测是否已经有线程在加载同样的资源(如果则取消较早的),避免出现重复加载 if (cancelPotentialLoad(path, surfaceHolder.iv)) { AsyncLoadImageTask task = new AsyncLoadImageTask(surfaceHolder.iv); surfaceHolder.iv.setImageDrawable(new LoadingDrawable(task)); task.execute(path); } return convertView; } static class SurfaceHolder { ImageView iv; } /** * 判断当前的imageview是否在加载相同的资源 * * @param url * @param imageview * @return */ private boolean cancelPotentialLoad(String url, ImageView imageview) { AsyncLoadImageTask loadImageTask = getAsyncLoadImageTask(imageview); if (loadImageTask != null) { String bitmapUrl = loadImageTask.url; if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) { loadImageTask.cancel(true); } else { // 相同的url已经在加载中. return false; } } return true; } /** * 负责加载图片的异步线程 * * @author Administrator */ class AsyncLoadImageTask extends AsyncTask<String, Void, Bitmap> { private final WeakReference<ImageView> imageViewReference; private String url = null; public AsyncLoadImageTask(ImageView imageview) { super(); imageViewReference = new WeakReference<ImageView>(imageview); } @Override protected Bitmap doInBackground(String... params) { /** * 具体的获取bitmap的部分,流程: 从内存缓冲区获取,如果没有向硬盘缓冲区获取,如果没有从sd卡/网络获取 */ Bitmap bitmap = null; this.url = params[0]; // 从内存缓存区域读取 bitmap = imageManager.getBitmapFromMemory(url); if (bitmap != null) { Log.d("dqq", "return by 内存"); return bitmap; } // 从硬盘缓存区域中读取 bitmap = imageManager.getBitmapFormDisk(url); if (bitmap != null) { imageManager.putBitmapToMemery(url, bitmap); Log.d("dqq", "return by 硬盘"); return bitmap; } // 没有缓存则从原始位置读取 bitmap = BitmapUtilities.getBitmapThumbnail(url, ImageShowManager.bitmap_width, ImageShowManager.bitmap_height); imageManager.putBitmapToMemery(url, bitmap); imageManager.putBitmapToDisk(url, bitmap); Log.d("dqq", "return by 原始读取"); return bitmap; } @Override protected void onPostExecute(Bitmap resultBitmap) { if (isCancelled()) { // 被取消了 resultBitmap = null; } if (imageViewReference != null) { ImageView imageview = imageViewReference.get(); AsyncLoadImageTask loadImageTask = getAsyncLoadImageTask(imageview); if (this == loadImageTask) { imageview.setImageDrawable(null); imageview.setImageBitmap(resultBitmap); } } super.onPostExecute(resultBitmap); } } /** * 根据imageview,获得正在为此imageview异步加载数据的函数 * * @param imageview * @return */ private AsyncLoadImageTask getAsyncLoadImageTask(ImageView imageview) { if (imageview != null) { Drawable drawable = imageview.getDrawable(); if (drawable instanceof LoadingDrawable) { LoadingDrawable loadedDrawable = (LoadingDrawable) drawable; return loadedDrawable.getLoadImageTask(); } } return null; } /** * 记录imageview对应的加载任务,并且设置默认的drawable * * @author Administrator */ public static class LoadingDrawable extends ColorDrawable { // 引用与drawable相关联的的加载线程 private final WeakReference<AsyncLoadImageTask> loadImageTaskReference; public LoadingDrawable(AsyncLoadImageTask loadImageTask) { super(Color.BLUE); loadImageTaskReference = new WeakReference<AsyncLoadImageTask>( loadImageTask); } public AsyncLoadImageTask getLoadImageTask() { return loadImageTaskReference.get(); } }}
ViewHolde文件:从sd卡中读取图片时gridview和listview的优化:
package com.xiyouliwp.fangweixin;/** * Created by lwp940118 on 2016/5/29. */import android.content.Context;import android.graphics.Bitmap;import android.util.SparseArray;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.TextView;public class ViewHolder { private final SparseArray<View> mViews; private int mPosition; private View mConvertView; private ViewHolder(Context context, ViewGroup parent, int layoutId, int position) { this.mPosition = position; this.mViews = new SparseArray<View>(); mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false); // setTag mConvertView.setTag(this); } /** * 拿到一个ViewHolder对象 */ public static ViewHolder get(Context context, View convertView, ViewGroup parent, int layoutId, int position) { ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(context, parent, layoutId, position); } else { holder = (ViewHolder) convertView.getTag(); holder.mPosition = position; } return holder; } public View getConvertView() { return mConvertView; } /** * 通过控件的Id获取对于的控件,如果没有则加入views * * @return */ public <T extends View> T getView(int viewId) { View view = mViews.get(viewId); if (view == null) { view = mConvertView.findViewById(viewId); mViews.put(viewId, view); } return (T) view; } /** * 为TextView设置字符串 * * @return */ public ViewHolder setText(int viewId, String text) { TextView view = getView(viewId); view.setText(text); return this; } /** * 为ImageView设置图片 * * @return */ public ViewHolder setImageResource(int viewId, int drawableId) { ImageView view = getView(viewId); view.setImageResource(drawableId); return this; } /** * 为ImageView设置图片 */ public ViewHolder setImageBitmap(int viewId, Bitmap bm) { ImageView view = getView(viewId); view.setImageBitmap(bm); return this; } /** * 为ImageView设置图片 */ public ViewHolder setImageByUrl(int viewId, String url) { ImageLoade.getInstance(3, ImageLoade.Type.LIFO).loadImage(url, (ImageView) getView(viewId)); return this; } public int getPosition() { return mPosition; }}
push_bottom_in.xml push_bottom_out.xml文件:定义弹出窗口的划入划出方式:
<?xml version="1.0" encoding="utf-8"?><!-- 上下滑入式 --><set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="200" android:fromYDelta="100%p" android:toYDelta="0" /> <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="200" /></set>
<?xml version="1.0" encoding="utf-8"?><!-- 上下滑入式 --><set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="200" android:fromYDelta="0" android:toYDelta="50%p" /> <alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="200" /></set>
mybutton.xml按钮形状设置:
<?xml version="1.0" encoding="utf-8"?><layer-list xmlns:android="http://schemas.android.com/apk/res/android" > <item> <shape android:shape="rectangle" > <corners android:radius="8dp"/> <solid android:color="#ffffff"/> </shape> </item> <item android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp"> <shape android:shape="rectangle" > <corners android:radius="8dp" /> <solid android:color="#ddf0ed" /> </shape> </item></layer-list>
myedittext.xml 输入框的边框设置
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <!-- <gradient android:angle="45" android:endColor="#CCCCCC" android:startColor="#CCCCCC" /> --> <padding android:bottom="7dp" android:left="7dp" android:right="7dp" android:top="7dp" /> <!-- 设置圆角矩形 --> <corners android:radius="6dp" /> <stroke android:width="5px" android:color="#1199EF" /> <solid android:color="#CCCCCC" /></shape>
下面给出demo中使用的布局文件
activity_image_add.xml
<?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"> <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:orientation="horizontal" android:background="#ddf0ed"> <ImageButton android:id="@+id/imagebutton_imageadd_back" android:layout_width="25dp" android:layout_height="25dp" android:layout_gravity="center" android:layout_marginLeft="15dp" android:background="@drawable/share_search_back" /> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"/> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:text="iPet选择图片" android:gravity="center" android:textSize="20dp"/> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"/> <ImageButton android:id="@+id/imagebutton_imageadd_finish" android:layout_width="28dp" android:layout_height="28dp" android:layout_gravity="center" android:layout_marginRight="15dp" android:background="@drawable/finish"/> </LinearLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <GridView android:id="@+id/gridview_imageadd" android:layout_width="match_parent" android:layout_height="match_parent" android:cacheColorHint="@android:color/transparent" android:clipChildren="true" android:gravity="center" android:horizontalSpacing="3dip" android:listSelector="@android:color/transparent" android:numColumns="3" android:stretchMode="columnWidth" android:verticalSpacing="3dip"> </GridView> <RelativeLayout android:id="@+id/id_bottom_ly" android:layout_width="match_parent" android:layout_height="50dip" android:layout_alignParentBottom="true" android:background="#e0000000" android:clickable="true"> <TextView android:id="@+id/id_choose_dir" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:gravity="center_vertical" android:paddingLeft="10dip" android:text="所有图片" android:textColor="@android:color/white" /> <TextView android:id="@+id/id_total_count" android:layout_width="50dip" android:layout_height="match_parent" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:gravity="center" android:text="0张" android:textColor="@android:color/white" /> </RelativeLayout> </RelativeLayout></LinearLayout>
activity_main.xml
<?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"> <LinearLayout android:id="@+id/linearlayout_pop_recommend" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="20dp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="60dp" android:background="#ddf0ed" android:orientation="horizontal"> <TextView android:id="@+id/textview_recommend_list" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="15dp" android:gravity="left|center" android:text="动态发布:" android:textColor="#fb0b0b0b" android:textSize="20dp" /> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /> <ImageButton android:id="@+id/imagview_poprecommend_back" android:layout_width="30dp" android:layout_height="30dp" android:layout_gravity="center" android:layout_marginRight="15dp" android:background="@drawable/quxiao" /> </LinearLayout> <EditText android:id="@+id/edittext_poprecommend" android:layout_width="match_parent" android:layout_height="150dp" android:background="@drawable/myedittext" /> <LinearLayout android:layout_width="match_parent" android:layout_height="70dp" android:orientation="horizontal"> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /> <LinearLayout android:layout_width="40dp" android:layout_height="40dp" android:layout_gravity="center" android:background="#ddf0ed"> <ImageButton android:id="@+id/iamgebutton_poprecommend_tianjiatupian" android:layout_width="40dp" android:layout_height="40dp" android:layout_gravity="center" android:background="@drawable/tianjiatupian" /> </LinearLayout> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="5" /> <Button android:id="@+id/button_poprecommend_fabu" android:layout_width="70dp" android:layout_height="40dp" android:layout_gravity="center" android:background="@drawable/mybutton" android:text="发布" android:textSize="20dp" /> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /> </LinearLayout> </LinearLayout> <GridView android:id="@+id/gridview_poprecommend" android:layout_width="match_parent" android:layout_height="150dp" android:cacheColorHint="@android:color/transparent" android:clipChildren="true" android:gravity="center" android:horizontalSpacing="3dip" android:listSelector="@android:color/transparent" android:numColumns="4" android:stretchMode="columnWidth" android:verticalSpacing="3dip"> </GridView> <TextView android:layout_width="match_parent" android:layout_height="20dp"/></LinearLayout>
item_gridview_imageadd.xml
<?xml version="1.0" encoding="UTF-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ImageView android:id="@+id/id_item_image" android:layout_width="fill_parent" android:layout_height="100dp" android:background="@drawable/pictures_no" android:scaleType="centerCrop" /> <ImageButton android:id="@+id/id_item_select" android:clickable="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginRight="3dp" android:layout_marginTop="3dp" android:background="@null" android:src="@drawable/pictures_selected" /></RelativeLayout>
item_gridview_poprecommend.xml
<?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" > <RelativeLayout android:layout_width="80dp" android:layout_height="80dp" android:layout_gravity="center" android:orientation="vertical" > <ImageView android:id="@+id/imageView1" android:layout_width="100dp" android:layout_height="100dp" android:layout_margin="10dp" android:scaleType="centerInside" android:background="@drawable/pictures_no"/> </RelativeLayout></LinearLayout>
list_dir_item.xml
<?xml version="1.0" encoding="UTF-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="5dp" > <ImageView android:id="@+id/id_dir_item_image" android:layout_width="100dp" android:layout_height="100dp" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:background="@drawable/pic_dir" android:paddingBottom="17dp" android:paddingLeft="12dp" android:paddingRight="12dp" android:paddingTop="9dp" android:scaleType="fitXY" android:src="@drawable/ic_launcher" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="10dp" android:layout_toRightOf="@id/id_dir_item_image" android:orientation="vertical" > <TextView android:id="@+id/id_dir_item_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="所有图片" android:textSize="10sp" /> <TextView android:id="@+id/id_dir_item_count" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="4723张" android:textColor="#444" android:textSize="8sp" /> </LinearLayout> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_marginRight="20dp" android:src="@drawable/dir_choose" /></RelativeLayout>
list_dir.xml
<?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"> <ListView android:id="@+id/listviwe_dir" android:layout_width="fill_parent" android:layout_height="fill_parent" android:divider="#EEE3D9" android:dividerHeight="1px" > </ListView></LinearLayout>
本demo参考博文有:
http://blog.csdn.net/lmj623565791/article/details/39943731/
还有一些小的问题是从网上百度的 忘记地址了,总之谢谢他们
最后别忘了给整个demo加入权限设置:
<uses-permission android:name="android.permission.CALL_PHONE"></uses-permission> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
- 仿微信图片选择器
- Android-仿微信图片选择器
- Android 仿微信图片选择器
- 仿微信图片选择器
- 仿微信图片选择器
- Android仿微信图片选择器
- 0.仿微信图片选择器
- Android 仿微信图片选择器
- 仿微信图片选择器
- 仿微信图片选择器,一步到位!!!
- android仿微信图片选择器
- android 仿微信图片选择器
- 仿微信图片选择器
- android 超高仿微信图片选择器
- Android开发:仿微信图片选择器
- Android 超高仿微信图片选择器
- 图片选择器
- 图片选择器
- 命令行执行Junit测试
- 对链表进行排序
- 欢迎使用CSDN-markdown编辑器
- NoSQL之Redis---Lists类型命令
- Java加密技术(二)——对称加密算法DES&AES
- 仿微信图片选择器
- Android Dev Intro - Stencil Test
- java中的jar包
- iOS学习之——多线程编程
- 图解 & 深入浅出JavaWeb:事务必会必知
- C++11简介(五)
- Git Gui for Windows的建库、克隆(clone)、上传(push)、下载(pull)、合并
- Spring3.0+Hibernate+Atomikos集成构建JTA的分布式事务-
- html5 viedo视频标签在手机上无法正常播放解决方法