软件编程
位置:首页>> 软件编程>> Android编程>> Android * 微信朋友圈动态支持双击手势放大并滑动查看图片效果

Android * 微信朋友圈动态支持双击手势放大并滑动查看图片效果

作者:夜未央_Zz  发布时间:2021-08-21 21:16:40 

标签:android,双击手势,微信朋友圈

最近参与了开发一款旅行APP,其中包含实时聊天和动态评论功能,终于耗时几个月几个伙伴完成了,今天就小结一下至于实时聊天功能如果用户不多的情况可以scoket实现,如果用户万级就可以采用开源的smack + opnefile实现,也可以用mina开源+XMMP,至于怎么搭建和实现,估计目前github上一搜一大把,至于即时通讯怕误人子弟,暂且不做介绍,现就把实现的一个微信朋友圈的小功能介绍一下。

   先上效果图:

Android  * 微信朋友圈动态支持双击手势放大并滑动查看图片效果

一拿到主流的UI需求,大致分析下,需要我ListView嵌套Gridview,而gridView的行数也和图片总数有关系,因此通过个数我们可以动态设置条目的宽高,而点击图片放大我们可一跳转到另一界面,图片左右滑动可以用viewpager实现,双击图片放大和手指缩放图片也可以用就监听手势进行不断放大,对于安卓事件不熟悉的朋友可以直接使用一个著名的photoVIew开源项目,支持手势缩放图片和滑动图片实现画廊功能,也很好的解决了内存溢出问题。

      一 配置ImageLoader       

       本项目中加载网络图片我就直接使用imageLoader,但建议还是去看下源码,因为开源项目本身自带缓存机制,有很好的缓存技巧,有很多东西值得我们借鉴。其不仅可以加载本地图片(文件path),也支持加载网络图片(url),并且自带防止内存溢出功能。


public class MyApplication extends Application {
 @Override
 public 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;
 }
 @Override
 public int getCount() {
   return mList==null?0:mList.size();
 }
 @Override
 public MyBean getItem(int position) {
   return mList.get(position);
 }
 @Override
 public long getItemId(int position) {
   return getItem(position).id;
 }
 @Override
 public 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() {
       @Override
       public 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);
 }
 // 优化listview
 private 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;
 @Override
 public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);
   new LoderDataTask().execute();
 }
 class LoderDataTask extends AsyncTask<Void, Void, MessageModle> {
   @Override
   protected MessageModle doInBackground(Void... params) {
     Gson gson = new Gson();
     MessageModle msg = gson.fromJson(getData(), MessageModle.class);
     return msg;
   }
   @Override
   protected 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张,显示一张的时候,图片比较大,两张的时候稍微减少,四张的时候两列两行和两张的大小一致,其他张数的时候都是三行三列的九宫格。


@Override
 public 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);
 }
 @Override
 protected 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;
 @Override
 public 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() {
     @Override
     public void onPageScrollStateChanged(int arg0) {
     }
     @Override
     public void onPageScrolled(int arg0, float arg1, int arg2) {
     }
     @Override
     public 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);
 }
 @Override
 public 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;
   }
   @Override
   public int getCount() {
     return fileList == null ? 0 : fileList.length;
   }
   @Override
   public Fragment getItem(int position) {
     String url = fileList[position];
     return ImageDetailFragment.newInstance(url);
   }
 }

2 查看大图界面


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;
 }
 @Override
 public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   mImageUrl = getArguments() != null ? getArguments().getString("url") : null;
 }
 @Override
 public 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() {
     @Override
     public void onPhotoTap(View arg0, float arg1, float arg2) {
       getActivity().finish();
     }
   });
   progressBar = (ProgressBar) v.findViewById(R.id.loading);
   return v;
 }
 @Override
 public void onActivityCreated(Bundle savedInstanceState) {
   super.onActivityCreated(savedInstanceState);
   ImageLoader.getInstance().displayImage(mImageUrl, mImageView, new SimpleImageLoadingListener() {
     @Override
     public void onLoadingStarted(String imageUri, View view) {
       progressBar.setVisibility(View.VISIBLE);
     }
     @Override
     public 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);
     }
     @Override
     public 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.CircleImageView
   android:id="@+id/avator"
   android:layout_width="48dp"
   android:layout_height="48dp"
   android:src="@drawable/empty_photo" />
 <TextView
   android: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" />
 <TextView
   android: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.NoScrollGridView
   android: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绘制机制加载过程,事件传递和分发的朋友是不需要第三方开源项目的支持的,但是对于入门不久的同学,学会怎样使用开源框架就可以,但是想要提高开源项目的的核心还是需要了解的,欢迎阅读

  运行效果图:

Android  * 微信朋友圈动态支持双击手势放大并滑动查看图片效果 

  有兴趣的朋友建议阅读下:

     安卓事件机制(一)和上篇关于View的博文。谢谢交流和分享。

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

以上所述是小编给大家介绍的Android * 微信朋友圈动态支持双击手势放大并滑动查看图片效果网站的支持!

来源:http://blog.csdn.net/qq944639839/article/details/54572480

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com