RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1585909
Accepted
Sirop4ik
Sirop4ik
Asked:2024-07-02 22:02:28 +0000 UTC2024-07-02 22:02:28 +0000 UTC 2024-07-02 22:02:28 +0000 UTC

单击左侧的(远程控制)时如何将焦点返回到同一视图?

  • 772

我有一个这样的屏幕(Andorid TV)

在此输入图像描述

我需要这样做:

  1. 当屏幕打开时,焦点位于左侧面板中的第一个视图上(左侧面板:0)
  2. 用户可以(在遥控器上)上下切换左侧面板中的元素
  3. 如果用户按向右,焦点将移至第一个视图中的右侧面板(右侧面板:0)
  4. 用户可以根据需要在右侧面板中的元素之间移动焦点
  5. 如果用户位于左侧堆栈的右侧面板中,按向左键,则焦点应移动到左侧面板到从其转到右侧面板的元素。也就是说,如果用户位于左侧面板中的第三个元素上并向右按下,那么当他从右侧面板返回到左侧时,焦点应移回到他之前所在的第三个元素。

总的来说,除了第 5 点之外,一切都正常

这是代码

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Test_delete_itTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    shape = RectangleShape
                ) {
                    Greeting()
                }
            }
        }
    }
}

@Composable
fun Greeting() {
    val leftPanelFocusRequester: FocusRequester = remember { FocusRequester() }
    val rightPanelFocusRequester: FocusRequester = remember { FocusRequester() }

    Row(modifier = Modifier
        .fillMaxSize()
    ) {
        LeftPanel(
            focusRequester = leftPanelFocusRequester,
            onRightDirectionClicked = {
                rightPanelFocusRequester.requestFocus()
            }
        )
        RightPanel(focusRequester = rightPanelFocusRequester)
    }
}

@Composable
fun RowScope.LeftPanel(
    focusRequester: FocusRequester,
    onRightDirectionClicked: () -> Unit
) {
    LaunchedEffect(Unit) {
        this.coroutineContext.job.invokeOnCompletion {
            focusRequester.requestFocus()
        }
    }

    Column(
        modifier = Modifier
            .background(Color.Blue.copy(alpha = 0.1f))
            .fillMaxHeight()
            .weight(1f)
            .onKeyEvent {
                if (it.key == Key.DirectionRight) {
                    onRightDirectionClicked()
                    true
                } else {
                    false
                }
            },
        verticalArrangement = Arrangement.spacedBy(8.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        repeat(5) {
            Button(
                modifier = Modifier
                    .let { modifier ->
                        if (it == 0) {
                            modifier.focusRequester(focusRequester)
                        } else {
                            modifier
                        }
                    },
                onClick = { }
            ) {
                Text(text = "Left Panel: $it")
            }
        }
    }
}

@Composable
fun RowScope.RightPanel(focusRequester: FocusRequester) {
    Column(
        modifier = Modifier
            .background(Color.Green.copy(alpha = 0.1f))
            .fillMaxHeight()
            .weight(1f),
        verticalArrangement = Arrangement.spacedBy(8.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        val buttons by rememberSaveable { mutableStateOf(List(10) { "Button ${it + 1}" }) }

        LazyVerticalGrid(
            columns = GridCells.Fixed(2),
            modifier = Modifier.padding(16.dp),
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            itemsIndexed(
                items = buttons,
                key = { idx, _ -> idx }
            ) { idx, _ ->
                Button(
                    modifier = Modifier
                        .padding(8.dp)
                        .let {
                            if (idx == 0) {
                                it.focusRequester(focusRequester)
                            } else {
                                it
                            }
                        }
                    ,
                    onClick = { }
                ) {
                    Text(text = "Right Panel: $idx")
                }
            }
        }
    }
}

据我想象,您需要记住用户转到右侧面板的索引(假设按钮3)并跟踪用户向左的单击,当用户单击向左时,然后请求将焦点放在保存的索引(在我们的示例 3 中)。但这2个问题

  1. 如何区分右侧面板元素之间的右键单击(例如,右侧面板 3 -> 右侧面板 2 单击)和所需的单击(例如,右侧面板:6 -> 左侧面板 3)?
  2. 在我看来,这个解决方案看起来太麻烦了,不知何故,这一切应该更简单。

欢迎任何想法:)

UPD

我还有一个相关的问题,如果有人感兴趣欢迎 - https://ru.stackoverflow.com/a/1586671/195957

android
  • 1 1 个回答
  • 28 Views

1 个回答

  • Voted
  1. Best Answer
    Sirop4ik
    2024-07-05T03:41:26Z2024-07-05T03:41:26Z

    最后,我使用了focusRestorer该功能,这样它本身就会记住最后的焦点位置。

    但我必须说,这帮助我找到了我在问题中描述的问题的解决方案,但出现了我在这个问题中描述的另一个问题 - >当您返回屏幕时如何将焦点分配到同一位置?(如果有人有任何想法请告诉我)

    这是我得到的代码,作为该线程中提出的问题的解决方案

    private const val FIRST_SCREEN_ROUTE = "first_screen"
    private const val SECOND_SCREEN_ROUTE = "second_screen"
    private const val DEFAULT_FOCUS_POSITION = -1
    
    class MainActivity : ComponentActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent {
                Test_delete_itTheme {
                    Surface(
                        modifier = Modifier.fillMaxSize(),
                        shape = RectangleShape
                    ) {
                        Greeting()
                    }
                }
            }
        }
    }
    
    @Composable
    fun Greeting() {
        val navigator: NavHostController = rememberNavController()
    
        NavHost(
            navController = navigator,
            startDestination = FIRST_SCREEN_ROUTE
        ) {
            composable(FIRST_SCREEN_ROUTE) {
                DisposableEffect(Unit) {
                    Log.e("HERE", "1 CREATED first_screen_route")
    
                    onDispose {
                        Log.e("HERE", "DISPOSED first_screen_route")
                    }
                }
    
                FirstScreen(onClick = {
                    Log.e("HERE", "NAVIGATION TO SECOND SCREEN")
                    navigator.navigate(SECOND_SCREEN_ROUTE)
                })
            }
    
            composable(SECOND_SCREEN_ROUTE) {
                DisposableEffect(Unit) {
                    Log.e("HERE", "CREATED second_screen_route")
    
                    onDispose {
                        Log.e("HERE", "DISPOSED second_screen_route")
                    }
                }
    
                SecondScreen()
            }
        }
    }
    
    @Composable
    fun SecondScreen() {
        Box(
            modifier = Modifier
                .fillMaxSize()
                .background(Color.Red.copy(alpha = 0.1f)),
            contentAlignment = Alignment.Center
        ) {
            Text(text = "SECOND SCREEN")
        }
    }
    
    @Composable
    fun FirstScreen(
        onClick: () -> Unit
    ) {
        var focusBtnIdx by rememberSaveable { mutableIntStateOf(DEFAULT_FOCUS_POSITION) }
    
        Row(modifier = Modifier
            .fillMaxSize()
        ) {
            LeftPanel()
            RightPanel(onClick = onClick, focusBtnIdx = focusBtnIdx, setFocusBtnIdx = { focusBtnIdx = it })
        }
    }
    
    @OptIn(ExperimentalComposeUiApi::class)
    @Composable
    fun RowScope.LeftPanel() {
        val firstItemFr = remember { FocusRequester() }
        val buttons by rememberSaveable { mutableStateOf(List(5) { "Button ${it + 1}" }) }
    
        LaunchedEffect(Unit) {
            this.coroutineContext.job.invokeOnCompletion {
                try { firstItemFr.requestFocus() }
                catch (e: Exception) {/* do nothing */ }
            }
        }
    
        TvLazyColumn(
            modifier = Modifier
                .focusRestorer { firstItemFr }
                .background(Color.Blue.copy(alpha = 0.1f))
                .fillMaxHeight()
                .weight(1f),
            verticalArrangement = Arrangement.spacedBy(8.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            itemsIndexed(
                items = buttons,
                key = { idx, _ -> idx }
            ) { idx, _ ->
                Button(
                    modifier = Modifier
                        .let { modifier ->
                            if (idx == 0) {
                                modifier.focusRequester(firstItemFr)
                            } else {
                                modifier
                            }
                        },
                    onClick = {}
                ) {
                    Text(text = "Left Panel: $idx")
                }
            }
        }
    }
    
    @OptIn(ExperimentalComposeUiApi::class)
    @Composable
    fun RowScope.RightPanel(
        onClick: () -> Unit,
        focusBtnIdx: Int,
        setFocusBtnIdx: (Int) -> Unit
    ) {
        val firstItemFr = remember { FocusRequester() }
    
        LaunchedEffect(Unit) {
            this.coroutineContext.job.invokeOnCompletion {
                try {
                    Log.e("HERE", ">>> REQUEST FOCUS")
                    if (focusBtnIdx != DEFAULT_FOCUS_POSITION) {
                        firstItemFr.requestFocus()
                        Log.e("HERE", "<<< REQUEST FOCUS")
                    }
                }
                catch (e: Exception) {
                    /* do nothing */
                    Log.e("HERE", "FOCUS ERROR: $e")
                }
            }
        }
    
        Column(
            modifier = Modifier
                .background(Color.Green.copy(alpha = 0.1f))
                .fillMaxHeight()
                .weight(1f),
            verticalArrangement = Arrangement.spacedBy(8.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            val buttons: List<String> by rememberSaveable { mutableStateOf(List(4) { "Button ${it + 1}" }) }
    
            TvLazyVerticalGrid(
                modifier = Modifier
                    .focusRestorer { firstItemFr }
                    .padding(16.dp),
                columns = TvGridCells.Fixed(2),
                verticalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                itemsIndexed(
                    items = buttons,
                    key = { idx, _ -> idx }
                ) { idx, _ ->
                    Button(
                        modifier = Modifier
                            .padding(8.dp)
                            .let {
                                Log.e("HERE", "1 RightPanel: $idx")
                                if (idx == focusBtnIdx || (focusBtnIdx == DEFAULT_FOCUS_POSITION && idx == 0)) {
                                    Log.e("HERE", "2 RightPanel: $idx")
                                    it.focusRequester(firstItemFr)
                                } else {
                                    it
                                }
                            },
                        onClick = {
                            setFocusBtnIdx(idx)
                            onClick()
                        }
                    ) {
                        Text(text = "Right Panel: $idx")
                    }
                }
            }
        }
    }
    
    • 0

相关问题

  • 来自片段的列表落后于 BottomNavigationView

  • 无法将变量从 Activity 传递到 Fragment

  • 构建与完成的片段略有不同的片段的最佳方法是什么?

  • 如何更改来自服务器的响应中的日期格式?

  • 谷歌地图在应用程序的发布版本中不起作用

  • 材料设计按钮。单击按钮上的可选区域!

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5