Android TV ListView无法返回上次选中项问题求助
Android TV ListView 返回上次选中项问题处理方案
我的界面分为左右两部分,左侧是ListView,右侧是显示选中内容的TextView。使用场景:选中某一项后,按Dpad右键切换到TextView,再按左键返回ListView,按Dpad下键移动几个项目;再次按右键切换到TextView,再左键返回时,选中的不是上次的项,而是随机位置,不符合直觉。
以下是测试用的ListView代码:
public class MainActivity extends AppCompatActivity { private static final String LOG_TAG = MainActivity.class.getSimpleName(); private TextView m_program_description; ListView listView; ArrayList<String> arrayList = new ArrayList<>(Arrays.asList("C-Language", "Java", "Data Structure", "Networking", "Operating System", "Compiler Design", "Theory Of Computation", "Software Engineering", "Web Engineering")); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.listView); // simple_list_item_1 is a built in layout. It is part of Android OS, instead of creating our own // xml layout we are using built-in layout ArrayAdapter arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, arrayList); listView.setAdapter(arrayAdapter); listView.setOnItemClickListener((adapterView, view, i, l) -> { view.setSelected(true); view.setActivated(true); }); listView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { Log.e(LOG_TAG, "onItemSelected() called"); m_program_description = findViewById(R.id.program_description); m_program_description.setMovementMethod(new ScrollingMovementMethod()); m_program_description.setText(arrayList.get(position)); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); } }
布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:weightSum="2"> <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical"> <!--ListView to store list items--> <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical"> <TextView android:id="@+id/program_description" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:layout_marginTop="10dp" android:layout_marginStart="20dp" android:layout_marginEnd="20dp" android:layout_marginBottom="25dp" android:focusable="true" android:clickable="true" android:foreground="?attr/selectableItemBackground" android:scrollbars="vertical" android:fadeScrollbars="false" android:textSize="16sp" android:gravity="start" > </TextView> </LinearLayout> </LinearLayout>
解决思路
核心是记录ListView最后选中的位置,在焦点回到ListView时,主动将选中状态恢复到该位置。
具体修改步骤
- 添加选中位置记录变量
在MainActivity中新增成员变量:
private int lastSelectedPosition = 0; // 默认选中第一个项
- 更新选中位置记录
在onItemSelected方法中实时更新记录的位置:
@Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { Log.e(LOG_TAG, "onItemSelected() called"); lastSelectedPosition = position; // 记录当前选中位置 m_program_description = findViewById(R.id.program_description); m_program_description.setMovementMethod(new ScrollingMovementMethod()); m_program_description.setText(arrayList.get(position)); }
- 监听焦点变化,恢复选中状态
给ListView添加焦点监听器,当重新获得焦点时恢复选中项:
@Override protected void onCreate(Bundle savedInstanceState) { // ... 保留原有初始化代码 ... listView.setOnFocusChangeListener((v, hasFocus) -> { if (hasFocus) { // 焦点回到ListView时,选中上次记录的位置 listView.setSelection(lastSelectedPosition); // 确保选中项获得焦点,增强视觉反馈 View selectedView = listView.getChildAt(lastSelectedPosition - listView.getFirstVisiblePosition()); if (selectedView != null) { selectedView.requestFocus(); } } }); }
- 优化选中样式(可选)
替换ListView的item布局为带激活状态的系统布局,让选中项有更明显的视觉反馈:
ArrayAdapter arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_activated_1, arrayList);
问题原因
Android TV的焦点管理机制中,当ListView失去焦点后,不会自动保留最后选中的位置,默认会回到列表顶部或随机可见位置,通过主动记录并恢复选中位置即可解决该问题。
内容的提问来源于stack exchange,提问作者Frantisek Kaduch
相关产品推荐
相关产品推荐

