swiftui使用ScrollView实现左右滑动和上下滑动的效果,仿小红书页面

实现的效果如果所示,顶部的关注用户列表可以左右滑动,中间的内容区域是可以上下滚动的效果,点击顶部的toolbar也可以切换关注/发现/附近不同页面,实现翻页效果。

首页布局

这里使用了NavigationStack组件和tabViewStyle样式配置,tabViewStyle主要是为了实现左右滑动翻页的效果,就是关注,发现和附近的三个页面切换。还有TabView就是控制这三个页面切换的。toolbar+ToolbarItem是为了实现顶部的三个切换菜单还有顶部右侧的搜索按钮。BottomTab是我封装的一个底部四个tab菜单。FollowView是我封装的关注页面的视图。

布局代码:

//
//  Hongshu.swift
//  SwiftBook
//
//  Created by Song on 2024/7/6.
//

import SwiftUI

struct Hongshu: View {
    @State var current = 0
    var body: some View {
        VStack {
            NavigationStack {
                ScrollView(content: {
                    TabView(selection: $current) {
                        // 关注
                        FollowView()
                        .tag(0)
                        // 发现
                        HStack(content: {
                            VStack(content: {
                                CardItem(preImg: "taozi", avatar: "taozi", nickname: "11111", distance: "555")
                                CardItem(preImg: "xigua", avatar: "xigua", nickname: "putao", distance: "11")
                                CardItem(preImg: "hongyou", avatar: "xigua", nickname: "山竹", distance: "53")
                                Spacer()
                            })
                            VStack(content: {
                                CardItem(preImg: "liulian", avatar: "liulian", nickname: "liula", distance: "11")
                                CardItem(preImg: "xigua2", avatar: "xigua2", nickname: "山竹", distance: "53")
                                Spacer()
                            })
                        })
                        .tag(1)
                        // 附近
                        HStack(content: {
                            VStack(content: {
                                CardItem(preImg: "xigua", avatar: "taozi", nickname: "11111", distance: "555")
                                CardItem(preImg: "default", avatar: "xigua", nickname: "putao", distance: "11")
                                CardItem(preImg: "xigua2", avatar: "xigua", nickname: "山竹", distance: "53")
                                Spacer()
                            })
                            VStack(content: {
                                CardItem(preImg: "liulian", avatar: "liulian", nickname: "liula", distance: "11")
                                CardItem(preImg: "taozi", avatar: "xigua2", nickname: "山竹", distance: "53")
                                Spacer()
                            })
                        })
                        .tag(2)
                    }
                    .tabViewStyle(.page(indexDisplayMode: .never))
                    .frame(width: .infinity,
                           height: UIScreen.main.bounds.height - 100)
                })
                .background(.gray.opacity(0.3))
                .navigationBarTitleDisplayMode(.inline)
                .toolbar {
                    ToolbarItem(placement: .principal, content: {
                        HStack(spacing: 30) {
                            Text("关注")
                                .foregroundColor(
                                    current == 0 ? .blue : .black)
                                .onTapGesture {
                                    current = 0
                                }
                            Text("发现")
                                .foregroundColor(
                                    current == 1 ? .blue : .black)
                                .onTapGesture {
                                    current = 1
                                }
                            Text("附近")
                                .foregroundColor(
                                    current == 2 ? .blue : .black)
                                .onTapGesture {
                                    current = 2
                                }
                        }
                    })
                    ToolbarItem(placement: .topBarTrailing, content: {
                        HStack {
                            Image(systemName: "magnifyingglass")
                        }
                    })
                }
            }
            BottomTab()
        }
    }
}

#Preview {
    Hongshu()
}

BottomTab菜单

因为这里要自定义一个中间的红色按钮,所以没有使用系统自带的tabview视图,而是自己定义并实现的一个样式代码。

底部tab菜单实现代码:

//
//  BottomTab.swift
//  SwiftBook
//
//  Created by Song on 2024/7/6.
//

import SwiftUI

struct BottomTab: View {
    @State var sel = "home"
    var body: some View {
        HStack {
            Spacer()
            Text("首页").onTapGesture {
                sel = "home"
            }.foregroundColor(sel == "home" ? .blue : .gray)
            Spacer()
            Text("购物").onTapGesture {
                sel = "shoping"
            }.foregroundColor(sel == "shoping" ? .blue : .gray)
            Spacer()
            Button(action: {
                sel = "publish"
            }, label: {
                Image(systemName: "plus")
                    .padding(.horizontal, 20)
                    .padding(.vertical, 10)
                    .foregroundColor(.white)
                    .background(.red)
                    .cornerRadius(5)
            })
            Spacer()
            Text("消息").onTapGesture {
                sel = "message"
            }.foregroundColor(sel == "message" ? .blue : .gray)
            Spacer()
            Text("我的").onTapGesture {
                sel = "my"
            }.foregroundColor(sel == "my" ? .blue : .gray)
            Spacer()
        }
    }
}

#Preview {
    BottomTab()
}

关注页面

这里的关注页面实现了顶部的左右滑动布局和内容区域的上下滑动布局。这里需要注意的是,因为我们使用了自定义的tabview视图实现了页面底部的菜单,所以这个页面的内容区域底部会被自定义的菜单视图盖住一部分,要给ScrollView添加padding(.bottom, 70)用于抵消这部分遮挡

关注页面代码:

//
//  FollowView.swift
//  SwiftBook
//
//  Created by Song on 2024/7/7.
//

import SwiftUI

struct FollowView: View {
    @State var users = ["xigua", "damangguo", "juzi", "hongyou", "liulian", "lizhi", "putao", "shanchu", "taozi"]

    var body: some View {
        // 关注的用户列表,可以左右滑动
        ScrollView(.vertical, showsIndicators: false) {
            ScrollView(.horizontal, showsIndicators: false) {
                HStack {
                    ForEach(users, id: \.self) { u in
                        Image(u).avator(w: 60, h: 60)
                    }
                }.padding(5)
            }
            ForEach(0 ..< 5) { _ in
                FollowUserCard()
            }
            Spacer()
        }.padding(.bottom, 70)
    }
}

#Preview {
    FollowView()
}

FollowUserCard

这是一个内容区域的card视图内容,为了方便复用,所以封装了一个组件实现。其中Rectangle是为了实现分割线效果,因为设置边框的话,只能给一个视图设置全部的边框,所以就没有使用边框

//
//  FollowUserCard.swift
//  SwiftBook
//
//  Created by Song on 2024/7/7.
//

import SwiftUI

struct FollowUserCard: View {
    @State var commit = ""
    var body: some View {
        VStack {
            // 分割线
            Rectangle()
                .fill(.black)
                .frame(height: 1)
            // 头像和更多
            HStack {
                Image("xigua").avator(w: 30, h: 30)
                Text("你好")
                Text("6天前").foregroundColor(.secondary)
                Spacer()
                Image(systemName: "ellipsis")
            }.padding(.horizontal)
            // 图片
            Image("xigua2")
                .resizable()
                .frame(width: .infinity, height: 300)
                .aspectRatio(contentMode: .fill)
            // 点赞分享
            HStack {
                Image(systemName: "square.and.arrow.up")
                Spacer()
                Image(systemName: "heart")
                Image(systemName: "star")
                Image(systemName: "ellipsis.message")
            }.padding(5)
            // 文字内容
            Text("无籽西瓜已进入香港市场。周至种西瓜有史已久,特别是近十多年来,新品种较多,有“周至红”、“兴城红”、“及醇酥”和“台黑”等一类脆瓤型西瓜").lineLimit(/*@START_MENU_TOKEN@*/2/*@END_MENU_TOKEN@*/)
                .padding(5)
            // 评论
            HStack {
                Image("xigua").avator(w: 30, h: 30).padding(5)
                TextField("请输入评论", text: $commit)
            }
            .background(.gray.opacity(0.1), in: RoundedRectangle(cornerRadius: 20))
            .padding(5)
        }
    }
}

#Preview {
    FollowUserCard()
}

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-21 23:30:03       103 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-21 23:30:03       114 阅读
  3. 在Django里面运行非项目文件

    2024-07-21 23:30:03       93 阅读
  4. Python语言-面向对象

    2024-07-21 23:30:03       99 阅读

热门阅读

  1. Shiro-550反序列化漏洞

    2024-07-21 23:30:03       19 阅读
  2. Kotlin单例、数据类、静态

    2024-07-21 23:30:03       29 阅读
  3. CSP-J模拟赛day1

    2024-07-21 23:30:03       29 阅读
  4. Linux下双网卡NAT组网

    2024-07-21 23:30:03       29 阅读
  5. Node的API基础

    2024-07-21 23:30:03       27 阅读
  6. C2W3.LAB.N-grams+Language Model+OOV

    2024-07-21 23:30:03       25 阅读
  7. 力扣题解(一和零)

    2024-07-21 23:30:03       35 阅读
  8. urllib&requests

    2024-07-21 23:30:03       26 阅读
  9. 接到需求后的开发步骤

    2024-07-21 23:30:03       30 阅读