转载请注明出处: 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),并且自带防止内存溢出功能。
    
public class MyApplication extends Application {@Overridepublic void onCreate() {super.onCreate();DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder().showImageForEmptyUri(R.drawable.empty_photo) .showImageOnFail(R.drawable.empty_photo) .cacheInMemory(true).cacheOnDisc(true).build();ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext()).defaultDisplayImageOptions(defaultOptions).discCacheSize(50 * 1024 * 1024)//.discCacheFileCount(100)//缓存一百张图片.writeDebugLogs().build();ImageLoader.getInstance().init(config);}
}
 
 二 准备主界面和需要的基础类
  1  Listadapter
public class  FridListAdapter extends BaseAdapter{private ArrayList<MyBean> mList;private LayoutInflater mInflater;private Context mContext;public FridListAdapter(Context context,ArrayList<MyBean> list) {mInflater = LayoutInflater.from(context);mContext=context;this.mList=list;}@Overridepublic int getCount() {return mList==null?0:mList.size();}@Overridepublic MyBean getItem(int position) {return mList.get(position);}@Overridepublic long getItemId(int position) {return getItem(position).id;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder;if (convertView == null) {holder = new ViewHolder();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();}final MyBean bean = 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(new DynamicGridAdapter(bean.urls, mContext));holder.gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {imageBrower(position,bean.urls);}});}else{holder.gridView.setVisibility(View.GONE);}return convertView;}private void imageBrower(int position, String[] urls) {Intent intent = new Intent(mContext, ImagePagerActivity.class);// 图片url,为了演示这里使用常量,一般从数据库中或网络中获取intent.putExtra(ImagePagerActivity.EXTRA_IMAGE_URLS, urls);intent.putExtra(ImagePagerActivity.EXTRA_IMAGE_INDEX, position);mContext.startActivity(intent);}// 优化listviewprivate static class ViewHolder {public TextView name;public ImageView avator;TextView content;NoScrollGridView gridView;}
}
  2  主界面
   实际项目中数据是数据是从服务器获取的,本次就只将图片从网络获取,
public class MainActivity extends ListActivity {public static final String TAG = "MainActivity";private FridListAdapter mAdapter;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);new LoderDataTask().execute();}class LoderDataTask extends AsyncTask<Void, Void, MessageModle> {@Overrideprotected MessageModle doInBackground(Void... params) {Gson gson = new Gson();MessageModle msg = gson.fromJson(getData(), MessageModle.class);return msg;}@Overrideprotected void onPostExecute(MessageModle result) {mAdapter = new FridListAdapter(MainActivity.this, result.list);setListAdapter(mAdapter);}}private String getData() {// 模拟网络获取数据String json = "{\"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\"]}]}";return json;}
  3 GridView的Adapter
     因为Listview的条目中包含Gridview,在这里还需要为它创建atapter
    由于adapter没太多技术含量,因此重点部分列出,在这里我们需要判断下适配的数据眼总数,微信最大数是9张,显示一张的时候,图片比较大,两张的时候稍微减少,四张的时候两列两行和两张的大小一致,其他张数的时候都是三行三列的九宫格。
@Overridepublic View getView(int position, View convertView, ViewGroup parent) {MyGridViewHolder viewHolder;if (convertView == null) {viewHolder = new MyGridViewHolder();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();}String url = getItem(position);if (getCount() == 1) {viewHolder.imageView.setLayoutParams(new android.widget.AbsListView.LayoutParams(300, 250));}if (getCount() == 2 ||getCount() == 4) {viewHolder.imageView.setLayoutParams(new android.widget.AbsListView.LayoutParams(200, 200));}ImageLoader.getInstance().displayImage(url, viewHolder.imageView);return convertView;}
   4  新建用于支持九宫格自定义的Gridview
  
public class NoScrollGridView extends GridView {public NoScrollGridView(Context context) {super(context);}public NoScrollGridView(Context context, AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int  expandSpec = 0;int  size = 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
    
public class ImagePagerActivity extends FragmentActivity {private static final String STATE_POSITION = "STATE_POSITION";public static final String EXTRA_IMAGE_INDEX = "image_index";public static final String EXTRA_IMAGE_URLS = "image_urls";private HackyViewPager mPager;private int pagerPosition;private TextView indicator;@Overridepublic void onCreate(Bundle savedInstanceState) {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);ImagePagerAdapter mAdapter = new ImagePagerAdapter(getSupportFragmentManager(), urls);mPager.setAdapter(mAdapter);indicator = (TextView) findViewById(R.id.indicator);CharSequence text = getString(R.string.viewpager_indicator, 1, mPager.getAdapter().getCount());indicator.setText(text);// 更新下标mPager.setOnPageChangeListener(new OnPageChangeListener() {@Overridepublic void onPageScrollStateChanged(int arg0) {}@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {}@Overridepublic void onPageSelected(int arg0) {CharSequence text = getString(R.string.viewpager_indicator,arg0 + 1, mPager.getAdapter().getCount());indicator.setText(text);}});if (savedInstanceState != null) {pagerPosition = savedInstanceState.getInt(STATE_POSITION);}mPager.setCurrentItem(pagerPosition);}@Overridepublic void onSaveInstanceState(Bundle outState) {outState.putInt(STATE_POSITION, mPager.getCurrentItem());}private class ImagePagerAdapter extends FragmentStatePagerAdapter {public String[] fileList;public ImagePagerAdapter(FragmentManager fm, String[] fileList) {super(fm);this.fileList = fileList;}@Overridepublic int getCount() {return fileList == null ? 0 : fileList.length;}@Overridepublic Fragment getItem(int position) {String url = fileList[position];return ImageDetailFragment.newInstance(url);}}
2 查看大图界面
  
    转载请注明出处: http://blog.csdn.net/sk719887916/article/details/40348873 作者skay:
public class ImageDetailFragment extends Fragment {private String mImageUrl;private ImageView mImageView;private ProgressBar progressBar;private PhotoViewAttacher mAttacher;public static ImageDetailFragment newInstance(String imageUrl) {final ImageDetailFragment f = new ImageDetailFragment();final Bundle args = new Bundle();args.putString("url", imageUrl);f.setArguments(args);return f;}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mImageUrl = getArguments() != null ? getArguments().getString("url") : null;}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {final View v = inflater.inflate(R.layout.image_detail_fragment, container, false);mImageView = (ImageView) v.findViewById(R.id.image);mAttacher = new PhotoViewAttacher(mImageView);mAttacher.setOnPhotoTapListener(new OnPhotoTapListener() {@Overridepublic void onPhotoTap(View arg0, float arg1, float arg2) {getActivity().finish();}});progressBar = (ProgressBar) v.findViewById(R.id.loading);return v;}@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);ImageLoader.getInstance().displayImage(mImageUrl, mImageView, new SimpleImageLoadingListener() {@Overridepublic void onLoadingStarted(String imageUri, View view) {progressBar.setVisibility(View.VISIBLE);}@Overridepublic void onLoadingFailed(String imageUri, View view, FailReason failReason) {String message = null;switch (failReason.getType()) {case IO_ERROR:message = "下载错误";break;case DECODING_ERROR:message = "图片无法显示";break;case NETWORK_DENIED:message = "网络有问题,无法下载";break;case OUT_OF_MEMORY:message = "图片太大无法显示";break;case UNKNOWN:message = "未知的错误";break;}Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show();progressBar.setVisibility(View.GONE);}@Overridepublic void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {progressBar.setVisibility(View.GONE);mAttacher.update();}});}
     四  界面的头像圆形
      圆形头像用主流的circleimageview.jar的框架,但是有兴趣的朋友也可以自定义Imagview采用重写onDrawI()画圆形的方式将bitmap画上去,由于此demo整体功能较复杂,因此使用第三方的东西,ListView条目布局如下:
    
<RelativeLayout xmlns: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

   
												

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

  1. android com.mylhyl,Android 高仿微信朋友圈拍照上传功能

    模仿微信朋友圈发布动态,输入文字支持文字多少高度自增,有一个最小输入框高度,输入文字有限制,不过这些都很easy! 1. photopicker的使用 这是一个支持选择多张图片,点击图片放大,图片之间 ...

  2. android 微信高仿,Android 高仿微信朋友圈拍照上传功能

    模仿微信朋友圈发布动态,输入文字支持文字多少高度自增,有一个最小输入框高度,输入文字有限制,不过这些都很easy! 1. PhotoPicker的使用 这是一个支持选择多张图片,点击图片放大,图片之间 ...

  3. Android 实现仿微信朋友圈九宫格图片+NineGridView+ImageWatcher(图片查看:1.预览,2.拖动,3.放大,4.左右滑动,5.长按保存到手机)的功能

    一.测试 实现: 二.添加依赖包: implementation 'androidx.appcompat:appcompat:1.1.0'implementation 'androidx.recycl ...

  4. 仿微信朋友圈动态列表

    仿微信朋友圈动态列表,如下图: Demo下载

  5. Android实现仿微信朋友圈发布动态(拍照、图库选择、照片压缩、显示、保存、缩略图、点击缩略图删除对应文件等)

    原址: http://blog.csdn.net/zhang3776813/article/details/52092591 /*** 仿微信朋友圈发布动态* 拍照或图库选择 * 压缩图片并保存**/ ...

  6. Android实现仿微信朋友圈发布动态(拍照、图库选择、照片压缩、显示、保存、缩略图、点击缩略图删除对应文件等)附源码

             原创作品,转载请注明出处:http://blog.csdn.net/zhang3776813/article/details/52092591 最近项目需求中要用到类似微信朋友圈发布 ...

  7. android 打开微信好友动态图片,Android GridView仿微信朋友圈显示图片

    最近项目要求上传多图并且多图显示,而且要规则的显示,就像微信朋友圈的图片显示一样. 利用GridView再适合不过了,GridView可以动态加载图片的数量,而且还比较规律,下面说一下自己的思路: 1 ...

  8. 修改源码自定义SwipeRefreshLayout样式——高仿微信朋友圈下拉刷新

    上一篇文章里把SwipeRefreshLayout的原理简单过了一下,大致了解了其工作原理,不熟悉的可以去看一下:http://blog.csdn.net/u011443509/article/det ...

  9. android开发--仿微信朋友圈界面

    话不多说,先来看两张效果图 看图片效果还凑合,就是"朋友圈"三个字和头像的动画过渡效果和微信朋友圈的实际效果还是有点差距,可以的话以后慢慢再优化吧,这里贴出相关的代码,可能部分代码 ...

最新文章

  1. asprise java_使用asprise进行图片验证码识别
  2. [ios][swift]UIButton
  3. java的object有show_Java中 Object的方法
  4. adf4351使用_使用ADF BC管理保存点
  5. react+redux+node报错Tapable.plugin is deprecated. Use new API on `.h ooks` instead
  6. VisualStudio移动开发(C#、VB.NET)Smobiler开发平台——BarcodeView控件的使用方式,.Net移动开发...
  7. 代码实现:输入某年某月某日,判断这一天是这一年的第几天?
  8. 计算机科学素养大赛,第六届全国大学生计算机应用能力与信息素养大赛圆满结束...
  9. ActivityManager: Warning: Activity not started,...
  10. docker compose入门
  11. 数据库常用的sql语句大全--sql
  12. MySql服务无法连接
  13. 视频教程-【曾贤志】Excel函数视频教程-Office/WPS
  14. delphi 发送html邮件,delphi – 以HTML格式发送电子邮件
  15. Maximo学习:创建表和应用程序
  16. 下载神器aria2和他的客户端Persepolis
  17. 第五章 Spring Boot的数据库编程
  18. 专为医疗领域打造!飞凌嵌入式新一代FDU显控一体机发布
  19. 油田系统三维布局可视化解决方案
  20. ElasticSearch、ES、es使用教程

热门文章

  1. IP和MNC地址协议
  2. 小南迎宾机器人使用说明
  3. 基于EasyNVR网络摄像机无插件直播流媒体服务器实现文字滤镜处理功能
  4. 使用python turtle库13行代码实现奥运五环
  5. linux的dns怎么配置正向区域文件,linux系统下部署DNS正向解析
  6. 新媒体运营:如何策划出一场完整高效的活动方案?(一) | 黎想
  7. 新媒体数据分析:新媒体运营主要做什么?
  8. OAK 3D人工智能相机和RealSense系列相机的对比
  9. 这才是图扑数字孪生污水处理厂该有的样子
  10. 17-7PH不锈钢(SUS 631)用于哪些领域