Android仿微信朋友圈图片查看器

再看文章之前,希望大家先打开自己的微信点到朋友圈中去,仔细观察是不是发现朋友圈里的有个“九宫格”的图片区域,点击图片又会跳到图片的详细查看页面,并且支持图片的滑动和缩放?这个功能是不是很常用呢?!那么我今天正好做了这个Demo,下面为大家讲解一下。首先按照惯例先看一下效果图吧,尤其不会录制gif动画(哎~没办法,模拟器不支持多点触控,刚好我的手机又没有Root,不能录屏,悲催啊,大家见谅,想要看真实效果的话,烦请移到文章最下方转载文章中进行源码下载,点击下载源码,运行后再看效果哈~~),这里先就拿几张静态的图片顶替一下好了。见谅!

效果嘛,将就着看吧!实在看不明白就想想微信朋友圈,或者拖到下方,点击下载源码!这里,首先分析一下主界面吧,布局都是很简单的,主界面仅仅就是一个ListView的控件,ListView的Item上值得注意的是,Item上包含了一个GridView,这个GridView呗用作实现“九宫格”的效果,主界面布局就是一个ListView,这里不说了,我们先来看看ListView的Item的布局吧,以下是item_list.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:paddingBottom="5dp"
 android:paddingTop="5dp" > 

 <ImageView
 android:id="@+id/iv_avatar"
 android:layout_width="50dp"
 android:layout_height="50dp"
 android:background="@drawable/ic_launcher"
 android:scaleType="centerCrop" /> 

 <TextView
 android:id="@+id/tv_title"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_marginLeft="5dp"
 android:layout_toRightOf="@id/iv_avatar"
 android:text="爷,今天心情好!"
 android:textSize="16sp" /> 

 <TextView
 android:id="@+id/tv_content"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_below="@+id/tv_title"
 android:layout_marginLeft="5dp"
 android:layout_marginTop="3dp"
 android:layout_toRightOf="@id/iv_avatar"
 android:text="今天又是雾霾!"
 android:textSize="16sp" /> 

 <com.example.imagedemo.NoScrollGridView
 android:id="@+id/gridview"
 android:layout_width="220dp"
 android:layout_height="wrap_content"
 android:layout_below="@id/tv_content"
 android:layout_marginLeft="5dp"
 android:layout_marginTop="3dp"
 android:layout_toRightOf="@id/iv_avatar"
 android:columnWidth="70dp"
 android:gravity="center"
 android:horizontalSpacing="2.5dp"
 android:numColumns="3"
 android:stretchMode="columnWidth"
 android:verticalSpacing="2.5dp" /> 

</RelativeLayout>

好了,大家看到了,布局也是极其简单的,但是有个问题就是ListView嵌套进了GridView,那么就会出现一个问题,导致GridView显示的不全,那么该怎么解决这个问题呢?其实也简单,就是重写一个GridView,测量一下GridView的高度,再设置上去。具体解决方案请看上篇博文ListView嵌套GridView显示不全解决方法或者源码,如下NoScrollGridView.java

package com.example.imagedemo; 

import android.content.Context;
import android.util.AttributeSet;
import android.widget.GridView; 

/**
 * 自定义的“九宫格”——用在显示帖子详情的图片集合 解决的问题:GridView显示不全,只显示了一行的图片,比较奇怪,尝试重写GridView来解决
 *
 * @author lichao
 * @since 2014-10-16 16:41
 *
 */
public class NoScrollGridView extends GridView { 

 public NoScrollGridView(Context context) {
 super(context);
 // TODO Auto-generated constructor stub
 } 

 public NoScrollGridView(Context context, AttributeSet attrs) {
 super(context, attrs);
 // TODO Auto-generated constructor stub
 } 

 public NoScrollGridView(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);
 // TODO Auto-generated constructor stub
 } 

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 // TODO Auto-generated method stub
 int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
  MeasureSpec.AT_MOST);
 super.onMeasure(widthMeasureSpec, expandSpec);
 } 

}

接下来看看ListView上面Item的实体是什么样的数据结构,这就显得非常简单了。

public class ItemEntity {
 private String avatar; // 用户头像URL
 private String title; // 标题
 private String content; // 内容
 private ArrayList<String> imageUrls; // 九宫格图片的URL集合 

 public ItemEntity(String avatar, String title, String content,
  ArrayList<String> imageUrls) {
 super();
 this.avatar = avatar;
 this.title = title;
 this.content = content;
 this.imageUrls = imageUrls;
 }
 ...
}

好了,有了ListView,那么不可避免的就是做Item上的数据适配了。继承一个BaseAdapter,代码如下,都比较简单:

/**
 * 首页ListView的数据适配器
 *
 * @author Administrator
 *
 */
public class ListItemAdapter extends BaseAdapter { 

 private Context mContext;
 private ArrayList<ItemEntity> items; 

 public ListItemAdapter(Context ctx, ArrayList<ItemEntity> items) {
 this.mContext = ctx;
 this.items = items;
 } 

 @Override
 public int getCount() {
 return items == null ? 0 : items.size();
 } 

 @Override
 public Object getItem(int position) {
 return items.get(position);
 } 

 @Override
 public long getItemId(int position) {
 return position;
 } 

 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
 ViewHolder holder;
 if (convertView == null) {
  holder = new ViewHolder();
  convertView = View.inflate(mContext, R.layout.item_list, null);
  holder.iv_avatar = (ImageView) convertView
   .findViewById(R.id.iv_avatar);
  holder.tv_title = (TextView) convertView
   .findViewById(R.id.tv_title);
  holder.tv_content = (TextView) convertView
   .findViewById(R.id.tv_content);
  holder.gridview = (NoScrollGridView) convertView
   .findViewById(R.id.gridview);
  convertView.setTag(holder);
 } else {
  holder = (ViewHolder) convertView.getTag();
 }
 ItemEntity itemEntity = items.get(position);
 holder.tv_title.setText(itemEntity.getTitle());
 holder.tv_content.setText(itemEntity.getContent());
 // 使用ImageLoader加载网络图片
 DisplayImageOptions options = new DisplayImageOptions.Builder()//
  .showImageOnLoading(R.drawable.ic_launcher) // 加载中显示的默认图片
  .showImageOnFail(R.drawable.ic_launcher) // 设置加载失败的默认图片
  .cacheInMemory(true) // 内存缓存
  .cacheOnDisk(true) // sdcard缓存
  .bitmapConfig(Config.RGB_565)// 设置最低配置
  .build();//
 ImageLoader.getInstance().displayImage(itemEntity.getAvatar(),
  holder.iv_avatar, options);
 final ArrayList<String> imageUrls = itemEntity.getImageUrls();
 if (imageUrls == null || imageUrls.size() == 0) { // 没有图片资源就隐藏GridView
  holder.gridview.setVisibility(View.GONE);
 } else {
  holder.gridview.setAdapter(new NoScrollGridAdapter(mContext,
   imageUrls));
 }
 // 点击回帖九宫格,查看大图
 holder.gridview.setOnItemClickListener(new OnItemClickListener() { 

  @Override
  public void onItemClick(AdapterView<?> parent, View view,
   int position, long id) {
  // TODO Auto-generated method stub
  imageBrower(position, imageUrls);
  }
 });
 return convertView;
 } 

 /**
 * 打开图片查看器
 *
 * @param position
 * @param urls2
 */
 protected void imageBrower(int position, ArrayList<String> urls2) {
 Intent intent = new Intent(mContext, ImagePagerActivity.class);
 // 图片url,为了演示这里使用常量,一般从数据库中或网络中获取
 intent.putExtra(ImagePagerActivity.EXTRA_IMAGE_URLS, urls2);
 intent.putExtra(ImagePagerActivity.EXTRA_IMAGE_INDEX, position);
 mContext.startActivity(intent);
 } 

 /**
 * listview组件复用,防止“卡顿”
 *
 * @author Administrator
 *
 */
 class ViewHolder {
 private ImageView iv_avatar;
 private TextView tv_title;
 private TextView tv_content;
 private NoScrollGridView gridview;
 }
}

这里有需要解释的地方了,看看listview上的图片处理,由于图片都是从网络获取的,为了避免图片过多造成OOM,那么这里加载图片的时候必不可少的需要做内存优化,图片的优化方式有很多,我这里采取了最简单最直接得方式,使用了开源的ImageLoader这个图片加载框架,这个框架简直是太优秀了,减少了开发者一系列不必要而且时常会出现的麻烦,关于ImageLoader并不是本篇博文需要讲解的知识,关于ImageLoader,欢迎在GitHub主页上下载,地址是https://github.com/nostra13/Android-Universal-Image-Loader,既然使用了ImageLoader这个框架,就不得不在程序上做一些初始化的操作,首先需要自定义一个全局的上下文Application类,将ImageLoader的相关属性初始化上去,直接看代码好了,见名知意:MyApplication.java

public class MyApplication extends Application {
 @Override
 public void onCreate() {
 super.onCreate();
 DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder() //
  .showImageForEmptyUri(R.drawable.ic_launcher) //
  .showImageOnFail(R.drawable.ic_launcher) //
  .cacheInMemory(true) //
  .cacheOnDisk(true) //
  .build();//
 ImageLoaderConfiguration config = new ImageLoaderConfiguration//
 .Builder(getApplicationContext())//
  .defaultDisplayImageOptions(defaultOptions)//
  .discCacheSize(50 * 1024 * 1024)//
  .discCacheFileCount(100)// 缓存一百张图片
  .writeDebugLogs()//
  .build();//
 ImageLoader.getInstance().init(config);
 }
}

定义这个Application之后,需要在清单文件中配置一下,在Manifest.xml中的Application节点上添加:
android:name="com.example.imagedemo.MyApplication"  
        此外由于ImageLoader是网络获取图片,又需要本地sdcard缓存图片,所以需要加上一下的权限,这是Imageloader标准权限:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 

再看看上面的Item上数据,里面有个GridView,显然这个GridView也是需要做数据适配的,这个数据反应的是从网络加载图片,比较简单,看代码NoScrollGridAdapter.java

 ......
Override
public View getView(int position, View convertView, ViewGroup parent) {
 View view = View.inflate(ctx, R.layout.item_gridview, null);
 ImageView imageView = (ImageView) view.findViewById(R.id.iv_image);
 DisplayImageOptions options = new DisplayImageOptions.Builder()//
  .cacheInMemory(true)//
  .cacheOnDisk(true)//
  .bitmapConfig(Config.RGB_565)//
  .build();
 ImageLoader.getInstance().displayImage(imageUrls.get(position),
  imageView, options);
 return view;
}
 ......

这样,所有的数据适配就做好了,接下来就需要做图片查看器了,当我们点击ListView上Item里的“九宫格”——NoScrollGridView的某张图片的时候,需要把这个图片的url传给一个图片查看器,图片查看器里会根据传递进来的url去网络加载这张图片,那么其实图片查看器就是一个新的单独的Activity,这个Activity会包含一个ViewPager,用来管理多张图片的查看。image_detail_pager.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent" > 

 <com.example.imagedemo.HackyViewPager
 android:id="@+id/pager"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="@android:color/black" /> 

 <TextView
 android:id="@+id/indicator"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_gravity="bottom"
 android:background="@android:color/transparent"
 android:gravity="center"
 android:text="@string/viewpager_indicator"
 android:textColor="@android:color/white"
 android:textSize="18sp" /> 

</FrameLayout>

HackyViewPager.java

public class HackyViewPager extends ViewPager { 

 private static final String TAG = "HackyViewPager"; 

 public HackyViewPager(Context context) {
 super(context);
 } 

 public HackyViewPager(Context context, AttributeSet attrs) {
 super(context, attrs);
 } 

 @Override
 public boolean onInterceptTouchEvent(MotionEvent ev) {
 try {
  return super.onInterceptTouchEvent(ev);
 } catch (IllegalArgumentException e) {
  // 不理会
  Log.e(TAG, "hacky viewpager error1");
  return false;
 } catch (ArrayIndexOutOfBoundsException e) {
  // 不理会
  Log.e(TAG, "hacky viewpager error2");
  return false;
 }
 } 

}

ImagePagerActivity.java

/**
 * 图片查看器
 */
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);
 ArrayList<String> urls = getIntent().getStringArrayListExtra(
  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 ArrayList<String> fileList; 

 public ImagePagerAdapter(FragmentManager fm, ArrayList<String> fileList) {
  super(fm);
  this.fileList = fileList;
 } 

 @Override
 public int getCount() {
  return fileList == null ? 0 : fileList.size();
 } 

 @Override
 public Fragment getItem(int position) {
  String url = fileList.get(position);
  return ImageDetailFragment.newInstance(url);
 } 

 }
}

已知图片查看的界面是继承自FragmentActivity的,所以支持显示的界面必须需要Fragment来实现,那么就自定义个Frangment吧,用这个Fragment来从url中获取图片资源,显示图片。image_detail_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="@android:color/black" > 

 <ImageView
 android:id="@+id/image"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:adjustViewBounds="true"
 android:contentDescription="@string/app_name"
 android:scaleType="centerCrop" /> 

 <ProgressBar
 android:id="@+id/loading"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_gravity="center"
 android:visibility="gone" /> 

</FrameLayout>

ImageDetailFragment.java

/**
 * 单张图片显示Fragment
 */
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();
   }
  });
 }
}

写到这里,此篇博文也宣告结束了。需要提出的是,我这里的图片查看器实现的图片的缩放效果使用的是开源组件PhotoView,关于PhotoView的github项目地址在这里,https://github.com/chrisbanes/PhotoView 需要点进去这个项目的网址,去下载源码,将源码全部拷贝到项目中来,使用也是相当方便的,demo如下:

ImageView mImageView;
PhotoViewAttacher mAttacher; 

@Override
public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main); 

 // Any implementation of ImageView can be used!
 mImageView = (ImageView) findViewById(R.id.iv_photo); 

 // Set the Drawable displayed
 Drawable bitmap = getResources().getDrawable(R.drawable.wallpaper);
 mImageView.setImageDrawable(bitmap); 

 // Attach a PhotoViewAttacher, which takes care of all of the zooming functionality.
 mAttacher = new PhotoViewAttacher(mImageView);
} 

// If you later call mImageView.setImageDrawable/setImageBitmap/setImageResource/etc then you just need to call
attacher.update();

刚开始这个图片查看器是我自己自定义View来实现的,其实需要实现图片的手势识别+多点触控+缩放,是可以使用矩阵Matrix来实现的,只不过这样显得特别的麻烦不说,而且极易出现BUG,这对于某些“急功近利”的项目来说,是个不好的兆头。所以,我这里摒弃了我用Matrix自定义的效果,改用github大牛为我们写好的开源组件,这样效率就上去了,大家也可以用Matrix自己去实现一下图片的多点触摸缩放的效果,关于Matrix的学习,请参加我以前的博文,Android自定义控件——3D画廊和图像矩阵。其实关于android上的图片缩放真没什么其它的方式,唯一能使用的还是Matrix这个类,不信先来瞧瞧Github大牛写的开源组件PhotoView是怎么实现的,查看以下部分源码:

// These are set so we don't keep allocating them on the heap
 private final Matrix mBaseMatrix = new Matrix();
 private final Matrix mDrawMatrix = new Matrix();
 private final Matrix mSuppMatrix = new Matrix();
 private final RectF mDisplayRect = new RectF();
 private final float[] mMatrixValues = new float[9];
/**
 * Set's the ImageView's ScaleType to Matrix.
 */
 private static void setImageViewScaleTypeMatrix(ImageView imageView) {
 /**
 * PhotoView sets it's own ScaleType to Matrix, then diverts all calls
 * setScaleType to this.setScaleType automatically.
 */
 if (null != imageView && !(imageView instanceof IPhotoView)) {
  if (!ScaleType.MATRIX.equals(imageView.getScaleType())) {
  imageView.setScaleType(ScaleType.MATRIX);
  }
 }
 }

以上只是PhotoView的部分源码,一目了然的发现它的实现也是基于Matrix的,时间与篇幅的局限性,大家需要更好的了解PhotoView的实现的话,就下载它的源码查看吧,要理解大神的想法是需要一些扎实的基础,关于PhotoView的具体实现细节,我也弄不太明白,可能是我对Matrix了解的不深刻吧,希望以后加强学习,也希望以后跟你们交流学习,共同进步!

本文转载:http://blog.csdn.net/allen315410/article/details/40264551

(0)

相关推荐

  • Android实现的可以调整透明度的图片查看器实例

    本文以实例讲解了基于Android的可以调整透明度的图片查看器实现方法,具体如下:  main.xml部分代码如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent"

  • Android 简单的图片查看器源码实现

    本文介绍了Android 简单的图片查看器源码实现,分享给大家,具体如下: public class MainActivity extends Activity { private EditText et_path; private ImageView iv; //创建handler 对象 // private Handler handler = new Handler(){ // // //处理消息 // public void handleMessage(android.os.Message

  • Android 网络图片查看器与网页源码查看器

    在AndroidManifest.xml里面先添加权限访问网络的权限: <uses-permission android:name="android.permission.INTERNET"/> 效果图如下: 下面是主要代码: package com.hb.neting; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import android.ann

  • android网络图片查看器简单实现代码

    本文实例为大家分享了android网络图片查看器的具体代码,供大家参考,具体内容如下 效果图: 1.输入一个图片url 2.转换成bitmap位图 3.展示到ImageView上 xml: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:t

  • Android编程实现网络图片查看器和网页源码查看器实例

    本文实例讲述了Android编程实现网络图片查看器和网页源码查看器.分享给大家供大家参考,具体如下: 网络图片查看器 清单文加入网络访问权限: <!-- 访问internet权限 --> <uses-permission android:name="android.permission.INTERNET"/> 界面如下: 示例: public class MainActivity extends Activity { private EditText image

  • Android仿微信朋友圈图片查看器

    再看文章之前,希望大家先打开自己的微信点到朋友圈中去,仔细观察是不是发现朋友圈里的有个"九宫格"的图片区域,点击图片又会跳到图片的详细查看页面,并且支持图片的滑动和缩放?这个功能是不是很常用呢?!那么我今天正好做了这个Demo,下面为大家讲解一下.首先按照惯例先看一下效果图吧,尤其不会录制gif动画(哎~没办法,模拟器不支持多点触控,刚好我的手机又没有Root,不能录屏,悲催啊,大家见谅,想要看真实效果的话,烦请移到文章最下方转载文章中进行源码下载,点击下载源码,运行后再看效果哈~~)

  • Android仿微信朋友圈图片选择器

    最近做开发需要解决一个模仿微信朋友圈附加图片的功能,具体要求如下: (1)从手机中最多选择3张图片,可拍照上传: (2)选择的图片可以点击移除然后再添加新图片: (3)可以在手机包含图片的各个文件夹中随意选择等. 本博客主要实现的是以上功能,其他诸如主界面布局.各种控件添加和提交功能等旨在说明问题,只做了简单处理,重点在图片选择添加部分.该功能的实现主要引用了一个图片加载的开源框架universal-image-loader. 其中截图如下: 为了不过于冗余,过滤了部分布局文件和资源文件,在这里

  • Android 仿微信朋友圈点赞和评论弹出框功能

    贡献/下载源码:https://github.com/mmlovesyy/PopupWindowDemo 本文简单模仿微信朋友圈的点赞和评论弹出框,布局等细节请忽略,着重实现弹出框.发评论,及弹出位置的控制. 1. 微信弹出框 微信朋友圈的点赞和评论功能,有2个组成部分: 点击左下角的"更多"按钮,弹出对话框: 点击评论,弹出输入框,添加评论并在页面中实时显示: 微信朋友圈点赞和评论功能 2. 实际效果 本文将建一个 ListView,在其 Item 中简单模仿微信的布局,然后着重实现

  • Android仿微信朋友圈点击评论自动定位到相关行功能

    最近闲来无事,随便看看各种UI实现的代码 本文涉及到的相关代码已经上传到 https://github.com/r17171709/android_demo/tree/master/WeixinEditText 打开你的微信朋友圈,点击评论,你就会发现有一个小细节:文本输入框的高度恰好定位到这条信息的底部位置 这个实现起来其实很简单,咱们就来看看吧 最简单的RecyclerView 依然是先实现RecyclerView.跟朋友圈一样,我们也把头给加上去,这样我们在点第一条信息的时候,效果会更好一

  • Android实现微信朋友圈图片和视频播放

    本文实例为大家分享了Android实现微信朋友圈图片和视频播放的具体代码,供大家参考,具体内容如下 1.效果图: 2.源码地址:链接 3.参数控制,是否显示播放按钮 holder.layout.setIsShowAll(mList.get(position).isShowAll); holder.layout.setIsVideo(true); //true :video, false :img holder.layout.setUrlList(mList.get(position).urlLi

  • Android仿微信朋友圈全文、收起功能的实例代码

    前言 一般在社交APP中都有类似朋友圈的功能,其中发表的动态内容很长的时候不可能让它全部显示.这里就需要做一个仿微信朋友圈全文.收起功能来解决该问题.在网上看到一个例子-->http://www.jb51.net/article/105251.htm,写的很不错,但是有个bug,他这个Demo只有在条目固定的时候才正常,当增加.删除条目的时候会出现全文.收起显示混乱的问题.原因是他使用了固定的position作为key来保存当前显示的状态.这篇文章在他的基础上进行优化. 效果图 具体代码 (详细

  • Android仿微信朋友圈点击加号添加图片功能

    本文为大家分享了类似微信朋友圈,点击+号图片,可以加图片功能,供大家参考,具体内容如下 xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto

  • Android仿微信朋友圈实现滚动条下拉反弹效果

    微信朋友圈上面的图片封面,QQ空间说说上面的图片封面都有下拉反弹的效果,这些都是使用滚动条实现的.下拉,当松开时候,反弹至原来的位置.下拉时候能看到背景图片.那么这里简单介绍一下这种效果的实现. 1.效果图 这部手机显示的分辨率有限,很老的手机调试. 2.具有反弹效果BounceScrollView package com.org.scroll; import android.content.Context; import android.graphics.Rect; import androi

  • Android仿微信朋友圈点赞和评论功能

    最近在做朋友圈的项目,所以写一个Android仿朋友圈点赞和评论功能Demo,代码就是简单实现了一下功能,没有做优化,凑合看 图文排列是用的RecyclerView实现的,弹窗效果是用的自定义的PopupWindow,点赞应该是在本地请求数据库,设置一个flag,获取当前用户的id后,带着id向服务器post一个flag,评论就比较简单了,也是获取当前朋友id(或者昵称),带着内容,向服务器post 贴代码: package com.example.lenovo.dianzandemo; imp

  • Android仿微信朋友圈添加图片的实例代码

    老习惯,先上图,着急用的朋友,直接带走Demo,先拿来用吧,毕竟老板催的紧,先把工作完成了,再看也来得及,是吧! 在项目中这种添加图片上传的效果应该是非常常见的,后面有个添加的按钮应该让有些童鞋不知道咋办了吧,其实没那么复杂,通过GridView就可以实现了 先说明一下,这里主要是讲添加图片的效果,至于图片选择器用的是第三方库photopicker,6.0权限用的是第三方库EasyPermission 1.首先这是用GridView实现的 <?xml version="1.0"

随机推荐