IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 【高级UI】【030】自定义LayoutManager -> 正文阅读

[移动开发]【高级UI】【030】自定义LayoutManager

前言

RecyclerView的核心功能,并不是由自己来完成的,而是转交给LayoutManager来完成的

LayoutManager负责的功能有:布局管理,滑动管理,缓存管理

自定义流式布局管理器 - FlowLayoutManager

这里,我们自定义了一个流式布局管理器,来演示LayoutManager是如何工作的

代码比较简单,对标准流程做了简化了,主要是为了演示,在性能和和细节上并不够好


	public class MainActivity extends AppCompatActivity {
	
	    @Override
	    protected void onCreate(Bundle savedInstanceState) {
	        super.onCreate(savedInstanceState);
	        setContentView(R.layout.activity_main);
	        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
	        FlowLayoutManager layoutManager = new FlowLayoutManager();
	        recyclerView.setLayoutManager(layoutManager);
	        Adapter adapter = new Adapter();
	        recyclerView.setAdapter(adapter);
	    }
	}


	public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
	
	    String[] datas = new String[300];
	
	    public Adapter() {
	        initData();
	    }
	
	    @Override
	    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
	        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view_pager, parent, false);
	        return new ViewHolder(view);
	    }
	
	    @Override
	    public void onBindViewHolder(ViewHolder holder, int position) {
	        holder.btn.setText(datas[position]);
	    }
	
	    @Override
	    public int getItemCount() {
	        return datas.length;
	    }
	
	    public class ViewHolder extends RecyclerView.ViewHolder {
	
	        Button btn;
	
	        public ViewHolder(View itemView) {
	            super(itemView);
	            btn = itemView.findViewById(R.id.btn);
	        }
	    }
	
	    protected void initData() {
	        String[] randoms = new String[]{"X", "XXXXXX", "XXXXXXXXXXXXX", "XXXXXXXXXXXXXX", "XXXXXXXXXXXXXXXXXXXX", "XXXXXXXXXXXXXXXXXXXX", "XXX", "XXXXXXXXXXXXX"};
	        for (int i = 0; i < datas.length; i++)
	            datas[i] = randoms[(int) (Math.random() * randoms.length)];
	    }
	}


	//自定义流式布局管理器
	//这个Demo主要是为了演示自定义LayoutManager
	//很多代码都做了简化处理,在性能上并不够好
	public class FlowLayoutManager extends RecyclerView.LayoutManager {
	
	    //保存所有item偏移量信息,所有数据高度和
	    int totalHeight = 0;
	    SparseArray<Rect> itemBounds = new SparseArray<>();
	
	    //滑动偏移量
	    int verticalScrollOffset = 0;
	
	    @Override
	    public RecyclerView.LayoutParams generateDefaultLayoutParams() {
	        return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
	    }
	
	    @Override
	    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
	
	        //摆放
	        if (getItemCount() <= 0)
	            return;
	        //布局动画
	        if (state.isPreLayout())
	            return;
	        //将视图分离放入scrap缓存中,以准备重新对view进行排版
	        detachAndScrapAttachedViews(recycler);
	
	        int offsetY = 0;
	        int offsetX = 0;
	        int itemHeight = 0;
	        for (int i = 0; i < getItemCount(); i++) {
	            View view = recycler.getViewForPosition(i);
	            addView(view);
	            measureChildWithMargins(view, 0, 0);
	            int w = getDecoratedMeasuredWidth(view);
	            int h = getDecoratedMeasuredHeight(view);
	            itemHeight = h;
	            Rect bound = itemBounds.get(i);
	            if (bound == null)
	                bound = new Rect();
	            //需要换行
	            if (offsetX + w > getWidth()) {
	                //换行的View的值
	                offsetY += h;
	                offsetX = w;
	                bound.set(0, offsetY, w, offsetY + h);
	            } else {
	                //不需要换行
	                bound.set(offsetX, offsetY, offsetX + w, offsetY + h);
	                offsetX += w;
	            }
	            //计算前View的布局区域,然后放到allItemframs数组
	            itemBounds.put(i, bound);
	        }
	        totalHeight = offsetY + itemHeight;
	
	        //回收不可见的元素
	        recyclerViewFillView(recycler, state);
	    }
	
	    @Override
	    public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
	        detachAndScrapAttachedViews(recycler);
	        //实际滑动距离
	        int trval = dy;
	        if (verticalScrollOffset + dy < 0) {
	            trval = -verticalScrollOffset;
	        } else if (verticalScrollOffset + dy > totalHeight - getHeight()) {
	            trval = totalHeight - getHeight() - verticalScrollOffset;
	        }
	
	        //边界值判断
	        verticalScrollOffset += trval;
	
	        //平移容器内的item
	        offsetChildrenVertical(trval);
	        recyclerViewFillView(recycler, state);
	        return trval;
	    }
	
	    @Override
	    public boolean canScrollVertically() {
	        return true;
	    }
	
	    protected void recyclerViewFillView(RecyclerView.Recycler recycler, RecyclerView.State state) {
	        //清空RecyclerView的子View
	        detachAndScrapAttachedViews(recycler);
	        Rect phoneFrame = new Rect(0, verticalScrollOffset, getWidth(), verticalScrollOffset + getHeight());
	        //将滑出屏幕的view进行回收
	        Rect childRect = new Rect();
	        for (int i = 0; i < getChildCount(); i++) {
	            View childView = getChildAt(i);
	            Rect child = itemBounds.get(i);
	            if (!Rect.intersects(phoneFrame, child))
	                removeAndRecycleView(childView, recycler);
	        }
	
	        //可见区域出现在屏幕上的子view
	        for (int j = 0; j < getItemCount(); j++)
	            if (Rect.intersects(phoneFrame, itemBounds.get(j))) {
	                //scrap回收池里面拿的
	                View scrap = recycler.getViewForPosition(j);
	                measureChildWithMargins(scrap, 0, 0);
	                addView(scrap);
	                Rect frame = itemBounds.get(j);
	                layoutDecorated(scrap, frame.left, frame.top - verticalScrollOffset, frame.right, frame.bottom - verticalScrollOffset);
	            }
	    }
	}

源码下载

Android自定义FlowLayoutManager

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-04-07 22:51:12  更:2022-04-07 22:51:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 21:26:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码