关于V_Layout的使用总结

VLayout通过分块Adapter实现RecyclerView的多样化布局效果,提供包括线性、网格等10种LayoutHelper子类,支持自定义属性及组合使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

VLayout在处理RecyclerView多布局时使用了分块Adapter,也就是一个RecyclerView存在多个Adapter。最后通过一个总的Adapter整合了所有。

核心类

VirtualLayoutManager

重写了RecyclerView的原生LinearLayoutManager,来间接管理各个Adapter,所以使用VLayout必然要配置VirtualLayoutManager。

VirtualLayoutManager virtualLayoutManager = new VirtualLayoutManager(this);

   VirtualLayoutManager virtualLayoutManager = new VirtualLayoutManager(this);
   recyclerView.setLayoutManager(virtualLayoutManager);
LayoutHelper

如果VirtualLayoutManager是间接管理各个Adapter,那么 LayoutHelper就是负责管理自己所属的Adapter。VLayout的多样化也正是体现在了LayoutHelper子类的多样化。

  • LinearLayoutHelper(线性布局)
  • GridLayoutHelper(网格布局)
  • FixLayoutHelper(固定布局)
  • ScrollFixLayoutHelper(可选的固定布局)
  • FloatLayoutHelper(浮动布局)
  • ColumnLayoutHelper(格栅布局)
  • SingleLayoutHelper(通栏布局)
  • OnePlusNLayoutHelper(一拖N布局)
  • StickyLayoutHelper(吸边布局)
  • StaggeredGridLayoutHelper(瀑布流布局)

VLayout提供了这10种布局效果,基本上已经可以应付我们碰到的各种需求。

创建一种布局Adapter
public class LinearAdapter extends DelegateAdapter.Adapter<LinearAdapter.MyHolder> {


    List<String> data;


    public LinearAdapter(List<String> data) {
        this.data = data;
    }


    @Override
    public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {


        TextView textView = new TextView(parent.getContext());

        textView.setBackgroundColor(Color.WHITE);

        textView.setLayoutParams(new ViewGroup.LayoutParams(-1, 100));

        return new MyHolder(textView);
    }

    @Override
    public void onBindViewHolder(MyHolder holder, int position) {

        holder.textView.setText(data.get(position));


    }

    @Override
    public int getItemCount() {
        return data.size();
    }


    @Override
    public int getItemViewType(int position) {
        return 0;
    }


    @Override
    public LayoutHelper onCreateLayoutHelper() {

        LinearLayoutHelper l = new LinearLayoutHelper();

        return l;

    }
    
   //View被回收时调用
    @Override
    public void onViewRecycled(@NonNull MyHolder holder) {
        super.onViewRecycled(holder);
    }

	//由于VLayout将整个布局分割开每个Item之间已经没有了关联,所以VLayout提供了这个方法 offsetTotal反应了总的position
    @Override
    protected void onBindViewHolderWithOffset(MyHolder holder, int position, int offsetTotal) {
        super.onBindViewHolderWithOffset(holder, position, offsetTotal);
    }

    public static class MyHolder extends RecyclerView.ViewHolder {


        TextView textView;

        public MyHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView;
        }

    }

}

继承于DelegateAdapter.Adapter用法与RecyclerView.Adapter相同,这里多了个硬性重写方法onCreateLayoutHelper() 返回一个layoutHelper,也就是指定当前Adapter需要使用哪种类型。 我们指定一个线性的。

组装各个Adapter
        VirtualLayoutManager virtualLayoutManager = new VirtualLayoutManager(this);
        recyclerView.setLayoutManager(virtualLayoutManager);

        DelegateAdapter delegateAdapter = new DelegateAdapter(virtualLayoutManager, true);

        delegateAdapter.addAdapter(new LinearAdapter(getData()));
        delegateAdapter.addAdapter(new FixAdapter());
 
        recyclerView.setAdapter(delegateAdapter);

        RecyclerView.RecycledViewPool pool = new RecyclerView.RecycledViewPool();
        pool.setMaxRecycledViews(0, 20);

        recyclerView.setRecycledViewPool(pool);

通过DelegateAdapter将各个DelegateAdapter.Adapter包装起来实现了RecyclerView的多样化。如果一屏内相同类型的 View 个数比较多,需要设置一个合适的大小,防止来回滚动时重新创建 View使用自定义的复用池。

LayoutHelper属性详情
公共属性
    layoutHelper.setItemCount(4);// 设置布局里Item个数
    layoutHelper.setPadding(10,10,10,10);// 设置LayoutHelper的子元素相对LayoutHelper边缘的距离
    layoutHelper.setMargin(10,10,10,10);// 设置LayoutHelper边缘相对父控件(即RecyclerView)的距离
    layoutHelper.setBgColor(Color.GRAY);// 设置背景颜色
    layoutHelper.setAspectRatio(6);// 设置设置布局内每行布局的宽与高的比
私有属性
 	 linearLayoutHelper.setDividerHeight(1); // 设置每行Item的距离   

    gridLayoutHelper.setWeights(new float[]{40, 30, 30});//设置每行中 每个网格宽度 占 每行总宽度 的比例
    gridLayoutHelper.setVGap(20);// 控制子元素之间的垂直间距
    gridLayoutHelper.setHGap(20);// 控制子元素之间的水平间距
    gridLayoutHelper.setAutoExpand(false);//是否自动填充空白区域
    gridLayoutHelper.setSpanCount(3);// 设置每行多少个网格
    // 通过自定义SpanSizeLookup来控制某个Item的占网格个数
    gridLayoutHelper.setSpanSizeLookup(new GridLayoutHelper.SpanSizeLookup() {
        @Override
        public int getSpanSize(int position) {
            if (position > 7 ) {
                return 3;
                // 第7个位置后,每个Item占3个网格
            }else {
                return 2;
                // 第7个位置前,每个Item占2个网格
            }
        }
    });		

	fixLayoutHelper.setAlignType(FixLayoutHelper.TOP_LEFT);// 设置吸边时的基准位置(alignType)
	fixLayoutHelper.setX(30);// 设置基准位置的横向偏移量X
	fixLayoutHelper.setY(50);// 设置基准位置的纵向偏移量Y

	scrollFixLayoutHelper.setAlignType(FixLayoutHelper.TOP_LEFT);// 设置吸边时的基准位置(alignType)
	scrollFixLayoutHelper.setX(30);// 设置基准位置的横向偏移量X
	scrollFixLayoutHelper.setY(50);// 设置基准位置的纵向偏移量Y
	scrollFixLayoutHelper.setShowType(ScrollFixLayoutHelper.SHOW_ON_ENTER);// 设置Item的显示模式 

	SHOW_ALWAYS:永远显示(即效果同固定布局)
	SHOW_ON_ENTER:默认不显示视图,当页面滚动到该视图位置时才显示;
	SHOW_ON_LEAVE:默认不显示视图,当页面滚出该视图位置时才显示

	floatLayoutHelper.setDefaultLocation(300,300);// 设置布局里Item的初始位置

 	columnLayoutHelper.setWeights(new float[]{30, 40, 30});// 设置该行每个Item占该行总宽度的比例

	stickyLayoutHelper.setStickyStart(true);
	// true = 组件吸在顶部
	// false = 组件吸在底部
	
	stickyLayoutHelper.setOffset(100);// 设置吸边位置的偏移量

	staggeredGridLayoutHelper.setLane(3);// 设置控制瀑布流每行的Item数
	staggeredGridLayoutHelper.setHGap(20);// 设置子元素之间的水平间距
	staggeredGridLayoutHelper.setVGap(15);// 设置子元素之间的垂直间距

参照

Android开源库V - Layout:淘宝、天猫都在用的UI框架,赶紧用起来吧!

``` class VideoWindow(QWidget): def __init__(self): super().__init__() self.setWindowTitle("远程摄像头监控 v2022.10.13.001") self.setWindowIcon(QIcon('./images/logo.png')) self.resize(777, 555) # 选择本电脑IP camera_label = QLabel("选择本电脑IP:") # ip列表 # 获取本地电脑的ip地址列表 hostname, alias_list, ip_addr_list = socket.gethostbyname_ex(socket.gethostname()) # print(hostname) # DESKTOP # print(alias_list) # [] # print(ip_addr_list) # ['192.168.47.1', '192.168.208.1', '192.168.31.53'] ip_addr_list.insert(0, "0.0.0.0") self.combox = QComboBox() self.combox.addItems(ip_addr_list) self.ip_addr_list = ip_addr_list # 本地端口 port_label = QLabel("本地端口:") self.port_edit = QLineEdit("9090") g_1 = QGroupBox("监听信息") g_1.setFixedHeight(60) g_1_h_layout = QHBoxLayout() g_1_h_layout.addWidget(camera_label) g_1_h_layout.addWidget(self.combox) g_1_h_layout.addWidget(port_label) g_1_h_layout.addWidget(self.port_edit) g_1.setLayout(g_1_h_layout) # 启动显示 self.camera_open_close_btn = QPushButton(QIcon("./images/shexiangtou.png"), "启动显示") self.camera_open_close_btn.clicked.connect(self.camera_open_close) self.record_video_btn = QPushButton(QIcon("./images/record.png"), "开始录制") self.record_video_btn.clicked.connect(self.recorde_video) save_video_path_setting_btn = QPushButton(QIcon("./images/folder.png"), "设置保存路径") save_video_path_setting_btn.clicked.connect(self.save_video_path_setting) g_2 = QGroupBox("功能操作") g_2.setFixedHeight(60) g_2_h_layout = QHBoxLayout() g_2_h_layout.addWidget(self.camera_open_close_btn) g_2_h_layout.addWidget(self.record_video_btn) g_2_h_layout.addWidget(save_video_path_setting_btn) g_2.setLayout(g_2_h_layout) # --------- 整体布局 --------- h_layout = QHBoxLayout() h_layout.addWidget(g_1) h_layout.addWidget(g_2) h_layout.addStretch(1) v_layout = QVBoxLayout() v_layout.addLayout(h_layout) # 创建底部的显示区域 self.stacked_layout_capture_view = ShowCaptureVideoWidget() v_layout.addWidget(self.stacked_layout_capture_view) self.setLayout(v_layout) # 定时刷新视频画面 self.timer = QTimer() self.timer.timeout.connect(self.show_video_image) self.load_time = 0 self.load_time_all = 0```解释每句代码
03-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值