Configure Video Feed View

FwVideoFeedView is a custom view that displays video thumbnails in a scrollable feed. Users can tap on any thumbnail to launch the fullscreen video player. The feed supports multiple layout types (horizontal, vertical, grid) and can display content from various sources.

Integration

Add to Layout

Add FwVideoFeedView to your layout XML file:

<com.firework.videofeed.FwVideoFeedView
    android:id="@+id/videoFeedView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Initialize

Initialize the feed view by calling init():

class MainActivity : AppCompatActivity() {
    private lateinit var videoFeedView: FwVideoFeedView
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        videoFeedView = findViewById(R.id.videoFeedView)
        
        // Simple initialization with defaults
        videoFeedView.init()
    }
    
    override fun onDestroy() {
        videoFeedView.destroy()
        super.onDestroy()
    }
}

Initialize with ViewOptions

Provide ViewOptions to customize the feed:

val viewOptions = viewOptions {
    baseOptions {
        feedResource(FeedResource.Discovery)
    }
    layoutOptions {
        feedLayout(FeedLayout.GRID)
        columnCount(3)
        itemSpacing(8.dpToPx())
    }
}

videoFeedView.init(viewOptions)

Configuration Options

Feed Source (BaseOption)

Configure the content source for the feed. See Feed Sources for detailed information on each type.

viewOptions {
    baseOptions {
        // Discovery feed
        feedResource(FeedResource.Discovery)
        
        // Or Channel feed
        feedResource(FeedResource.Channel(channelId = "your_encoded_channel_id"))
        
        // Or Playlist feed
        feedResource(
            FeedResource.Playlist(
                channelId = "your_encoded_channel_id",
                playlistId = "your_encoded_playlist_id"
            )
        )
        
        // Or Single content
        feedResource(FeedResource.SingleContent(contentId = "your_encoded_content_id"))
        
        // Or SKU-based feed
        feedResource(
            FeedResource.Sku(
                channelId = "your_encoded_channel_id",
                productIds = listOf("sku1", "sku2")
            )
        )
    }
}

For more feed types (HashtagPlaylist, DynamicContent, ShareUrl), see BaseOption Configuration.

Layout Configuration (LayoutOption)

Control the visual layout and appearance of the video feed.

Feed Layout Types

viewOptions {
    layoutOptions {
        // Horizontal scrolling row (default)
        feedLayout(FeedLayout.HORIZONTAL)
        
        // Or vertical scrolling column
        feedLayout(FeedLayout.VERTICAL)
        
        // Or multi-column grid
        feedLayout(FeedLayout.GRID)
        columnCount(3) // Only for grid layout
    }
}

Spacing and Appearance

viewOptions {
    layoutOptions {
        // Item spacing
        itemSpacing(12.dpToPx()) // Space between items
        
        // Background color
        backgroundColor(Color.parseColor("#F5F5F5"))
        
        // Rounded corners
        roundedCorner(true)
        roundedCornerRadius(12.dpToPx())
        
        // Play icon
        showPlayIcon(true)
        playIconWidth(32.dpToPx())
        
        // Aspect ratio
        aspectRatio(9.0 / 16.0) // 9:16 ratio
    }
}

Title Position

viewOptions {
    layoutOptions {
        // Title overlays thumbnail (default)
        feedTitlePosition(FeedTitlePosition.NESTED)
        
        // Or title appears below thumbnail
        feedTitlePosition(FeedTitlePosition.STACKED)
    }
}

For complete layout options, see LayoutOption Configuration.

Title Configuration (TitleOption)

Customize the appearance of feed titles.

viewOptions {
    titleOptions {
        // Visibility
        showFeedTitle(true)
        
        // Text styling
        feedTitleTextColor(Color.WHITE)
        feedTitleTextSize(18.spToPx())
        feedTitleTextNumberOfLines(2)
        feedTitleTextPadding(12.dpToPx())
        
        // Background
        feedTitleBackgroundColor(Color.parseColor("#80000000"))
        
        // Custom font
        feedTitleTextTypeface(
            ResourcesCompat.getFont(context, R.font.custom_font)
        )
    }
}

Gradient Background

viewOptions {
    titleOptions {
        feedTitleBackgroundDrawable(
            GradientDrawable().apply {
                colors = intArrayOf(
                    Color.parseColor("#667eea"),
                    Color.parseColor("#764ba2")
                )
                gradientType = GradientDrawable.LINEAR_GRADIENT
                orientation = GradientDrawable.Orientation.TOP_BOTTOM
            }
        )
    }
}

For complete title options, see TitleOption Configuration.

Player Configuration (PlayerOption)

Configure the fullscreen video player that opens when users tap on video thumbnails.

viewOptions {
    playerOptions {
        // Autoplay first visible video in feed
        autoplay(true)
        
        // Player display mode
        playerMode(PlayerMode.FIT_MODE) // or FULL_BLEED_MODE
        
        // Auto-play next video when current ends
        autoPlayOnComplete(true)
        
        // UI elements
        showShareButton(true)
        showMuteButton(true)
        showFireworkLogo(false)
        
        // Picture-in-Picture
        enablePipMode(true)
    }
}

For complete player configuration options, see Video Player Configuration.

CTA Configuration (CtaOption)

Configure Call-to-Action button behavior.

viewOptions {
    ctaOptions {
        // CTA visibility delay
        ctaDelay(CtaDelay(3.0f, CtaDelayUnit.SECONDS))
        // Or use percentage
        ctaDelay(CtaDelay(0.5f, CtaDelayUnit.PERCENTAGE))
        
        // CTA highlight delay
        ctaHighlightDelay(CtaDelay(2.0f, CtaDelayUnit.SECONDS))
    }
}

Delay Units:

  • CtaDelayUnit.SECONDS - Delay in seconds (0.0 - 10.0, default: 3)

  • CtaDelayUnit.PERCENTAGE - Percentage of video duration (0.0 - 1.0, default: 0.2)

For CTA handling, see Shopping Integration.

Ad Badge Configuration (AdBadgeOption)

Customize the ad badge appearance on sponsored content.

viewOptions {
    adBadgeOptions {
        // Visibility
        adBadgeIsHidden(false)
        adBadgeShowOnThumbnails(true)
        
        // Appearance
        adBadgeBackColor(Color.parseColor("#FFFECD"))
        adBadgeTextColor(Color.BLACK)
        
        // Label text
        adBadgeLabel(AdBadgeTextType.SPONSORED) // or AdBadgeTextType.AD
        
        // Custom font
        adBadgeTypeface(ResourcesCompat.getFont(context, R.font.custom_font))
    }
}

Chat Configuration (ChatOption)

Configure livestream chat appearance.

viewOptions {
    chatOptions {
        // Chat text color
        chatTextColor(Color.WHITE)
        
        // Chat text shadow
        chatTextShadowColor(Color.BLACK)
        chatTextShadowOffsetX(2f)
        chatTextShadowOffsetY(2f)
        chatTextShadowRadius(4f)
    }
}

Feed Refresh

Manually refresh the feed to reload content:

videoFeedView.refresh()

Example with SwipeRefreshLayout:

swipeRefreshLayout.setOnRefreshListener {
    videoFeedView.refresh()
    swipeRefreshLayout.isRefreshing = false
}

Feed State Monitoring

Feed View State Listener

Monitor feed loading states and respond to state changes:

videoFeedView.setOnFeedViewStateListener { feedViewState ->
    when (feedViewState) {
        is FeedViewState.Loading -> {
            // The feed is currently loading content
         
        }
        is FeedViewState.LoadData -> {
            // Data has been successfully loaded and is available
        }
        is FeedViewState.EmptyFeed -> {
            // The feed has no content to display
        }
        is FeedViewState.EndOfFeed -> {
            // User has reached the end of available content
        }
        is FeedViewState.Error -> {
            // An error occurred while loading feed content
        }
    }
}

Feed View States:

  • Loading - Feed is currently loading content

  • LoadData - Data has been successfully loaded

  • EmptyFeed - Feed has no content to display

  • EndOfFeed - End of available content reached

  • Error - Error occurred with message

Error Listener

Handle errors during feed operations:

videoFeedView.setOnErrorListener { error ->
    when (error) {
        is SdkLevelError.SdkNotInitialized -> {
            // SDK not initialized
            showError("Please initialize Firework SDK first")
        }
        is VideoFeedError.LoadingFailed -> {
            // Feed loading failed
            showError("Failed to load video feed")
        }
        is NetworkError -> {
            // Network error
            showError("Network error. Please check your connection")
        }
        is AdsError -> {
            // Ad-related error
            Log.e("VideoFeed", "Ad error: ${error::class.simpleName}")
        }
        is LivestreamError -> {
            // Livestream error
            Log.e("VideoFeed", "Livestream error: ${error::class.simpleName}")
        }
        else -> {
            showError("An error occurred: ${error::class.simpleName}")
        }
    }
}

Error Types:

  • SdkLevelError.SdkNotInitialized - SDK not initialized

  • VideoFeedError.LoadingFailed - Feed loading failed

  • AdsError - Ad-related errors (VideoLoadFailed, PlaybackFailed, ImaAdFailed)

  • LivestreamError - Livestream errors (MissingLivestreamInitializer, EngineFailed)

  • ShareContentError - Share errors (EmptyShareUrl, SharingFailed)

  • NetworkError - Network-related errors

  • PlayerError - Video playback errors

Feed Item Click Listener

Track when users tap on feed items:

videoFeedView.setOnFeedItemClickListener { feedItem ->
    // Log analytics
    Log.d("VideoFeed", "Video clicked: ${feedItem.title}")
    
    // Access video information
    val videoId = feedItem.id
    val title = feedItem.title
    val index = feedItem.indexInTheList
    val duration = feedItem.duration
    val videoInfo = feedItem.videoInfo
}

FeedItem Properties:

  • id - Video content ID

  • title - Video title

  • indexInTheList - Position in feed

  • duration - Video duration in milliseconds

  • videoInfo - Detailed video information

Lifecycle Management

Destroy in Activity

Call destroy() when the feed view is no longer needed:

class VideoFeedActivity : AppCompatActivity() {
    private lateinit var videoFeedView: FwVideoFeedView
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_video_feed)
        
        videoFeedView = findViewById(R.id.videoFeedView)
        videoFeedView.init()
    }
    
    override fun onDestroy() {
        videoFeedView.destroy()
        super.onDestroy()
    }
}

Destroy in Fragment

In fragments, call destroy() in onDestroyView():

class VideoFeedFragment : Fragment() {
    private var _binding: FragmentVideoFeedBinding? = null
    private val binding get() = _binding!!
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        _binding = FragmentVideoFeedBinding.bind(view)
        
        binding.videoFeedView.init()
    }
    
    override fun onDestroyView() {
        binding.videoFeedView.destroy()
        super.onDestroyView()
        _binding = null
    }
}

Complete Configuration Examples

Grid Layout Feed

class GridFeedActivity : AppCompatActivity() {
    private lateinit var videoFeedView: FwVideoFeedView
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_grid_feed)
        
        videoFeedView = findViewById(R.id.videoFeedView)
        
        val viewOptions = viewOptions {
            baseOptions {
                feedResource(FeedResource.Discovery)
            }
            layoutOptions {
                feedLayout(FeedLayout.GRID)
                columnCount(3)
                itemSpacing(8.dpToPx())
                roundedCorner(true)
                roundedCornerRadius(12.dpToPx())
                backgroundColor(Color.parseColor("#F8F9FA"))
                showPlayIcon(true)
            }
            titleOptions {
                showFeedTitle(true)
                feedTitleTextColor(Color.WHITE)
                feedTitleBackgroundColor(Color.parseColor("#80000000"))
                feedTitleTextSize(14.spToPx())
                feedTitleTextNumberOfLines(2)
            }
            playerOptions {
                autoplay(false)
                showShareButton(true)
                enablePipMode(true)
            }
        }
        
        videoFeedView.init(viewOptions)
    }
    
    override fun onDestroy() {
        videoFeedView.destroy()
        super.onDestroy()
    }
}

Horizontal Story Feed

class StoryFeedActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_story_feed)
        
        val videoFeedView = findViewById<FwVideoFeedView>(R.id.videoFeedView)
        
        val viewOptions = viewOptions {
            baseOptions {
                feedResource(FeedResource.Channel(channelId = "your_channel_id"))
            }
            layoutOptions {
                feedLayout(FeedLayout.HORIZONTAL)
                itemSpacing(16.dpToPx())
                roundedCorner(true)
                roundedCornerRadius(12.dpToPx())
                showPlayIcon(false) // No play icon for story style
                aspectRatio(9.0 / 16.0)
            }
            titleOptions {
                showFeedTitle(false)
            }
            playerOptions {
                autoplay(false)
                scrollingOrientation(ScrollingOrientation.VERTICAL)
            }
        }
        
        videoFeedView.init(viewOptions)
    }
}
class ProductGalleryActivity : AppCompatActivity() {
    private fun loadProductVideos(productSku: String) {
        val videoFeedView = findViewById<FwVideoFeedView>(R.id.productVideos)
        
        // Set up error listener
        videoFeedView.setOnErrorListener { error ->
            Toast.makeText(this, "Error: ${error::class.simpleName}", Toast.LENGTH_SHORT).show()
        }
        
        // Set up state listener
        videoFeedView.setOnFeedViewStateListener { state ->
            when (state) {
                is FeedViewState.Loading -> {
                    progressBar.isVisible = true
                }
                is FeedViewState.LoadData -> {
                    progressBar.isVisible = false
                }
                is FeedViewState.EmptyFeed -> {
                    progressBar.isVisible = false
                    emptyView.isVisible = true
                }
                else -> {}
            }
        }
        
        val viewOptions = viewOptions {
            baseOptions {
                feedResource(
                    FeedResource.Sku(
                        channelId = "your_channel_id",
                        productIds = listOf(productSku)
                    )
                )
            }
            layoutOptions {
                feedLayout(FeedLayout.GRID)
                columnCount(2)
                itemSpacing(8.dpToPx())
                roundedCorner(true)
                showPlayIcon(true)
            }
            playerOptions {
                autoplay(false)
                showShareButton(true)
            }
        }
        
        videoFeedView.init(viewOptions)
    }
}

Important Notes

  • Always call init() before the feed view can display content

  • The SDK must be initialized (via FireworkSdk.init()) before calling init() on the feed view

  • Always call destroy() when the feed view is no longer needed to free resources

  • ViewOptions provided to init() allow complete customization of the feed

  • For grid layout, columnCount determines the number of columns

  • Autoplay on thumbnails can impact battery and data usage

  • Use dpToPx() for density-independent pixel values

  • Use spToPx() for text size values

See Also

Last updated