Sponsored

SwiftUIতে টিকটক স্টাইল ইন্টারফেস তৈরি

0
70

টিকটক স্টাইল ইন্টারফেস কিভাবে তৈরি করা যায়, তা দেখব। আমরা ফোকাস করব ভিডিও প্লেয়ারটায়। আর একটার পর আরেকটা ভিডিও স্ক্রল কিভাবে করা যায়, এসব।

উদাহরণে আমরা লোকাল ভিডিও থেকে ভিডিও প্লে করব। লোকাল ভিডিও এর পরিবর্তে অনলাইন ভিডিও URL দিলেও একই রকম কাজ করবে।

এর আগে একটা লেখা লিখেছি SwifUI অ্যাপে ফুল উইডথ ভিডিও ব্যাকগ্রাউন্ড নিয়ে। ঐখানে দেখেছি কিভাবে ভিডিও প্লে করা যায়। কঠিন কিছু না। ভিডিও প্লে করার জন্য অ্যাপলের নিজস্ব ফ্রেমওয়ার্ক AVkit রয়েছে। তা ইম্পোর্ট করে নিলেই হবে।

import SwiftUI
import AVKit
struct ContentView: View {
    var body: some View {
        if let url = Bundle.main.url(forResource: "videoName", withExtension: "mp4") {
            VideoPlayer(player: AVPlayer(url: url))
        } else {
            Text("Video Not Found")
        }
    }
}

এখানে VideoPlayer এর ভেতর AVPlayer পাস করেছি। আর AVPlayer এ ভিডিও URL পাস করেছি। যদি প্রজেক্টে নির্দিষ্ট নামে ভিডিও রাখি, তাহলে দেখব ভিডিও প্লে করতে পারছি।

উপরের উদাহরণে আমরা লোকাল ভিডিও প্লে করেছি। চাইলে রিমোট ভিডিও প্লে করতে পারি। একই রকমঃ

import SwiftUI
import AVKit
struct ContentView: View {
    var body: some View {
        
        if let url = URL(string: "https://download.samplelib.com/mp4/sample-30s.mp4") {
            VideoPlayer(player: AVPlayer(url: url))
        } else {
            Text("Video Not Found")
        }
    }
}

দুই ভাবেই দেখেছি ভিডিও প্লে করতে পেরেছি। টিকটকে আমরা দেখি ভিডিও অটো প্লে হয়। তাও করতে পারব। কোডটা এভাবে লিখতে হবেঃ

import SwiftUI
import AVKit
struct ContentView: View {
    @State private var player: AVPlayer?
    var body: some View {
        if let url = URL(string: "https://download.samplelib.com/mp4/sample-30s.mp4") {
            VideoPlayer(player: player)
                .onAppear {
                    player = AVPlayer(url: url)
                    player?.play()
                }
        } else {
            Text("Video Not Found")
        }
    }
}

মানে প্লেয়ার ভিউ লোড হওয়ার সাথে সাথে অটোমেটিক্যালি ভিডিও প্লে হওয়া শুরু হবে।

এবার টিকটকের ইন্টারফেস দেখি। যেখানে ভিডিও প্লেয়ার ভিউ স্ক্রল করা যায়। ভিডিও অটোমেটিক প্লে হয়। কিছু বাটন থাকে। এই তো। যা এভাবে লিখতে পারিঃ

import SwiftUI
import AVKit

struct VideoPlayerView: View {
    let videoName: String
    @State private var player: AVPlayer?
    @State private var isVisible: Bool = false
    @State private var isLiked: Bool = false
    
    var body: some View {
        GeometryReader { geo in
            ZStack {
                if let url = Bundle.main.url(forResource: videoName, withExtension: "mp4") {
                    VideoPlayer(player: player)
                        .onAppear {
                            setupPlayer(url: url)
                        }
                        .onDisappear {
                            stopPlayer()
                        }
                        .edgesIgnoringSafeArea(.all)
                } else {
                    Text("Video Not Found")
                        .foregroundColor(.white)
                        .background(Color.black.edgesIgnoringSafeArea(.all))
                }
                
                // Overlay UI
                VStack {
                    Spacer()
                    HStack {
                        Spacer()
                        VStack(spacing: 20) {
                            // Like Button
                            Button(action: { isLiked.toggle() }) {
                                VStack {
                                    Image(systemName: isLiked ? "heart.fill" : "heart")
                                        .font(.system(size: 40))
                                        .foregroundColor(isLiked ? .red : .white)
                                    Text("662.7K")
                                        .foregroundColor(.white)
                                        .font(.caption)
                                }
                            }
                            // Comment Button
                            Button(action: { print("Comment tapped") }) {
                                VStack {
                                    Image(systemName: "message.fill")
                                        .font(.system(size: 40))
                                        .foregroundColor(.white)
                                    Text("22.1K")
                                        .foregroundColor(.white)
                                        .font(.caption)
                                }
                            }
                            // Share Button
                            Button(action: { print("Share tapped") }) {
                                VStack {
                                    Image(systemName: "arrowshape.turn.up.right.fill")
                                        .font(.system(size: 40))
                                        .foregroundColor(.white)
                                    Text("64K")
                                        .foregroundColor(.white)
                                        .font(.caption)
                                }
                            }
                        }
                        .padding(.bottom, 100)
                        .padding(.trailing, 20)
                    }
                }
            }
            .onChange(of: geo.frame(in: .global).minY) { old, newValue in
                handleVisibility(newValue)
            }
        }
        .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
        .edgesIgnoringSafeArea(.all)
    }
    
    // MARK: - Helper Methods
    private func setupPlayer(url: URL) {
        player = AVPlayer(url: url)
        player?.play()
        player?.isMuted = false
    }
    
    private func stopPlayer() {
        player?.pause()
        player?.replaceCurrentItem(with: nil)
        player = nil
    }
    
    private func handleVisibility(_ yPosition: CGFloat) {
        // Detect if the video is visible
        if yPosition > -UIScreen.main.bounds.height && yPosition < UIScreen.main.bounds.height {
            if !isVisible {
                player?.play()
                isVisible = true
            }
        } else {
            if isVisible {
                stopPlayer()
                isVisible = false
            }
        }
    }
}

#Preview{
    VideoPlayerView(videoName: "video1")
}

এটা হচ্ছে প্লেয়ার ভিউ। যেখানে একটা ভিডিও প্লে হবে। এবং ভিডিও এর উপর থাকা বাটন গুলো যোগ করেছি। কোড কিন্তু কমপ্লেক্স কিছু না।

এখানে GeometryReader ব্যবহার করেছি ভিডিও স্ক্রল করে নেক্সট ভিডিওতে গিয়েছে কিনা, তা ডিটেক্ট করার জন্য। যখন অন্য আরেকটা ভিডিওতে চলে যাবে, তখন আগের ভিডিও প্লে বন্ধ করে দিবে।

এবার লিস্ট অনুযায়ী স্ক্রল ভিউ তৈরি করবঃ

import SwiftUI

struct HomeView: View {
    let videos : [String]
    var body: some View {
        ScrollView(showsIndicators: false) {
            LazyVStack(spacing: 0) {
                ForEach(videos, id: \.self) { video in
                    VideoPlayerView(videoName: video)
                }
            }
            .scrollTargetLayout()
        }
 
        .scrollTargetBehavior(.paging)
        .edgesIgnoringSafeArea(.all)
    }
}

স্ক্রল ভিউ স্মুথ হয়। মানে একটা ভিডিও যদি স্ক্রল করে উপরের দিকে উঠাই, তাহলে অর্ধেক উপরে উঠবে। কিন্তু টিকটকে আমরা দেখব একটা ভিডিও অল্প একটু স্ক্রল করলে পুরোটাই স্ক্রল হবে। এটাকে বলে পেইজিং স্ক্রল। যা করেছি .scrollTargetBehavior(.paging) মডিফায়ার ব্যবহার করে। এই তো।

টিকটকের হোম মূল ভিউ একটা ট্যাব ভিউর মত। যা এভাবে লিখতে পারিঃ

import SwiftUI

struct ContentView: View {
    // Ensure videos are in the app bundle
    let videos =     ["video1", "video2", "video3"]
    var body: some View {
        
        TabView{
            
            HomeView(videos: videos)
                .tabItem {
                    Label("Home", systemImage: "house.fill")
                }
            Text("Friends")
                .tabItem {
                    Label("Friends", systemImage: "person.2.fill")
                }
            
            Text("Add video")
                .tabItem {
                    Label("Add", systemImage: "plus")
                }
            
            Text("Inbox")
                .tabItem {
                    Label("Inbox", systemImage: "message.fill")
                }
            Text("Profile")
                .tabItem {
                    Label("Profile", systemImage: "person.fill")
                }
        }
    }
}

আউটপুট পাবো এমনঃ

কোড গুলো গিটহাবে আপলোড করে দিয়েছি। আমি লোকাল ভিডিও থেকে প্লে করেছি। একই ভাবে চাইলে রিমোট ভিডিও প্লে করা যাবে। iOS রিলেটেড অন্যান্য লেখা গুলো এখানে পাওয়া যাবে।

যখন রিয়েল প্রজেক্ট করবেন, তখন হয়তো API ব্যবহার করতে হবে। মূল কনসেফট প্রায় একই। SwiftUI নিয়ে ইংরেজিতে বেশি কিছু লেখা লিখেছি। বাংলাতে কমই লিখেছি। আস্তে আস্তে লেখার চেষ্টা করছি। ঐখানে বেশ কিছু টপিক্স নিয়ে লিখেছি। আশা করি কাজে আসবে।

Sponsored
Sponsored
Search
Categories
Read More
News
মায়াবী চোখ নিয়ে উক্তি ও স্ট্যাটাস - Banglaph
সুন্দর মেয়েদের চোখ আসলেই অনেক মায়াবী। আপনি কি সেইসব সুন্দর মেয়েদের মায়াবী চোখের প্রেমে পরেছেন?...
By Nettumi 2026-10-02 22:55:22 0 79
Nulled
TripVendor v1.0 - Multi Vendor Tour and Travel Booking Platform PHP Script
TripVendor v1.0 – Multi Vendor Tour and Travel Booking Platform PHP Script Free Download....
By Nettumi 2026-09-17 18:27:02 0 40
Hacking Course
ইনফিনিক্স এর ল্যাপটপ ইনবুক ওয়াইটু প্লাস পাওয়া যাচ্ছে সুলভ দামে - Banglatech24.com
গত বছর ইনফিনিক্স বাংলাদেশের বাজারে প্রথমবারের মতো তাদের ল্যাপটপ নিয়ে আসে। সেই ধারাবাহিকতায় দেশে...
By Nettumi 2026-09-25 09:39:27 0 51
Nulled
অটোমেটেড নিউজ পোর্টাল তৈরির দিন শেষ! এবার অটো আরএসএস টিউনিং ও ট্রান্সলেশনের মাধ্যমে হয়ে উঠুন স্মার্ট পাবলিশার - WP Automatic by CS v187 | Techtunes | টেকটিউনস
ভবিষ্যৎ মোবাইল ফোন (2008-2010) মাহমুদ অপু
By Nettumi 2026-09-21 05:33:43 0 38
Nulled
TailorPos v1.3.1 - POS and Order Management System PHP Script
TailorPos v1.3.1 – POS and Order Management System PHP Script Free Download. TailorPOS is...
By Nettumi 2026-09-17 18:37:21 0 64
‎ ‎ ‎
Nettumi https://nettumi.com