拿着妹子Api去玩耍,RecyclerView瀑布流实现

RecyclerView是Andorid 5.X中谷歌对ListView进行的一个升级,是一个强大的滑动组件,使用起来比ListView更为强大,可以很好的维护大数据集的滚动和显示。

  • RecyclerView不关心Item是否显示在正确的位置,以及如何显示。(依靠LayoutManager进行RecyclerView布局的制定)
  • RecyclerView不关心Item间如何间隔(使用ItemDecoration进行下划线的绘制)
  • RecyclerView不关注Item增加与删除的动画效果(动画效果由ItemAnimator处理)
  • RecyclerView只关注如何回收和复用View

布局、绘制、动画等方面的工作谷歌都将其差分成不同的类进行管理,因此我们可以自定义这些类来实现自己的需求。

相比于List View,RecyclerView对ViewHolder进行了封装,强制我们必须要使用ViewHolder来进行优化,因此只要实现功能就可以了。
另外注意的是Android并没有给Recycler增加点击事件,因此需要我们自己使用接口的回调机制或者直接在适配器中监听View的点击事件。

下面看一下运行效果:

这里写图片描述

Api使用的是:http://gank.io/api/data/福利/10/1(就叫做妹子Api吧O(∩_∩)O),可以去http://gank.io/api

项目结构:

这里写图片描述

自己封装的网络请求和io流转换的工具类就就不贴出来了代码比较简单

下面通过这个案例梳理一下RecyclerView的用法以加深记忆:

MyRecyclerViewAdapter.java

/**
 * Created by 春水碧于天 on 2017/1/27.
 */

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyViewHolder> {

    private LayoutInflater mLayoutInflater;
    private Context mContext;
    private List<String> mDatas; //封装图片Url
    private Random random;

    //构造函数初始化数据
    public MyRecyclerViewAdapter(List<String> data, Context mContext) {
        mDatas = data;
        this.mContext = mContext;
        this.mLayoutInflater = mLayoutInflater.from(mContext);
        random = new Random();
    }


    //返回由多少条数据
    @Override
    public int getItemCount() {

        return mDatas.size();
    }

    //直接创建一个可复用的ViewHolder或者根据ViewType创建多种不同的ViewHolder
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {


        View view = mLayoutInflater.inflate(R.layout.item_single_textview,parent,false);

        MyViewHolder viewHolder = new MyViewHolder(view);

        return viewHolder;
    }

    //数据和ViewHolder中的内容通过position进行绑定
    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {



        Uri uri = Uri.parse(mDatas.get(position));

        ViewGroup.LayoutParams params = holder.imageView.getLayoutParams();

        //通过随机数生成ImageView的高度,动态设置给ImageView实现瀑布流效果的关键
        params.height = random.nextInt(200)+300;

        holder.imageView.setLayoutParams(params);

        //通过Glide加载网络路径的图片
        Glide.with(mContext).load(uri).into(holder.imageView);


        //设置ImageView的点击事件
        holder.imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Toast.makeText(mContext,position+"",Toast.LENGTH_SHORT).show();

                Intent intent = new Intent(mContext, DetailActivity.class);

                intent.putExtra("uri",mDatas.get(position));

                mContext.startActivity(intent, ActivityOptions.makeSceneTransitionAnimation((Activity) mContext,holder.imageView,"share").toBundle());


            }
        });

    }



}


//通过继承ViewHolder这个抽象类实现View的封装
class MyViewHolder extends RecyclerView.ViewHolder{

    public ImageView imageView;

    public MyViewHolder(View itemView) {

        super(itemView);
        imageView = (ImageView) itemView.findViewById(R.id.imageView);
    }
}

在ListView中ViewHolder的作用为了防止每次创建布局的时候都会调用findViewById(int ),导致ListView的性能展示缓慢,而RecyclerView则强制我们使用ViewHolder。

这里面的点击事件的逻辑直接写在了Adapter中,也可以通过回调的形式来完成。

回调的写法:

public OnItemClickListener onItemClickListener;

public void setOnItemClickListener(OnItemClickListener onItemClickListener){
    this.onItemClickListener = onItemClickListener;

}

public interface OnItemClickListener{
    void(View v,int position)
}

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private RecyclerView.Adapter myAdapter;
    private RecyclerView mRecyclerView;
    private Handler mHandler;
    private List<String> Images;
    private List<Integer> mImageHeights;
    private int count = 1;

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

        Log.i("ljx", "新年快乐O(∩_∩)O……");

        InitUI();
        InitData();

        //给RecyclerView设置布局
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);

        mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
        /**
         * 系统默认的三种布局样式:
         *
         *   new LinearLayoutManager() //线性布局管理器,默认方向垂直
         *   new GridLayoutManager() //创建网格布局管理器,默认方向垂直
         *   new LinearLayoutManager () //创建错综网格布局,默认方向锤子,可以用来实现瀑布流效果
         */


        myAdapter = new MyRecyclerViewAdapter(Images, MainActivity.this); //创建适配器

        mRecyclerView.setAdapter(myAdapter); //给RecyclerView绑定适配器

        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {

                String JsonStr = (String) msg.obj;

                Log.i("wk", "Handler:" + JsonStr);

                getImagesFromJson(JsonStr); //解析Json

                myAdapter.notifyDataSetChanged(); //更新数据

                Toast.makeText(MainActivity.this, "加载到第" + count + "页", Toast.LENGTH_SHORT).show();

            }
        };


        new Thread(new Runnable() {
            @Override
            public void run() {

                //进行网络请求
                String ResultStr = HttpHelper.GetHttpConnection("http://gank.io/api/data/%E7%A6%8F%E5%88%A9/40/1");

                Message msg = new Message();

                msg.obj = ResultStr;

                mHandler.sendMessage(msg);


            }
        }).start();


        //RecyclerView的滑动监听
        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                //判断是否滑动到底部,用于分页加载
                if (isSlideToBottom(recyclerView)) {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            String ResultStr = HttpHelper.GetHttpConnection("http://gank.io/api/data/%E7%A6%8F%E5%88%A9/40/" + count++);

                            Message msg = new Message();

                            msg.obj = ResultStr;

                            mHandler.sendMessage(msg);


                        }
                    }).start();


                }
            }
        });


    }

    //解析Json数据将解析到的Image的Url添加的Images集合当中
    private void getImagesFromJson(String jsonStr) {


        try {
            JSONObject jsonObject = new JSONObject(jsonStr);

            JSONArray jsonArray = jsonObject.getJSONArray("results");


            for (int i = 0; i < jsonArray.length(); i++) {


                JSONObject jb = jsonArray.getJSONObject(i);

                Images.add(jb.getString("url"));


            }


        } catch (JSONException e) {
            e.printStackTrace();
        } finally {
        }

    }


    private void InitData() {

        Images = new ArrayList<String>();


    }


    private void InitUI() {
        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
    }

    //判断recycler是否滑动到底部
    protected boolean isSlideToBottom(RecyclerView recyclerView) {
        if (recyclerView == null) return false;

        if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset() >= recyclerView.computeVerticalScrollRange())
            return true;

        return false;
    }


}

这边没有使用到之前提到的 ItemDecoration,ItemAnimator这两个类,后面深入的时候会对这两个类的使用进行详解,以及布局LayoutManager的自定义。

DetailActivity.java

用于显示大图

public class DetailActivity extends AppCompatActivity {
    private ImageView imageView;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_detail);



        imageView = (ImageView) findViewById(R.id.imageView);

        String uri = getIntent().getStringExtra("uri");

        Glide.with(this).load(Uri.parse(uri)).into(imageView);


    }
}

布局就补不贴了,比较简单,从上面的代码也就能看出布局文件的写法了。这样一个瀑布流就实现了,相比使用ListView来实现这个效果实在简单了不少。

最后 妹子API确实挺不错的额,适合练手^_^

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值