时间:2021-05-19
RecyclerView是一种列表容器, 发布很久了, 才想起来写点什么.
RecyclerView相比于ListView, 在回收重用时更具有灵活性, 也就是低耦合, 并且提供了扩展. 加载多个视图时, 应该多用RecyclerView代替ListView.
那么我们来看看这东西应该怎么用? 比如生成一个瀑布流的视图.
首先我们从一个HelloWorld写起, 看看如何构建一个RecyclerView.
1. 依赖库
Gradle配置, 添加Recycler库
2. 资源文件
资源文件
4. LayoutManager
管理RecyclerView的布局结构.
提供了多种LayoutManager, 瀑布流使用错列网格布局.
5. Adapter
适配器, 处理RecyclerView的Item事务.
对于Adapter, 我们需要展开来说, 先看看类.
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> { private List<DataModel> mDataModels; private List<Integer> mHeights; MyAdapter(List<DataModel> dataModels) { if (dataModels == null) { throw new IllegalArgumentException("DataModel must not be null"); } mDataModels = dataModels; mHeights = new ArrayList<>(); } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_recycler_view, parent, false); return new MyViewHolder(itemView); } @Override public void onBindViewHolder(MyViewHolder holder, int position) { DataModel dataModel = mDataModels.get(position); // 随机高度, 模拟瀑布效果. if (mHeights.size() <= position) { mHeights.add((int) (100 + Math.random() * 300)); } ViewGroup.LayoutParams lp = holder.getTvLabel().getLayoutParams(); lp.height = mHeights.get(position); holder.getTvLabel().setLayoutParams(lp); holder.getTvLabel().setText(dataModel.getLabel()); holder.getTvDateTime().setText(new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH) .format(dataModel.getDateTime())); } @Override public int getItemCount() { return mDataModels.size(); } public void addData(int position) { DataModel model = new DataModel(); model.setDateTime(getBeforeDay(new Date(), position)); model.setLabel("No. " + (int) (new Random().nextDouble() * 20.0f)); mDataModels.add(position, model); notifyItemInserted(position); } public void removeData(int position) { mDataModels.remove(position); notifyItemRemoved(position); } /** * 获取日期的前一天 * * @param date 日期 * @param i 偏离 * @return 新的日期 */ private static Date getBeforeDay(Date date, int i) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.DAY_OF_YEAR, i * (-1)); return calendar.getTime(); }}(1)onCreateViewHolder创建ViewHolder.
(2)onBindViewHolder绑定每一项数据.
(3)getItemCount返回列表长度.
(4)RecyclerView强制使用ViewHolder.
public class MyViewHolder extends RecyclerView.ViewHolder { private TextView mTvLabel; // 标签 private TextView mTvDateTime; // 日期 public MyViewHolder(View itemView) { super(itemView); mTvLabel = (TextView) itemView.findViewById(R.id.item_text); mTvDateTime = (TextView) itemView.findViewById(R.id.item_date); } public TextView getTvLabel() { return mTvLabel; } public TextView getTvDateTime() { return mTvDateTime; }}在onCreateViewHolder方法, 创建类; 在onBindViewHolder方法, 绑定数据.
DataModel
6. ItemDecoration
项的装饰, 比如ListView中的分割线, 在本例中, 左右两条粉线.
ItemDecoration, 注意parent和child的使用方式.
public class MyItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[]{android.R.attr.listDivider}; private Drawable mDivider; public MyItemDecoration(Context context) { final TypedArray array = context.obtainStyledAttributes(ATTRS); mDivider = array.getDrawable(0); array.recycle(); } @Override public void onDraw(Canvas c, RecyclerView parent, State state) { drawHorizontal(c, parent); drawVertical(c, parent); } // 水平线 public void drawHorizontal(Canvas c, RecyclerView parent) { final int childCount = parent.getChildCount(); // 在每一个子控件的底部画线 for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final int left = child.getLeft() + child.getPaddingLeft(); final int right = child.getWidth() + child.getLeft() - child.getPaddingRight(); final int top = child.getBottom() - mDivider.getIntrinsicHeight() - child.getPaddingBottom(); final int bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } // 竖直线 public void drawVertical(Canvas c, RecyclerView parent) { final int childCount = parent.getChildCount(); // 在每一个子控件的右侧画线 for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); int right = child.getRight() - child.getPaddingRight(); int left = right - mDivider.getIntrinsicWidth(); final int top = child.getTop() + child.getPaddingTop(); final int bottom = child.getTop() + child.getHeight() - child.getPaddingBottom(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } // Item之间的留白 @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) { outRect.set(0, 0, mDivider.getIntrinsicWidth(), mDivider.getIntrinsicHeight()); }}本例重写了listDivider
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> ... <item name="android:listDivider">@drawable/divider_bg</item> </style><?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="#ff00ff"/> <size android:height="4dp"/> <size android:width="4dp"/></shape>7. ItemAnimator
动画效果比较复杂, 使用默认动画. 如要定制的话, 继承DefaultItemAnimator; 如设置null, 则不显示任何动画.
8. 最终Activity
为了测试动画, Menu额外添加两个按钮。
9.运行ReactNative示例
既然感觉ReactNative开发靠谱, 那么我们就来看看ReactNative都能做哪些好玩的东西, 和原生的有哪些区别?
示例图
按照文档安装一些命令行工具, 再下载Git代码.
Github: https://github.com/facebook/react-native
内容很多, 包含一些依赖库和示例(Example), 下载的有点慢, 耐心等待.
下载完成后, 在react-native内, 执行npm install.
Android项目执行, 参考ReactAndroid的README.md.
在react-native目录, 新建local.properties
sdk.dir=/Users/wangchenlong/Installations/android-sdkndk.dir=/Users/wangchenlong/Installations/android-ndk-r10e执行
cd react-native./gradlew :ReactAndroid:assembleDebug再执行
./gradlew :ReactAndroid:installArchives启动服务
./packager/packager.sh安装项目
cd react-native./gradlew :Examples:UIExplorer:android:app:installDebug一定要先启动服务, 再安装项目.
出现transforming 100%, 即导入成功.
在最新版本中, 我的红米note4无法运行项目.
报错: Upload package to device fails.
原因是编译的gradle版本太高, 默认1.5.0, 实际1.2.0~1.3.0都可以运行.
我的是1.2.3.
真机调试, 本人红米note(Android 4.2)
摇动手机, 选择Dev Settings->Debug sever host & port for device. 设置IP地址, 观察本机的IP, 填入即可. 我当前的是
192.168.2.202:8081
注意设置端口8081, 否则无法加载. 有些情况可以直接输入IP即可.
Android5.0以上, 直接设置端口即可.
参考Android的真机调试文档.
IOS模拟器, 太穷没有iPhone. 直接打开open UIExplorer.xcodeproj项目, 执行就可以显示.
开发有两种选择, 一种是直接基于ReactNative开发, 一种是把ReactNative集成到现有的App中, 对于第二种, 我们就需要关注, ReactNative会增大多少代码呢?
使用最基本的HelloWorld做测试, ReactNative也是生成一个简单HelloWorld的JS. 最新生成的HelloWorld的大小是1.4M, 加上ReactNative的是7.6M, 框架大约6.2M左右, 各位可以权衡一下使用.
ReactNative的UIExplorer已经包含了大量示例, 很接近原生, 非常绚丽, 速度也很快. 如Android的ViewPager
OK, 好的开始是成功的一半, 继续探索吧! Enjoy it!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
接着上一篇vue慢速入门教程学习。4.组件使用基础什么是组件?组件可以理解为可重用的自定义HTML。可以使用一堆组件来构造大型应用,任意类型的应用界面都可以抽象
本文实例讲述了ZendFramework入门教程之Zend_View组件用法。分享给大家供大家参考,具体如下:Zend_View组件可以实现MVC模式中视图部分
相关阅读:AngularJS入门教程之AngularJS表达式AngularJS入门教程之AngularJS指令在前面表达式和指令的教程中了解到,Angular
关于LoadRunner基础入门教程的介绍就到这里了,希望对大家有所帮助!想要详细了解LoadRunner基础入门教程,可以继续关注软件问题的最新动态。注意
本文详细讲述了Docker集群的创建与管理。分享给大家供大家参考,具体如下:在《Docker简单安装与应用入门教程》中编写一个应用程序,并将其转化为服务,在《D