Compose support(Android)

Before integrating the VideoFeed and StoryBlock components in your Android Compose project, make sure to follow the official Firework Getting Started Guide for Android SDK.

Video Feed

An Activity that uses the VideoFeed component must extend ComponentActivity or a subclass of ComponentActivity.

A Fragment that uses the VideoFeed component must extend Fragment or a subclass of Fragment.

Then you can add VideoFeed to your project

@Composable
private fun VideoFeed(modifier: Modifier) {
    AndroidView(
        modifier = modifier.fillMaxSize(),
        factory = { context ->
        fwVideoFeedView(context) {
            viewOptions {
                ......
            }
        }
    })
}

For viewOptions detail configuration, refer to the video-feed-integration doc, you are allowed to fill in more options here.

Storyblock

An Activity that uses the Storyblock component must extend FragmentActivity or a subclass of FragmentActivity.

A Fragment that uses the Storyblock component must extend Fragment or a subclass of Fragment.

Use single storyblock

Create a Storyblock code down below, and add the widget to your compose code.

@Composable
fun StoryblockItem(modifier: Modifier = Modifier) {
    val context = LocalContext.current
    // create a FwStoryBlockView
    val storyBlockView = FwStoryBlockView(context)
    // init view options
    val viewOptions = viewOptions {
        baseOptions {
            feedResource(FeedResource.Discovery)
        }
        playerOptions {
            playerMode(PlayerMode.FIT_MODE)
        }
        storyBlockOptions {
            enableAutoPlay(true)
            showFullScreenIcon(true)
        }
    }

    AndroidView(
        modifier = modifier.padding(start = 20.dp, top = 50.dp, end = 20.dp, bottom = 50.dp),
        factory = { _ ->
            // initial storyblock
            storyBlockView.init( 
                // if you are using fragment as container, replace it with childFragmentManager
                (context as FragmentActivity).supportFragmentManager, 
                context,
                viewOptions,
                true
            )
            storyBlockView.apply {
                // set layout parameters 
                layoutParams = ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
                )
                setOnErrorListener { e ->
                    // handle and record the error
                }
                
                // set other listeners
                ......
            }
        }
    )
    
    DisposableEffect(Unit) {
        onDispose {
            // invoke destroy when disposable
            storyBlockView.destroy() 
        }
    }
}

To view the configuration details of the viewOptions, refer to the Storyblock doc, you are allowed to fill in more options here.

Note

Don't forget to destroy the FwStoryBlockView in DisposableEffect

Use multiple storyblocks in Grid

Create and Initialize the FwStoryBlockView with view options.

@Composable
fun StoryBlockItem(modifier: Modifier = Modifier, key: String, androidViewMap: MutableMap<String, FwStoryBlockView>) {
    val context = LocalContext.current
    val storyblockAndroidView = androidViewMap.getOrPut(key) {
        val storyBlockView = FwStoryBlockView(context = LocalContext.current)
        // init view options
        val viewOptions = viewOptions {
            baseOptions {
                feedResource(FeedResource.Discovery)
            }
            playerOptions {
                playerMode(PlayerMode.FIT_MODE)
            }
            storyBlockOptions {
                enableAutoPlay(true)
                showFullScreenIcon(true)
            }
        }
        storyBlockView.init(
            (context as AppCompatActivity).supportFragmentManager,
            context,
            viewOptions,
            true,
        )
        storyBlockView.apply {
            layoutParams = ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT,
            )
            storyBlockView.setOnErrorListener { e ->
                // handle the error
            }
        }
    }

    AndroidView(
        modifier = modifier
            .padding(top = 16.dp)
            .size(width, height),
        factory = { _ ->
            storyblockAndroidView
        },
        ...... 
    )
}

Integrate with LazyVerticalGrid Component

Build LazyVerticalGridItem demo code.

@Suppress("MagicNumber")
val list = List(50) {
    if (it == 3 || it == 24) {
        "View"
    } else {
        "Text"
    }
}

private val width = 150.dp
private val height = 250.dp

@Composable
fun LazyVerticalGridItem(modifier: Modifier = Modifier) {
    val androidViewMap = remember { mutableMapOf<String, FwStoryBlockView>() }
    LazyVerticalGrid(columns = GridCells.Fixed(2)) {
        items(list.size) { index ->
            if (list[index] == "View") {
                StoryBlockItem(modifier = modifier, key = "View_${index}", androidViewMap = androidViewMap)
            } else {
                Text(text = "Text $index", modifier = modifier.size(width, height))
            }
        }
    }

    DisposableEffect(Unit) {
        onDispose {
            // destroy all the cached storyblock view
            for (v in androidViewMap.values) {
                v.destroy()
            }
        }
    }
}

You can integrate LazyVerticalGridItem into your compose code.

Note

Don't forget to destroy the FwStoryBlockView in DisposableEffect

Last updated

Was this helpful?