粗仿数字尾巴实现安卓图片选择器

编程入门 行业动态 更新时间:2024-10-07 02:26:33

粗仿数字<a href=https://www.elefans.com/category/jswz/34/1746394.html style=尾巴实现安卓图片选择器"/>

粗仿数字尾巴实现安卓图片选择器

趁热打铁,使用内容解析者(ContentResolver)来实现一个图片选择器,大体的功能样式仿照的数字尾巴,( ̄▽ ̄)”只是粗仿……

下面是运行效果(GIF图片超过2MB就不能上传了/(ㄒoㄒ)/~~):

MediaStore这个类是android系统提供的一个多媒体数据库,android中多媒体信息都可以从这里提取。这个MediaStore包括了多媒体数据库的所有信息,包括音频,视频和图像。操作就和使用内容解析这获取其它数据的过程一样,android把所有的多媒体数据库接口进行了封装,所有的数据库不用自己进行创建,直接调用利用ContentResolver去掉用那些封装好的接口就可以进行数据库的操作了。

可以通过查看系统上层源码来查看数据封装的方式,以及在data目录下查看数据库,查看各种格式的文件在数据库中的存储方式,方便对后面的操作的理解。

下面叙述一下实现的过程:

目录结构:

ImageView的加强,重新自定义了一个可以选择的ImageView

MyCustomImageView.java

package com.example.imageselector;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ImageView;/*** Created by 春水碧于天 on 2017/1/18.*/public class MyCustomImageView extends ImageView {private int mViewWidth; //当前ImageView的宽private int mViewHeight; //当前ImageView的高private Paint mPaint_stroke;private Paint mPaint_fill;private Paint mPaint_text;private String mDrawText; //要绘制的文本private Boolean isChoice = false;private onCheckedChangeListener mCheckedChangeListener;private boolean isCanTouch = true;public MyCustomImageView(Context context) {super(context);InitPaint();}public MyCustomImageView(Context context, AttributeSet attrs) {super(context, attrs);InitPaint();}public MyCustomImageView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);InitPaint();}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mViewWidth = w;mViewHeight = h;}public void setDrawText(String mDrawText){this.mDrawText = mDrawText;invalidate(); //重新绘制}public void setChecked(boolean isChecked){isChoice = isChecked;invalidate();}public void setIsCanTouch(boolean isCanTouch){this.isCanTouch = isCanTouch;}@Overridepublic boolean onTouchEvent(MotionEvent event) {/*** 如果没有选中的话,按下选中* 如果已经选中的话,按下清除内容*/switch (event.getAction()){case MotionEvent.ACTION_DOWN:if(!isChoice){ //如果没有选中isChoice = true;invalidate();}else if(isChoice){ //如果已经选中了isChoice = false;invalidate();}//回调mCheckedChangeListener.isChecked(isChoice);Log.i("tag","手指按下了");break;case MotionEvent.ACTION_UP:Log.i("tag","手指抬起了");break;}if(isCanTouch){return true;}else{return false;}}//初始化画笔public void InitPaint(){mPaint_stroke = new Paint(Paint.ANTI_ALIAS_FLAG); //设置抗锯齿mPaint_stroke.setStyle(Paint.Style.STROKE);//设置填充模式为描边mPaint_stroke.setStrokeWidth(8f);//设置画笔的宽度mPaint_stroke.setColor(Color.BLUE); //设置画笔的颜色mPaint_fill = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint_fill.setStyle(Paint.Style.FILL);//设置填充模式为描边mPaint_fill.setColor(Color.BLUE); //设置画笔的颜色mPaint_text = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint_text.setTextSize(40f);mPaint_text.setColor(Color.rgb(255,255,255));mPaint_text.setTextAlign(Paint.Align.CENTER);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if(isChoice){//绘制矩形边框RectF rectF = new RectF(0f,0f,mViewWidth-10,mViewHeight);canvas.drawRect(rectF, mPaint_stroke);float mCircleX =mViewWidth*(2/3.0f)+(mViewWidth/6.0f);float mCircleY =mViewHeight*(1/6.0f);float mRadius = (mViewHeight/6.0f)*0.7f;//绘制圆canvas.drawCircle(mCircleX,mCircleY,mRadius, mPaint_fill);//绘制文字if(mDrawText!=null) {canvas.drawText(mDrawText, mCircleX, mCircleY + 13f, mPaint_text);}}}/***设置选中后的回调监听*/public void SetOnCheckedChangeListener(onCheckedChangeListener mCheckedChangeListener){this.mCheckedChangeListener = mCheckedChangeListener;}public interface onCheckedChangeListener{void isChecked(boolean isSelected);}
}

图片选择器的核心就是对图片的扫描,这面就使用内容解析者,获取安卓系统通过内容提供者暴露进出的数据库的增删改查的接口,进行操数的操作,后面只需要根据自己的需要筛选出需要的文件夹,以及对应格式的图片,下面的查询是对所有图片的查询没,有在查询的时候的筛根据条件进行晒选。

MainActivity.java

package com.example.imageselector;public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {private  ArrayList<FileBean> FileBeans = null;private Handler mHandler = null;private ListView listView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);InitUI();mHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);if(msg.what == 1){listView.setAdapter(new myAdapter(MainActivity.this,FileBeans));}}};/*** 在线程中处理扫描文件的耗时操作*/new Thread(new Runnable() {Set<String> DirSet  = null;@Overridepublic void run() {if (Environment.getExternalStorageDirectory() == null){Log.i("tag","外部存储卡为空");return;}//通过内容解析者获取手机中所有图片的路径Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;ContentResolver resolver = MainActivity.this.getContentResolver();//查询所有的图片信息,根据修改的时间排序Cursor cursor = resolver.query(uri, null, null, null, MediaStore.Images.Media.DATE_MODIFIED);DirSet = new HashSet<String>(); //用于记录已经扫描过的文件夹,避免重复扫描FileBeans = new ArrayList<FileBean>(); //存放图片文件夹信息FileBean fileBean = null;while(cursor.moveToNext()){String filePath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));if(filePath.endsWith(".gif") || filePath.endsWith(".GIF")) continue; //过滤掉包含GIF图片的文件夹File Parentfile = new File(filePath).getParentFile(); //获取文件所在的文件夹if(Parentfile==null) continue;if(DirSet.contains(Parentfile.toString())) continue; //如果文件夹里的内容已经遍历过就执行下一次的循环String[] list = Parentfile.list(new FilenameFilter() {@Overridepublic boolean accept(File dir, String name) {if (name.endsWith(".png") || name.endsWith(".jpeg") || name.endsWith(".jpg") ) {return true;}return false;}});DirSet.add(Parentfile.toString());int fileNums = list.length;fileBean = new FileBean();fileBean.setFileList(list); //封装一个文件夹中包含的所有图片fileBean.setFileNums(fileNums); //封装一个文件夹中的图片个数fileBean.setFileParent(Parentfile);fileBean.setFirstImage(filePath); //一个文件夹中对应的第一张图片FileBeans.add(fileBean);}mHandler.sendEmptyMessage(1);cursor.close();}}).start();listView.setOnItemClickListener(this);}private void InitUI() {listView = (ListView) findViewById(R.id.listview);}@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {FileBean fileBean = (FileBean) parent.getItemAtPosition(position);Intent intent = new Intent(MainActivity.this,ShowImageActivity.class);intent.putExtra("fileBean", (Serializable) fileBean);startActivity(intent);}
}

用于显示文件夹的listview适配器:myAdapter.java

/*** Created by 春水碧于天 on 2017/1/17.*/public class myAdapter extends BaseAdapter {private ArrayList<FileBean> BeanList;private Context mContext;public myAdapter(Context mContext,ArrayList<FileBean> BeanList) {this.BeanList = BeanList;this.mContext = mContext;}@Overridepublic int getCount() {return BeanList.size();}@Overridepublic Object getItem(int position) {return BeanList.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHoder viewHolder = null;if(convertView == null){viewHolder = new ViewHoder();convertView= View.inflate(mContext,R.layout.listview_item,null);viewHolder.imageView = (ImageView) convertView.findViewById(R.id.imageView);viewHolder.tv_name = (TextView) convertView.findViewById(R.id.tv_name);viewHolder.tv_nums = (TextView) convertView.findViewById(R.id.tv_num);convertView.setTag(viewHolder);}else{viewHolder = (ViewHoder) convertView.getTag();}String []path = BeanList.get(position).getFileParent().toString().split("/");int index = path.length-1;viewHolder.tv_name.setText(path[index]);viewHolder.tv_nums.setText(BeanList.get(position).getFileNums()+"");Glide.with(mContext).load(BeanList.get(position).getFirstImage()).into(viewHolder.imageView);return convertView;}static class ViewHoder {public TextView tv_name;public TextView tv_nums;public ImageView imageView;}
}
Glide.with(mContext).load(BeanList.get(position).getFirstImage()).into(viewHolder.imageView);

这里的图片加载使用的是谷歌推荐的Glide,惊喜的发现GIF图也是可以加载的,总的来说使用起来还是蛮优雅的,一行代码搞定,Glide和Android的Picasso使用起来api惊人的相似……

ShowImageView.java

public class ShowImageActivity extends AppCompatActivity {private GridView gridView;private TextView tv_cancle;private TextView tv_complete;private HashMap<Integer, Integer> mChoicePosition = new HashMap<Integer, Integer>(); //记录选择的图片对应的下标数(GridView复用的问题)private HashMap<Integer, ImageView> mChoiceImage = new HashMap<Integer, ImageView>(); //记录选择的图片private FileBean fileBean;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_show_image);InitUI();fileBean = (FileBean) getIntent().getSerializableExtra("fileBean");gridView.setAdapter(new MyGridAdapter(fileBean, this));//点击完成执行的相应操作tv_complete.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {String AllChoiceImagePath[] =  getChoiceImage(); //获取选择的图片存放在数组中}});}private String[] getChoiceImage() {Iterator<Map.Entry<Integer, Integer>> iterator = mChoicePosition.entrySet().iterator();int index[] = new int[mChoicePosition.size()];int i=0;while(iterator.hasNext()){Map.Entry entry = (Map.Entry)iterator.next();index[i++] = (int) entry.getKey(); //根据key(position)获取图片}Arrays.sort(index); //排序String ImagePath[] = new String[mChoicePosition.size()]; //存放选择的图片的路径for (int num:index) {ImagePath[num] = fileBean.getFileParent().toString()+fileBean.getFileList()[num]; //根据选择的下标获取fileBean对象中存储的图片的路径,存放在数组中}for(String imagePath:ImagePath){Log.i("tag","ImagePath:"+imagePath);}return ImagePath;}private void InitUI() {gridView = (GridView) findViewById(R.id.gridView);tv_cancle = (TextView) findViewById(R.id.tv_cancle);tv_complete = (TextView) findViewById(R.id.tv_complete);}/*** GridView的适配器*/public class MyGridAdapter extends BaseAdapter {private FileBean fileBean;private Context mContext;private int CurrentNum = 1;public MyGridAdapter(FileBean fileBean, Context mContext) {this.fileBean = fileBean;this.mContext = mContext;}@Overridepublic int getCount() {return fileBean.getFileList().length;}@Overridepublic Object getItem(int position) {return fileBean.getFileParent() + fileBean.getFileList()[position];}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(final int position, View convertView, ViewGroup parent) {ViewHolder viewHolder = null;if (convertView == null) {convertView = View.inflate(mContext, R.layout.grid_item, null);viewHolder = new ViewHolder();viewHolder.imageViewGrid = (MyCustomImageView) convertView.findViewById(R.id.imageViewGrid);convertView.setTag(viewHolder);} else {viewHolder = (ViewHolder) convertView.getTag();}final File file = new File(fileBean.getFileParent(), fileBean.getFileList()[position]);Glide.with(mContext).load(file).into(viewHolder.imageViewGrid);final ViewHolder ViewHolder = viewHolder;viewHolder.imageViewGrid.SetOnCheckedChangeListener(new MyCustomImageView.onCheckedChangeListener() {@Overridepublic void isChecked(boolean isSelected) {//点击图片进行选择的时候调用if (CurrentNum < 10) {if (isSelected) {//将选中的图片记录到map集合中mChoicePosition.put(position, CurrentNum);mChoiceImage.put(position, ViewHolder.imageViewGrid);ViewHolder.imageViewGrid.setDrawText(CurrentNum + "");CurrentNum++;} else {Log.i("tag", "CurrentNum--:" + CurrentNum);Log.i("tag", "Position==>" + position);ChangeIndex(position);//根据选择动态改变图片对应的下标数}} else {if (isSelected) { //如果是未选中状态就将其状态置为未选中状态ViewHolder.imageViewGrid.setChecked(false);} else {ChangeIndex(position);}if (CurrentNum == 10) {Toast.makeText(ShowImageActivity.this, "最多选择9张图片", Toast.LENGTH_SHORT).show();}}if (CurrentNum == 0) CurrentNum = 1;int num = mChoicePosition.size();if(num==0){tv_complete.setText("完成");}else{tv_complete.setText("完成 "+num+"/9");}}/*** 根据选择动态改变图片对应的下标数*/private void ChangeIndex(int position) {if (mChoicePosition.containsKey(position)) {int num = mChoicePosition.get(position);Iterator iter = mChoicePosition.entrySet().iterator();while (iter.hasNext()) {Map.Entry entry = (Map.Entry) iter.next();int key = (int) entry.getKey();int val = (int) entry.getValue();Log.i("tag", "key: " + key);Log.i("tag", "value: " + val);//将比当前点击的下标大的数进行减一操作if (val > num) {val = val - 1;mChoicePosition.put(key, val);MyCustomImageView iv = (MyCustomImageView) mChoiceImage.get(key);iv.setDrawText(val + "");}}mChoicePosition.remove(position);mChoiceImage.remove(position);ViewHolder.imageViewGrid.setDrawText(CurrentNum + "");CurrentNum--;}}});if (mChoicePosition.get(position) != null) {viewHolder.imageViewGrid.setChecked(true);viewHolder.imageViewGrid.setDrawText(String.valueOf(mChoicePosition.get(position)));} else {viewHolder.imageViewGrid.setChecked(false);}return convertView;}class ViewHolder {public MyCustomImageView imageViewGrid;}}}

由于GridView的复用,这里采用Map集合的方式将选中的图片的位置的下标记录到Map集合中,然后再根据map集合中的数据将选择的那个图片对应的Index设置给ImageView,防止ImageView复用造成的界面的错乱。

FileBean.java

/*** Created by 春水碧于天 on 2017/1/17.*/public class FileBean implements Serializable{private String firstImage;//第一张图片的文件名private File fileParent; //文件的父路径private int fileNums; //文件的数量private String[] fileList;private int ChoiceImage = -1; //设置选择的图片的下标数public String getFirstImage() {return firstImage;}public void setFirstImage(String firstImage) {this.firstImage = firstImage;}public File getFileParent() {return fileParent;}public void setFileParent(File fileParent) {this.fileParent = fileParent;}public String[] getFileList() {return fileList;}public void setFileList(String[] fileList) {this.fileList = fileList;}public int getFileNums() {return fileNums;}public void setFileNums(int fileNums) {this.fileNums = fileNums;}
}

布局就不朝上面贴了,反正挺简单的。
(被有些逻辑恶心到了……期待医生的群英传,更上一层楼!!)

更多推荐

粗仿数字尾巴实现安卓图片选择器

本文发布于:2024-02-26 01:46:07,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1700957.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:尾巴   数字   选择器   图片

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!