国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android 高仿微信朋友圈動態(tài)支持雙擊手勢放大并滑動查看圖片效果

2019-12-12 04:01:07
字體:
供稿:網(wǎng)友

最近參與了開發(fā)一款旅行APP,其中包含實時聊天和動態(tài)評論功能,終于耗時幾個月幾個伙伴完成了,今天就小結(jié)一下至于實時聊天功能如果用戶不多的情況可以scoket實現(xiàn),如果用戶萬級就可以采用開源的smack + opnefile實現(xiàn),也可以用mina開源+XMMP,至于怎么搭建和實現(xiàn),估計目前github上一搜一大把,至于即時通訊怕誤人子弟,暫且不做介紹,現(xiàn)就把實現(xiàn)的一個微信朋友圈的小功能介紹一下。

   先上效果圖:

一拿到主流的UI需求,大致分析下,需要我ListView嵌套Gridview,而gridView的行數(shù)也和圖片總數(shù)有關(guān)系,因此通過個數(shù)我們可以動態(tài)設(shè)置條目的寬高,而點擊圖片放大我們可一跳轉(zhuǎn)到另一界面,圖片左右滑動可以用viewpager實現(xiàn),雙擊圖片放大和手指縮放圖片也可以用就監(jiān)聽手勢進行不斷放大,對于安卓事件不熟悉的朋友可以直接使用一個著名的photoVIew開源項目,支持手勢縮放圖片和滑動圖片實現(xiàn)畫廊功能,也很好的解決了內(nèi)存溢出問題。

      一 配置ImageLoader       

       本項目中加載網(wǎng)絡(luò)圖片我就直接使用imageLoader,但建議還是去看下源碼,因為開源項目本身自帶緩存機制,有很好的緩存技巧,有很多東西值得我們借鑒。其不僅可以加載本地圖片(文件path),也支持加載網(wǎng)絡(luò)圖片(url),并且自帶防止內(nèi)存溢出功能。

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);   } } 

 二 準備主界面和需要的基礎(chǔ)類

  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);     //加載網(wǎng)絡(luò)圖片     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,為了演示這里使用常量,一般從數(shù)據(jù)庫中或網(wǎng)絡(luò)中獲取     intent.putExtra(ImagePagerActivity.EXTRA_IMAGE_URLS, urls);     intent.putExtra(ImagePagerActivity.EXTRA_IMAGE_INDEX, position);     mContext.startActivity(intent);   }   // 優(yōu)化listview   private static class ViewHolder {     public TextView name;     public ImageView avator;     TextView content;     NoScrollGridView gridView;   } }

  2  主界面

   實際項目中數(shù)據(jù)是數(shù)據(jù)是從服務(wù)器獲取的,本次就只將圖片從網(wǎng)絡(luò)獲取,

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() {     // 模擬網(wǎng)絡(luò)獲取數(shù)據(jù)     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,在這里還需要為它創(chuàng)建atapter

    由于adapter沒太多技術(shù)含量,因此重點部分列出,在這里我們需要判斷下適配的數(shù)據(jù)眼總數(shù),微信最大數(shù)是9張,顯示一張的時候,圖片比較大,兩張的時候稍微減少,四張的時候兩列兩行和兩張的大小一致,其他張數(shù)的時候都是三行三列的九宮格。

@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 );   } } 

三 點擊圖片后的基礎(chǔ)類

   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 = "網(wǎng)絡(luò)有問題,無法下載";           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加入到工程中,

   總結(jié)一下實現(xiàn)以上功能我們使用了第三的imagloader,支持手勢縮放的PhotoView,圓形圖像的circleimageView,熟悉安卓view繪制機制加載過程,事件傳遞和分發(fā)的朋友是不需要第三方開源項目的支持的,但是對于入門不久的同學,學會怎樣使用開源框架就可以,但是想要提高開源項目的的核心還是需要了解的,歡迎閱讀

  運行效果圖:

 

  有興趣的朋友建議閱讀下:

     安卓事件機制(一)和上篇關(guān)于View的博文。謝謝交流和分享。

demo源碼下載地址:https://github.com/Tamicer/CHatMomentDemo

以上所述是小編給大家介紹的Android 高仿微信朋友圈動態(tài)支持雙擊手勢放大并滑動查看圖片效果,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網(wǎng)網(wǎng)站的支持!

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 江城| 方山县| 皮山县| 龙海市| 武强县| 页游| 遂平县| 阿城市| 平武县| 应城市| 本溪| 富阳市| 瓦房店市| 都昌县| 秭归县| 西华县| 农安县| 柳州市| 曲周县| 清水县| 杨浦区| 万山特区| 遂川县| 哈密市| 肇源县| 闽清县| 自贡市| 甘泉县| 乌苏市| 布尔津县| 台安县| 永和县| 本溪市| 容城县| 延长县| 浑源县| 张家界市| 赫章县| 英吉沙县| 英吉沙县| 久治县|