您的位置:首页 > 移动开发 > 微信开发

Android 高仿微信朋友圈动态, 支持双击手势放大并滑动查看图片。

2014-10-21 18:00 405 查看
转载请注明出处:'target='_blank'>http://blog.csdn.net/sk719887916/article/details/40348873作者skay:
最近参与了开发一款旅行APP,其中包含实时聊天和动态评论功能,终于耗时几个月几个伙伴完成了,今天就小结一下至于实时聊天功能如果用户不多的情况可以scoket实现,如果用户万级就可以采用开源的smack+opnefile实现,也可以用mina开源+XMMP,至于怎么搭建和实现,估计目前github上一搜一大把,至于即时通讯怕误人子弟,暂且不做介绍,现就把实现的一个微信朋友圈的小功能介绍一下。
先上效果图:

u
一拿到主流的UI需求,大致分析下,需要我ListView嵌套Gridview,而gridView的行数也和图片总数有关系,因此通过个数我们可以动态设置条目的宽高,而点击图片放大我们可一跳转到另一界面,图片左右滑动可以用viewpager实现,双击图片放大和手指缩放图片也可以用就监听手势进行不断放大,对于安卓事件不熟悉的朋友可以直接使用一个著名的photoVIew开源项目,支持手势缩放图片和滑动图片实现画廊功能,也很好的解决了内存溢出问题。
一配置ImageLoader
本项目中加载网络图片我就直接使用imageLoader,但建议还是去看下源码,因为开源项目本身自带缓存机制,有很好的缓存技巧,有很多东西值得我们借鉴。其不仅可以加载本地图片(文件path),也支持加载网络图片(url),并且自带防止内存溢出功能。
publicclassMyApplicationextendsApplication{@OverridepublicvoidonCreate(){super.onCreate();DisplayImageOptionsdefaultOptions=newDisplayImageOptions.Builder().showImageForEmptyUri(R.drawable.empty_photo).showImageOnFail(R.drawable.empty_photo).cacheInMemory(true).cacheOnDisc(true).build();ImageLoaderConfigurationconfig=newImageLoaderConfiguration.Builder(getApplicationContext()).defaultDisplayImageOptions(defaultOptions).discCacheSize(50*1024*1024)//.discCacheFileCount(100)//缓存一百张图片.writeDebugLogs().build();ImageLoader.getInstance().init(config);}}
二准备主界面和需要的基础类
1ListadapterpublicclassFridListAdapterextendsBaseAdapter{privateArrayList<MyBean>mList;privateLayoutInflatermInflater;privateContextmContext;publicFridListAdapter(Contextcontext,ArrayList<MyBean>list){mInflater=LayoutInflater.from(context);mContext=context;this.mList=list;}@OverridepublicintgetCount(){returnmList==null?0:mList.size();}@OverridepublicMyBeangetItem(intposition){returnmList.get(position);}@OverridepubliclonggetItemId(intposition){returngetItem(position).id;}@OverridepublicViewgetView(intposition,ViewconvertView,ViewGroupparent){ViewHolderholder;if(convertView==null){holder=newViewHolder();convertView=mInflater.inflate(R.layout.list_item,null);holder.avator=(ImageView)convertView.findViewById(R.id.avator);holder.name=(TextView)convertView.findViewById(R.id.name);holder.content=(TextView)convertView.findViewById(R.id.content);holder.gridView=(NoScrollGridView)convertView.findViewById(R.id.gridView);convertView.setTag(holder);}else{holder=(ViewHolder)convertView.getTag();}finalMyBeanbean=getItem(position);//加载网络图片ImageLoader.getInstance().displayImage(bean.avator,holder.avator);holder.name.setText(bean.name);holder.content.setText(bean.content);if(bean.urls!=null&&bean.urls.length>0){holder.gridView.setVisibility(View.VISIBLE);holder.gridView.setAdapter(newDynamicGridAdapter(bean.urls,mContext));holder.gridView.setOnItemClickListener(newAdapterView.OnItemClickListener(){@OverridepublicvoidonItemClick(AdapterView<?>parent,Viewview,intposition,longid){imageBrower(position,bean.urls);}});}else{holder.gridView.setVisibility(View.GONE);}returnconvertView;}privatevoidimageBrower(intposition,String[]urls){Intentintent=newIntent(mContext,ImagePagerActivity.class);//图片url,为了演示这里使用常量,一般从数据库中或网络中获取intent.putExtra(ImagePagerActivity.EXTRA_IMAGE_URLS,urls);intent.putExtra(ImagePagerActivity.EXTRA_IMAGE_INDEX,position);mContext.startActivity(intent);}//优化listviewprivatestaticclassViewHolder{publicTextViewname;publicImageViewavator;TextViewcontent;NoScrollGridViewgridView;}}
2主界面
实际项目中数据是数据是从服务器获取的,本次就只将图片从网络获取,publicclassMainActivityextendsListActivity{publicstaticfinalStringTAG="MainActivity";privateFridListAdaptermAdapter;@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);newLoderDataTask().execute();}classLoderDataTaskextendsAsyncTask<Void,Void,MessageModle>{@OverrideprotectedMessageModledoInBackground(Void...params){Gsongson=newGson();MessageModlemsg=gson.fromJson(getData(),MessageModle.class);returnmsg;}@OverrideprotectedvoidonPostExecute(MessageModleresult){mAdapter=newFridListAdapter(MainActivity.this,result.list);setListAdapter(mAdapter);}}privateStringgetData(){//模拟网络获取数据Stringjson="{\"code\":200,\"msg\":\"ok\",list:["+"{\"id\":110,\"avator\":\"http://img0.bdstatic.com/img/image/shouye/leimu/mingxing.jpg\",\"name\":\"赵薇\",\"content\":\"今天不开心!\",\"urls\":[]},"+"{\"id\":111,\"avator\":\"http://image.cnwest.com/attachement/jpg/site1/20110507/001372d8a36f0f2f4c953a.jpg\",\"name\":\"李晨\",\"content\":\"我们\","+"\"urls\":[\"http://guangdong.sinaimg.cn/2015/0530/U11307P693DT20150530094310.jpg\"]},"+"{\"id\":114,\"avator\":\"http://img.hexun.com/2009-05-01/117287830.jpg\",\"name\":\"小马哥\",\"content\":\"今天淘宝了吗\",\"urls\":["+"\"http://g.hiphotos.bdimg.com/album/s%3D680%3Bq%3D90/sign=ccd33b46d53f8794d7ff4b26e2207fc9/0d338744ebf81a4c0f993437d62a6059242da6a1.jpg\","+"\"http://f.hiphotos.bdimg.com/album/s%3D680%3Bq%3D90/sign=6b62f61bac6eddc422e7b7f309e0c7c0/6159252dd42a2834510deef55ab5c9ea14cebfa1.jpg\","+"\"http://g.hiphotos.bdimg.com/album/s%3D680%3Bq%3D90/sign=e58fb67bc8ea15ce45eee301863b4bce/a5c27d1ed21b0ef4fd6140a0dcc451da80cb3e47.jpg\","+"\"http://c.hiphotos.bdimg.com/album/s%3D680%3Bq%3D90/sign=cdab1512d000baa1be2c44b3772bc82f/91529822720e0cf3855c96050b46f21fbf09aaa1.jpg\"]},"+"{\"id\":112,\"avator\":\"http://img3.yxlady.com/yl/UploadFiles_5361/20150528/20150528050208705.jpg\",\"name\":\"邓超\",\"content\":\"奔跑吧兄弟!欢迎收看!\",\"urls\":[\"http://upload.cbg.cn/2015/0305/1425518659246.jpg\","+"\"http://www.people.com.cn/mediafile/pic/20150619/30/4179219540177204330.jpg\"]},"+"{\"id\":113,\"avator\":\"http://img4.imgtn.bdimg.com/it/u=945108765,1070109457&fm=21&gp=0.jpg\",\"name\":\"奥巴马\",\"content\":\"holle\",\"urls\":[\"http://f.hiphotos.bdimg.com/album/s%3D680%3Bq%3D90/sign=6b62f61bac6eddc422e7b7f309e0c7c0/6159252dd42a2834510deef55ab5c9ea14cebfa1.jpg\",\"http://g.hiphotos.bdimg.com/album/s%3D680%3Bq%3D90/sign=e58fb67bc8ea15ce45eee301863b4bce/a5c27d1ed21b0ef4fd6140a0dcc451da80cb3e47.jpg\",\"http://c.hiphotos.bdimg.com/album/s%3D680%3Bq%3D90/sign=cdab1512d000baa1be2c44b3772bc82f/91529822720e0cf3855c96050b46f21fbf09aaa1.jpg\"]}]}";returnjson;}
3GridView的Adapter
因为Listview的条目中包含Gridview,在这里还需要为它创建atapter
由于adapter没太多技术含量,因此重点部分列出,在这里我们需要判断下适配的数据眼总数,微信最大数是9张,显示一张的时候,图片比较大,两张的时候稍微减少,四张的时候两列两行和两张的大小一致,其他张数的时候都是三行三列的九宫格。
@OverridepublicViewgetView(intposition,ViewconvertView,ViewGroupparent){MyGridViewHolderviewHolder;if(convertView==null){viewHolder=newMyGridViewHolder();convertView=mLayoutInflater.inflate(R.layout.gridview_item,parent,false);viewHolder.imageView=(ImageView)convertView.findViewById(R.id.album_image);convertView.setTag(viewHolder);}else{viewHolder=(MyGridViewHolder)convertView.getTag();}Stringurl=getItem(position);if(getCount()==1){viewHolder.imageView.setLayoutParams(newandroid.widget.AbsListView.LayoutParams(300,250));}if(getCount()==2||getCount()==4){viewHolder.imageView.setLayoutParams(newandroid.widget.AbsListView.LayoutParams(200,200));}ImageLoader.getInstance().displayImage(url,viewHolder.imageView);returnconvertView;}4新建用于支持九宫格自定义的Gridview[/code]
publicclassNoScrollGridViewextendsGridView{publicNoScrollGridView(Contextcontext){super(context);}publicNoScrollGridView(Contextcontext,AttributeSetattrs){super(context,attrs);}@OverrideprotectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){intexpandSpec=0;intsize=getAdapter().getCount();if(size==1){setNumColumns(1);}if(size==2||size==4){setNumColumns(2);}else{setNumColumns(3);}expandSpec=MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE>>2,MeasureSpec.AT_MOST);super.onMeasure(widthMeasureSpec,expandSpec);}}
三点击图片后的基础类
1建立大图查看器viewpaer
publicclassImagePagerActivityextendsFragmentActivity{privatestaticfinalStringSTATE_POSITION="STATE_POSITION";publicstaticfinalStringEXTRA_IMAGE_INDEX="image_index";publicstaticfinalStringEXTRA_IMAGE_URLS="image_urls";privateHackyViewPagermPager;privateintpagerPosition;privateTextViewindicator;@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.image_detail_pager);pagerPosition=getIntent().getIntExtra(EXTRA_IMAGE_INDEX,0);String[]urls=getIntent().getStringArrayExtra(EXTRA_IMAGE_URLS);mPager=(HackyViewPager)findViewById(R.id.pager);ImagePagerAdaptermAdapter=newImagePagerAdapter(getSupportFragmentManager(),urls);mPager.setAdapter(mAdapter);indicator=(TextView)findViewById(R.id.indicator);CharSequencetext=getString(R.string.viewpager_indicator,1,mPager.getAdapter().getCount());indicator.setText(text);//更新下标mPager.setOnPageChangeListener(newOnPageChangeListener(){@OverridepublicvoidonPageScrollStateChanged(intarg0){}@OverridepublicvoidonPageScrolled(intarg0,floatarg1,intarg2){}@OverridepublicvoidonPageSelected(intarg0){CharSequencetext=getString(R.string.viewpager_indicator,arg0+1,mPager.getAdapter().getCount());indicator.setText(text);}});if(savedInstanceState!=null){pagerPosition=savedInstanceState.getInt(STATE_POSITION);}mPager.setCurrentItem(pagerPosition);}@OverridepublicvoidonSaveInstanceState(BundleoutState){outState.putInt(STATE_POSITION,mPager.getCurrentItem());}privateclassImagePagerAdapterextendsFragmentStatePagerAdapter{publicString[]fileList;publicImagePagerAdapter(FragmentManagerfm,String[]fileList){super(fm);this.fileList=fileList;}@OverridepublicintgetCount(){returnfileList==null?0:fileList.length;}@OverridepublicFragmentgetItem(intposition){Stringurl=fileList[position];returnImageDetailFragment.newInstance(url);}}
2查看大图界面
转载请注明出处:'target='_blank'>http://blog.csdn.net/sk719887916/article/details/40348873作者skay:
publicclassImageDetailFragmentextendsFragment{privateStringmImageUrl;privateImageViewmImageView;privateProgressBarprogressBar;privatePhotoViewAttachermAttacher;publicstaticImageDetailFragmentnewInstance(StringimageUrl){finalImageDetailFragmentf=newImageDetailFragment();finalBundleargs=newBundle();args.putString("url",imageUrl);f.setArguments(args);returnf;}@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);mImageUrl=getArguments()!=null?getArguments().getString("url"):null;}@OverridepublicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){finalViewv=inflater.inflate(R.layout.image_detail_fragment,container,false);mImageView=(ImageView)v.findViewById(R.id.image);mAttacher=newPhotoViewAttacher(mImageView);mAttacher.setOnPhotoTapListener(newOnPhotoTapListener(){@OverridepublicvoidonPhotoTap(Viewarg0,floatarg1,floatarg2){getActivity().finish();}});progressBar=(ProgressBar)v.findViewById(R.id.loading);returnv;}@OverridepublicvoidonActivityCreated(BundlesavedInstanceState){super.onActivityCreated(savedInstanceState);ImageLoader.getInstance().displayImage(mImageUrl,mImageView,newSimpleImageLoadingListener(){@OverridepublicvoidonLoadingStarted(StringimageUri,Viewview){progressBar.setVisibility(View.VISIBLE);}@OverridepublicvoidonLoadingFailed(StringimageUri,Viewview,FailReasonfailReason){Stringmessage=null;switch(failReason.getType()){caseIO_ERROR:message="下载错误";break;caseDECODING_ERROR:message="图片无法显示";break;caseNETWORK_DENIED:message="网络有问题,无法下载";break;caseOUT_OF_MEMORY:message="图片太大无法显示";break;caseUNKNOWN:message="未知的错误";break;}Toast.makeText(getActivity(),message,Toast.LENGTH_SHORT).show();progressBar.setVisibility(View.GONE);}@OverridepublicvoidonLoadingComplete(StringimageUri,Viewview,BitmaploadedImage){progressBar.setVisibility(View.GONE);mAttacher.update();}});}
四界面的头像圆形
圆形头像用主流的circleimageview.jar的框架,但是有兴趣的朋友也可以自定义Imagview采用重写onDrawI()画圆形的方式将bitmap画上去,由于此demo整体功能较复杂,因此使用第三方的东西,ListView条目布局如下:
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="6dp"><de.hdodenhof.circleimageview.CircleImageViewandroid:id="@+id/avator"android:layout_width="48dp"android:layout_height="48dp"android:src="@drawable/empty_photo"/><TextViewandroid:id="@+id/name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10dp"android:layout_toRightOf="@id/avator"android:textColor="#576B95"android:textSize="16sp"android:text="name"/><TextViewandroid:id="@+id/content"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_below="@+id/name"android:layout_marginLeft="10dp"android:textSize="12sp"android:layout_toRightOf="@id/avator"android:text="content"/><com.loveplusplus.demo.image.NoScrollGridViewandroid:id="@+id/gridView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:paddingTop="5dp"android:layout_below="@id/content"android:layout_marginLeft="10dp"android:layout_toRightOf="@id/avator"android:horizontalSpacing="1dp"android:numColumns="3"android:visibility="gone"android:verticalSpacing="1dp"/></RelativeLayout>
接下来我们还需要将主流的photoView.jar加入到工程中,
总结一下实现以上功能我们使用了第三的imagloader,支持手势缩放的PhotoView,圆形图像的circleimageView,熟悉安卓view绘制机制加载过程,事件传递和分发的朋友是不需要第三方开源项目的支持的,但是对于入门不久的同学,学会怎样使用开源框架就可以,但是想要提高开源项目的的核心还是需要了解的,欢迎阅读
运行效果图:
有兴趣的朋友建议阅读下:
安卓事件机制(一)和上篇关于View的博文。谢谢交流和分享。

demo源码下载地址:https://github.com/Tamicer/CHatMomentDemo


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐