实现一个可以左右滑动切换预览图带标题的相册

Posted yarsnwoing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现一个可以左右滑动切换预览图带标题的相册相关的知识,希望对你有一定的参考价值。

实现一个可以左右滑动切换预览图带标题的相册

废话不多说,先来看看效果

(预览图较小)

(预览图较大)

(预览图最大)

按照文件夹显示:

实现思路

方法一: 可以用一个ListView嵌套GridView来实现。ListView的每个Item是一个显示标题的TextView和一个GridView组成。但是这种方式的实现需要我们自定义GridView,重写其OnMeasure()方法,否则GridView可能无法正常显示。而且优化不好容易卡顿
方法二:使用开源项目:[GitHub地址]https://github.com/TonicArtos/StickyGridHeaders 我们使用其中的StickyGridHeadersGridView和其适配器StickyGridHeadersSimpleAdapter展现出带标题的效果。至于左右滑动切换预览图的逻辑处理逻辑我们放在另外一个自定义GridView里面去实现。

1 首先实现StickyGridHeadersGridView的适配器

public class MyStickyAdapter extends BaseAdapter implements StickyGridHeadersSimpleAdapter

  String flag_sort;//根据什么排序的标志,可以更具日期,类型,还有文件来排序,默认按照时间排序
  private LayoutInflater inflater;
  LinkedHashMap<String, List<Picture>> listLinkedHashMap;
  private Context mContext;
  private List<Picture> pictures;

  public MyStickyAdapter(Context paramContext, String paramString)
  
    this.mContext = paramContext;
    this.flag_sort = paramString;
    this.inflater = LayoutInflater.from(paramContext);
    this.pictures = new ArrayList();
    init();
  

  private void init()
  
    if (this.flag_sort.equals("time_sort"))
    
      this.pictures = MainActivity1.pictures_timesort;//照片数据保存在MainActivity1中,在我的项目里,这是主Activity
      return;
    
    if (this.flag_sort.equals("folder_sort"))
    
      this.pictures = MainActivity1.pictures_default;
      return;
    
    if (this.flag_sort.equals("type_sort"))
    
      this.pictures = MainActivity1.pictures_type;
      return;
    
    this.pictures = MainActivity1.pictures_timesort;
  
  @Override
  public int getCount()
  
    return this.pictures.size();
  
  @Override
  public long getHeaderId(int paramInt)//会根据getTitle_id()返回有多少不同的结果来显示多少个不同的标题
  
    return ((Picture)this.pictures.get(paramInt)).getTitle_id();
  
  @Override
  public View getHeaderView(int paramInt, View paramView, ViewGroup paramViewGroup)
  
    HeadViewHolder localHeadViewHolder;
    if (paramView == null)
    
      localHeadViewHolder = new HeadViewHolder();
      paramView = this.inflater.inflate(R.layout.grid_head_item, paramViewGroup, false);
      localHeadViewHolder.textView = ((TextView)paramView.findViewById(R.id.grid_head_tv));
      paramView.setTag(localHeadViewHolder);
    else
        localHeadViewHolder = (HeadViewHolder)paramView.getTag()
    

      localHeadViewHolder.textView.setText(((Picture)this.pictures.get(paramInt)).getTitle());
      return paramView;

  
  @Override
  public Object getItem(int paramInt)
  
    return this.pictures.get(paramInt);
  
  @Override
  public long getItemId(int paramInt)
  
    return paramInt;
  
  @Override
  public View getView(int paramInt, View paramView, ViewGroup paramViewGroup)
  
      ViewHodler viewHodler
    if (paramView == null)
    
      viewHodler = new ViewHodler();
      paramView = this.inflater.inflate(R.layout.grid_body_item, null);
      viewHodler.imageView = ((ImageView)paramView.findViewById(R.id.grid_body_imageview));
      viewHodler.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
      LinearLayout localLinearLayout = (LinearLayout)paramView.findViewById(R.id.grid_body_linearlayout);//在grid_body_item.xml中此LinearLayout包含了ImageView,以便来展示不同的预览图的大小(注意包含的ImageView的宽和高都设为match_parent)
      int i;
      LinearLayout.LayoutParams localLayoutParams;
      if (GridViewAdapter.flag == 0)//根据不同的参数来使相册预览图显示不同的大小
      
        i = mContext.getResources().getDisplayMetrics().widthPixels / 8;
        localLayoutParams = (LinearLayout.LayoutParams)localLinearLayout.getLayoutParams();
        localLayoutParams.height = i;//宽和高都设置成相同的,以显示正方形效果
        localLayoutParams.width = i;
        localLinearLayout.setLayoutParams(localLayoutParams);
      
      if (GridViewAdapter.flag == 1)
      
        i = mContext.getResources().getDisplayMetrics().widthPixels / 6;
        localLayoutParams = (LinearLayout.LayoutParams)localLinearLayout.getLayoutParams();
        localLayoutParams.height = i;
        localLayoutParams.width = i;
        localLinearLayout.setLayoutParams(localLayoutParams);
      
      if (GridViewAdapter.flag == 2)
      
        i = mContext.getResources().getDisplayMetrics().widthPixels / 3;
        localLayoutParams = (LinearLayout.LayoutParams)localLinearLayout.getLayoutParams();
        localLayoutParams.height = i;
        localLayoutParams.width = i;
        localLinearLayout.setLayoutParams(localLayoutParams);
      
      paramView.setTag(viewHodler);
    else
     viewHodler = (ViewHodler)paramView.getTag();
    
    Glide.with(this.mContext).load(new File(((Picture)this.pictures.get(paramInt)).getPath())).error(R.drawable.error).into(viewHodler.imageView);//使用Glide图片加载框架来加载图片

    return paramView;

  

  class HeadViewHolder
  
    TextView textView; 
  

  class ViewHodler
  
    ImageView imageView;
  

2 接下来只需要在MainActivity1的布局里加上控件 StickyGridHeadersGridView,然后再setAdapter就可以将相册展现出来(我这里没有讲解怎样从android系统里面去获取所有照片的数据信息,我使用的是Android自带MediaStore类来获取的,网上有很多资料)

3 最后就是实现怎样左右滑动切换预览图的大小了,我采用的是自定义一个GridView,然后重写其OnTouchEvent()方法,最后再让StickyGridHeadersGridView继承我重写的GridView ( 本身StickyGridHeadersGridView是直接继承GridView的,我在项目里是将StickyGridHeadersGridView开源项目里面的类直接copy到我的项目里面,这样我就能够直接更改StickyGridHeadersGridView的源码 ) ,这样就能够让StickyGridHeadersGridView也能实现左右滑动监听了

public class MyGridView
  extends GridView

  private static final int SNAP_VELOCITY = 1000;

  private int column;//占时没有用到
  Context context;
  private int lastX = 0;
  private int lastY = 0;
  private Handler mHandler;
  private VelocityTracker mVelocityTracker;
  private int minTouchSlop = 0;//系统判定为滑动的最小距离

  public MyGridView(Context paramContext)
  
    super(paramContext);
    this.context = paramContext;
    this.animLoadUtil = new AnimLoadUtil(paramContext);
    this.mHandler = new Handler();
    this.minTouchSlop = ViewConfiguration.get(paramContext).getScaledTouchSlop();
  

  public MyGridView(Context paramContext, AttributeSet paramAttributeSet)
  
    super(paramContext, paramAttributeSet);
    this.context = paramContext;
    this.animLoadUtil = new AnimLoadUtil(paramContext);
    this.mHandler = new Handler();
    this.minTouchSlop = ViewConfiguration.get(paramContext).getScaledTouchSlop();
  

  public MyGridView(Context paramContext, AttributeSet paramAttributeSet, int paramInt)
  
    super(paramContext, paramAttributeSet, paramInt);
    this.context = paramContext;
    this.animLoadUtil = new AnimLoadUtil(paramContext);
    this.mHandler = new Handler();
    this.minTouchSlop = ViewConfiguration.get(paramContext).getScaledTouchSlop();
  

  private void change_ImageView_size_big()//使预览图变大
  
    if (GridViewAdapter.flag == 0) 
      GridViewAdapter.flag = 1;//表示中等大小
    
     if (GridViewAdapter.flag == 1) 
      GridViewAdapter.flag = 2;//表示最大大小
    
     if (GridViewAdapter.flag == 2) 
      //GridViewAdapter.flag = 2;

      return;
    
    mHandler.postDelayed(new Runnable()
        //MyGridView.this.setColumn();
            MyStickyAdapter localMyStickyAdapter;
            if (DataQueryUtil.getChangeName(AlbumApp.getContext()).equals("time_sort")) 
                //每次用户选择不同的排序方式时都会将表示当前排序方式的值写入数据库,而DataQueryUtil这个自己写的工具类就可以查询这个值
              localMyStickyAdapter = new MyStickyAdapter(MyGridView.this.context, "time_sort");
            else if (DataQueryUtil.getChangeName(AlbumApp.getContext()).equals("folder_sort")) 
              localMyStickyAdapter = new MyStickyAdapter(MyGridView.this.context, "folder_sort");
            else if (DataQueryUtil.getChangeName(AlbumApp.getContext()).equals("type_sort")) 
              localMyStickyAdapter = new MyStickyAdapter(MyGridView.this.context, "type_sort");
            else
                localMyStickyAdapter = new MyStickyAdapter(MyGridView.this.context, "time_sort");//默认按照时间排序
            
            //MyGridView.this.setAlpha(1.0F);
            MyGridView.this.setAdapter(localMyStickyAdapter);

    ,50);

  

  private void change_ImageView_size_small()
  
    if (GridViewAdapter.flag == 2) 
      GridViewAdapter.flag = 1;//表示中等大小
    
     if (GridViewAdapter.flag == 1) 
      GridViewAdapter.flag = 0;//表示最小大小
    
     if (GridViewAdapter.flag == 0) 

      return;
    
    mHandler.postDelayed(new Runnable()
        //MyGridView.this.setColumn();
        MyStickyAdapter localMyStickyAdapter;

            if (DataQueryUtil.getChangeName(AlbumApp.getContext()).equals("time_sort")) 

              localMyStickyAdapter = new MyStickyAdapter(MyGridView.this.context, "time_sort");
            else if (DataQueryUtil.getChangeName(AlbumApp.getContext()).equals("folder_sort")) 
              localMyStickyAdapter = new MyStickyAdapter(MyGridView.this.context, "folder_sort");
            else if (DataQueryUtil.getChangeName(AlbumApp.getContext()).equals("type_sort")) 
              localMyStickyAdapter = new MyStickyAdapter(MyGridView.this.context, "type_sort");
            else
                localMyStickyAdapter = new MyStickyAdapter(MyGridView.this.context, "time_sort");
            
            //MyGridView.this.setAlpha(1.0F);
            MyGridView.this.setAdapter(localMyStickyAdapter);

    ,50);

  

  @Override
  public boolean onTouchEvent(MotionEvent paramMotionEvent)
  
    if (this.mVelocityTracker == null) 
      this.mVelocityTracker = VelocityTracker.obtain();
    
    this.mVelocityTracker.addMovement(paramMotionEvent);
    int x = (int)paramMotionEvent.getX();
    int y = (int)paramMotionEvent.getY();

    switch (paramMotionEvent.getAction())
    
    case MotionEvent.ACTION_DOWN:
        this.lastX = x;
        this.lastY = y;
        break;

    case MotionEvent.ACTION_UP:

        VelocityTracker localVelocityTracker = this.mVelocityTracker;
          localVelocityTracker.computeCurrentVelocity(1000);
          int xVelocity = (int)localVelocityTracker.getXVelocity();//这里没有用上
          int yVelocity = (int)localVelocityTracker.getYVelocity();//这里没有用上
          int offsetX=x-lastX;
          int offsetY=y-lastY;


          if (this.mVelocityTracker != null)
          //及时回收
            this.mVelocityTracker.recycle();
            this.mVelocityTracker = null;
          
          if ((Math.abs(offsetX) > this.minTouchSlop) && (offsetY > 0))
          
            if ((offsetX > 0) && (Math.abs(offsetX) > Math.abs(offsetY)))
            
              change_ImageView_size_big();
              return true;
            
            if ((offsetX < 0) && (Math.abs(offsetX) > Math.abs(offsetY)))
            
              change_ImageView_size_small();
              return true;
            
          
          break;


    
     return super.onTouchEvent(paramMotionEvent);
  


  public void setColumn()
  
    if (GridViewAdapter.flag == 0) 
      this.column = 8;
    else if(GridViewAdapter.flag == 1) 
        this.column = 6;
    else if(GridViewAdapter.flag == 2) 
        this.column = 3;
    else 
        this.column = 8;
    
   

4 优化

1 在切换预览图时可以加上动画这样效果体验效果更好
2 加上显示视频缩略图的功能,可以将用户手机里面的视频也一起加载出来

最后放上我的完整apk吧,完整apk还有其他一些功能,比如指纹解锁等,大家可以有空可一体验下。[apk下载地址:]http://gsgs.oss-cn-qingdao.aliyuncs.com/album.apk

以上是关于实现一个可以左右滑动切换预览图带标题的相册的主要内容,如果未能解决你的问题,请参考以下文章

android怎么实现页面的左右滑动

手机左右滑动屏幕切换页面是如何实现的

为啥h5页面可以上下滑动,却不可以左右滑动

请问有人用videojs实现上下滑动切换视频功能

html5怎么实现页面左右滑动(下图区域),可以左右滑动但不需要换页

Android中使用GridView和ImageViewSwitcher实现电子相册简单功能