screen4.gif
玩了一段时间Android,最近在实现一些常用的控件封装:项目GitHub地址https://github.com/tikeyc/TikeycAndroid 。这几天想封装一个横向滑动的listView,但发现Android没有像iOS那样的UICollectionView控件,似乎只有一个HorizontalScrollView,后来发现Android有个RecyclerView设置setLayoutManager的setOrientation为HORIZONTAL即可简单实现,不过还是回到最初我的想法去尝试一下。

当然最后肯定是用RecyclerView控件实现(刚学自学Android开发的时候居然没发现RecyclerView,惭愧的很,不过这个控件也是2014年support.v7包出现才有的)。

前期实现思路有:

1.使用GridView添加到HorizontalScrollView上,设置column为item数量count,width为count*itemWidth,这样没有复用性了性能低;
2.根据listView的复用原理,结合HorizontalScrollView自定义一个横向滑动的控件,需要敲一些代码;

中期实现思路:

记得很久以前刚学iOS的时候第一次看到横向滑动的UITableView,想实现它,当时的思路就是将UITableView逆时针旋转90°,然后将UITableViewCell顺时针旋转90°(当然现在肯定是用UICollectionView)。这里我把这个思路用到Android的实现上,将ListView逆时针旋转90°,然后将item顺时针旋转90°,果不其然,成功了!小爽一把。源码地址:https://github.com/tikeyc/TikeycAndroid 封装详情代码见THorizontalListView类
目前还存在一个小问题:就是如果item不是正方形,因为默认旋转是以item中心点旋转,item会出现偏移的问题,需要根据你具体的item的尺寸修改旋转中心点,具体见下面需要了解的技术点.

这里也提一个问题,这个旋转不像iOS那样,iOS先旋转后重新设置想要的frame不会有问题,因初入Android开发,先setRotation,然后旋转后使用setLayoutParams设置想要的frame不成功,旋转中心位置就跟着变了。来个吊大的提供一个方法能像iOS那样。

后期实现思路:

RecyclerView是support.v7包中的控件,可以说是ListView和GridView的增强升级版。RecyclerView设置setLayoutManager的setOrientation为HORIZONTAL即可简单实现

需要了解的技术点:
/**逆时针旋转90°     *setRotation(-90); 默认是已view的中心点旋转,所以先根据最终旋转后显示的位置,先更改view的位置到初始旋转的合适位置,然后再旋转90°就会显示在你所希望的位置     * 如下图:由默认的竖向已中心点旋转为横向             * * * * *             *       *             *       *       * * * * * * * * * * *       *     *       *     *       *     *       *     *       * * * * * * * * * * *             *       *             *       *             * * * * *     */
//此方法用于获取View在Z轴上的旋转角度  public float android.view.View.getRotation()    //此方法用于获取View在X轴上的旋转角度  public float android.view.View.getRotationX()    //此方法用于获取View在Y轴上的旋转角度  public float android.view.View.getRotationY()    //设置View在Z轴上的旋转角度  public void android.view.View.setRotation(float rotation)    //设置View在X轴上的旋转角度  public void android.view.View.setRotationX(float rotationX)    //设置View在Y轴上的旋转角度  public void android.view.View.setRotationY(float rotationY)    //设置View旋转中心点的X坐标。  public void android.view.View.setPivotX(float pivotX)    //设置View旋转中心点的Y坐标。  public void android.view.View.setPivotX(float pivotX)   //设置摄像机的与旋转目标在Z轴上距离  void android.view.View.setCameraDistance(float distance)
具体实现:
package com.tikeyc.tikeycandroid.custom.ScrollView;import android.content.Context;import android.graphics.RectF;import android.os.Handler;import android.os.Message;import android.support.annotation.Nullable;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.view.ViewGroup;import android.view.ViewTreeObserver;import android.widget.AbsListView;import android.widget.BaseAdapter;import android.widget.LinearLayout;import android.widget.ListView;/** * Created by public1 on 2017/6/2. */public class THorizontalListView extends ListView {    private int listView_width;    private int listView_height;    private THorizontalListAdapter horizontalListAdapter;    public THorizontalListView(Context context) {        this(context,null);    }    public THorizontalListView(Context context, @Nullable AttributeSet attrs) {        this(context, attrs,0);    }    public THorizontalListView(Context context, @Nullable AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        init();    }    @Override    protected void onAttachedToWindow() {        super.onAttachedToWindow();    }    private void init() {        rotationListView();        horizontalListAdapter = new THorizontalListAdapter();        setAdapter(horizontalListAdapter);    }    /**逆时针旋转90°     *setRotation(-90); 默认是已view的中心点旋转,所以先根据最终旋转后显示的位置,先更改view的位置到初始旋转的合适位置,然后再旋转90°就会显示在你所希望的位置     * 如下图:由默认的竖向已中心点旋转为横向             * * * * *             *       *             *       *       * * * * * * * * * * *       *     *       *     *       *     *       *     *       * * * * * * * * * * *             *       *             *       *             * * * * *     */    private void rotationListView() {        ViewTreeObserver viewTreeObserver = getViewTreeObserver();        viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {            @Override            public boolean onPreDraw() {                getViewTreeObserver().removeOnPreDrawListener(this);                int left = getLeft();                int top = getTop();                int right = getRight();                int bottom = getBottom();                int width = right - left;                int height = bottom - top;                Log.e("TAG","getWidth():" + getWidth() + "--" + "getHeight():" + getHeight());                Log.e("TAG","left:" + left + "--" + "top:" + top + "--" + "width:" + width + "--" + "height:" + height);                LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();                layoutParams.leftMargin = layoutParams.leftMargin + (width - height)/2;//将view已到默认的旋转中心点                layoutParams.topMargin = layoutParams.topMargin + (height - width)/2;//将view已到默认的旋转中心点                listView_width = width;                listView_height = height;                layoutParams.width = height;//旋转后的宽是旋转前的高                layoutParams.height = width;//旋转后的高是旋转前的宽                setLayoutParams(layoutParams);                Log.e("TAG","left:" + left + "--" + "top:" + top + "--" + "width:" + width + "--" + "height:" + height);                setRotation(-90);                Log.e("TAG","left2:" + getLeft() + "--" + "top2:" + getTop() + "--" + "width:" + width + "--" + "height:" + height);                return true;            }        });    }    public class THorizontalListAdapter extends BaseAdapter {        @Override        public int getCount() {            if (dataSource != null) return dataSource.getCount();            return 0;        }        @Override        public Object getItem(int i) {            if (dataSource != null) return dataSource.getItem(i);            return null;        }        @Override        public long getItemId(int i) {            if (dataSource != null) return dataSource.getItemId(i);            return 0;        }        @Override        public View getView(int i, View view, ViewGroup viewGroup) {            if (dataSource != null) {                view = dataSource.getView(i,view,viewGroup);                //再将item顺时针旋转90° 宽是旋转后的高(item的宽度),高是旋转后的宽(item的高度)                ViewTreeObserver treeObserver = view.getViewTreeObserver();                final View finalView = view;                treeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {                    @Override                    public boolean onPreDraw() {//                        int width = finalView.getWidth();//                        int height = finalView.getHeight();//                        finalView.setPivotX(width/2);//                        finalView.setPivotY(listView_height/2);                        AbsListView.LayoutParams layoutParams = new AbsListView.LayoutParams(listView_height,listView_height);                        finalView.setLayoutParams(layoutParams);                        finalView.setRotation(90);                        return true;                    }                });                return view;            }            return view;        }    }    private THorizontalListAdapterDatasource dataSource;    public void setDataSource(THorizontalListAdapterDatasource dataSource) {        this.dataSource = dataSource;        horizontalListAdapter.notifyDataSetChanged();    }    public THorizontalListAdapterDatasource getDataSource() {        return dataSource;    }    public interface THorizontalListAdapterDatasource {        int getCount();        Object getItem(int i);        long getItemId(int i);        View getView(int i, View view, ViewGroup viewGroup);    }}
如何使用:
见类TReleaseFragment或者THomeUserAdapter
使用的主要关键代码:
THorizontalListView horizontalListView = (THorizontalListView) mView.findViewById(R.id.tHorizontalListView);        horizontalListView.setBackgroundColor(Color.BLUE);        horizontalListView.setDataSource(new THorizontalListView.THorizontalListAdapterDatasource() {            class ViewHolder {            }            @Override            public int getCount() {                return 20;            }            @Override            public Object getItem(int i) {                return null;            }            @Override            public long getItemId(int i) {                return 0;            }            @Override            public View getView(int i, View view, ViewGroup viewGroup) {                ViewHolder viewHolder;                if (view == null) {                    viewHolder = new ViewHolder();                    view = View.inflate(getContext(),R.layout.release_home_image_list_item,null);                    //宽是高,高是宽                    view.setTag(viewHolder);                } else {                    viewHolder = (ViewHolder) view.getTag();                }                return view;            }        });    }

更多相关文章

  1. 【Android】如何让跑马灯跑起来-控件请求焦点
  2. Android控件GridView的使用
  3. android获取GPS位置信息
  4. android 相对布局中的 控件布局
  5. Android中自定义switch控件样式
  6. android中listview控件覆盖了其它控件使下面的其它控件不显示
  7. 自定义控件 - 圆形缓冲进度条
  8. Android GPS获取当前位置信息
  9. Android支持展开/收缩功能的列表控件

随机推荐

  1. GalHttprequest类库简介——android平台
  2. One省电卫士 - Android内核级省电App
  3. 风投称Android将像Windows一样主宰移动市
  4. Smack和Asmack
  5. Android(安卓)网络访问框架 NiceDay 发布
  6. 手机的CPU架构简述及SO兼容(Android/iOS)及
  7. ANDROID – TOOLBAR STEP BY STEP
  8. Android(安卓)依赖注入Dagger2 使用 之
  9. Android(安卓)Canvas类介绍
  10. [置顶] Android实现数据存储技术集锦