Android 回收视图项目失去焦点
在我的fire tv应用程序中,我正在使用带有水平布局的Android 回收视图项目失去焦点,android,android-recyclerview,linearlayoutmanager,Android,Android Recyclerview,Linearlayoutmanager,在我的fire tv应用程序中,我正在使用带有水平布局的recyclerview 使用dpad滚动可以工作,而且项目也获得了关注 但是,当我按住按钮时,它会快速滚动,因为许多按键事件都会被触发,项目会失去焦点,并且无法再滚动,因为我的recyclerview上方的另一个Textview正在获得焦点 它看起来像一只虫子。有什么解决方法吗?我也面临同样的问题,我在项目中所做的事情就像我的活动(包含RecyclerView)中所做的那样: private long mLastKeyDownTime=0
recyclerview
使用dpad滚动可以工作,而且项目也获得了关注
但是,当我按住按钮时,它会快速滚动,因为许多按键事件都会被触发,项目会失去焦点,并且无法再滚动,因为我的recyclerview上方的另一个Textview
正在获得焦点
它看起来像一只虫子。有什么解决方法吗?我也面临同样的问题,我在项目中所做的事情就像我的活动(包含RecyclerView)中所做的那样:
private long mLastKeyDownTime=0;
@凌驾
公共布尔onKeyDown(int-keyCode,KeyEvent事件){
长电流=System.currentTimeMillis();
布尔res=false;
如果(当前-MLASTKEYDOWNTH<300){
res=真;
}否则{
res=super.onKeyDown(键码,事件);
MLASTKEYDOWNTH=当前;
}
返回res;
}
这避免了当您按住dpad上的按钮时快速滚动,并且在我的RecyclerView中焦点工作正常。看起来这是一个bug 看到和
我可以通过对我的项目视图进行中性化
clearFocus()
来解决此错误,因此分离视图失去焦点不会将焦点移到RecyclerView之外:
private long mLastKeyDownTime = 0;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
long current = System. currentTimeMillis();
boolean res = false;
if (current - mLastKeyDownTime < 300 ) {
res = true;
} else {
res = super.onKeyDown(keyCode, event);
mLastKeyDownTime = current;
}
return res;
}
override fun clearFocus() {
if (parent != null)
super.clearFocus()
}
我在为Android TV和leanback library工作时也遇到过同样的问题 好消息是,流行应用(YouTube和其他)没有这个问题。 我发现信息丰富。经过调查,我提出了一个对我来说方便的解决方案。 关键是用而不是用 有一个最简单的例子
//Presenter class
public class ItemViewPresenter extends Presenter {
@Override
public final ViewHolder onCreateViewHolder(ViewGroup parent) {
//I use data binding
ItemBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.item, parent, false);
return new MyViewHolder(binding);
}
@Override
public final void onBindViewHolder(ViewHolder viewHolder, Object item) {
String text = (String) item;
((MyViewHolder) viewHolder).bind(text);
}
@Override
public final void onUnbindViewHolder(ViewHolder viewHolder) {
}
private class MyViewHolder extends Presenter.ViewHolder {
private final ItemBinding binding;
private DiscoveryViewHolder(ItemBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
private void bind(String text) {
binding.textView.setText(text);
}
}
}
//...
private void setupRecyclerView() {
RecyclerView recyclerView = _baseLayout.findViewById(R.id.recyclerView);
ArrayObjectAdapter arrayObjectAdapter = new ArrayObjectAdapter(new ItemViewPresenter());
ItemBridgeAdapter bridgeAdapter = new ItemBridgeAdapter(arrayObjectAdapter);
recyclerView.setAdapter(bridgeAdapter);
LinearLayoutManager layoutManager = new LinearLayoutManager(_baseLayout.getContext(), LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(layoutManager);
List<Strings> textList = new ArrayList(1);
textList.add("1");
//add objects
arrayObjectAdapter.addAll(0, textList);
//clear objects
//arrayObjectAdapter.clear();
}
//演示者类
公共类ItemViewPresenter扩展了Presenter{
@凌驾
公共最终视图持有者onCreateViewHolder(视图组父视图){
//我使用数据绑定
ItemBinding=DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),R.layout.item,parent,false);
返回新的MyViewHolder(具有约束力);
}
@凌驾
BindViewHolder上的公共最终无效(ViewHolder ViewHolder,对象项){
字符串文本=(字符串)项;
((MyViewHolder)viewHolder.bind(文本);
}
@凌驾
公开最终无效onUnbindViewHolder(ViewHolder ViewHolder){
}
私有类MyViewHolder扩展了Presenter.ViewHolder{
私人最终条款具有约束力;
私有发现文件夹(ItemBinding绑定){
super(binding.getRoot());
这个。绑定=绑定;
}
私有void绑定(字符串文本){
binding.textView.setText(text);
}
}
}
//...
私有void setupRecyclerView(){
RecycleView RecycleView=\u baseLayout.findViewById(R.id.RecycleView);
ArrayObjectAdapter ArrayObjectAdapter=new ArrayObjectAdapter(new ItemViewPresenter());
ItemBridgeAdapter bridgeAdapter=新的ItemBridgeAdapter(arrayObjectAdapter);
recyclerView.setAdapter(桥接适配器);
LinearLayoutManager布局管理器=新的LinearLayoutManager(_baseLayout.getContext(),LinearLayoutManager.HORIZONTAL,false);
recyclerView.setLayoutManager(layoutManager);
List textList=newarraylist(1);
文本列表。添加(“1”);
//添加对象
arrayObjectAdapter.addAll(0,文本列表);
//清除物体
//arrayObjectAdapter.clear();
}
我认为@tmm1给出的答案是目前为止最好的。我已经成功地实现了这个解决方案,解决了如果用户使用DPAD太快而无法滚动时,在RecyclerView中加载的元素会失去焦点的问题
在我的RecyclerView适配器中,我使用LayoutFlater来像这样膨胀我的元素视图
@Override
public ListItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_keyboard_key, viewGroup, false);
return new ListItemViewHolder(itemView);
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_keyboard_key_layout"
android:orientation="vertical"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/item_keyboard_key_text"
android:text="A"/>
</FrameLayout>
public class FocusFixFrameLayout extends FrameLayout {
public FocusFixFrameLayout(@NonNull Context context) {
super(context);
}
public FocusFixFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public FocusFixFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public FocusFixFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public void clearFocus() {
if(this.getParent() != null)
super.clearFocus();
}
}
我的item_keyboard_key.xml最初是这样定义的
@Override
public ListItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_keyboard_key, viewGroup, false);
return new ListItemViewHolder(itemView);
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_keyboard_key_layout"
android:orientation="vertical"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/item_keyboard_key_text"
android:text="A"/>
</FrameLayout>
public class FocusFixFrameLayout extends FrameLayout {
public FocusFixFrameLayout(@NonNull Context context) {
super(context);
}
public FocusFixFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public FocusFixFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public FocusFixFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public void clearFocus() {
if(this.getParent() != null)
super.clearFocus();
}
}
对于那些将面临同样问题的人。我找到了解决办法。我不再使用RecyclerView了。我已经切换到这个HorizontalListView库:,它足以满足我的需要。
parent
从哪里来?parent
是在FrameLayout
/ViewGroup
/视图
中定义的,我认为它在任何地方都没有定义,我的意思是有一个getParent()
方法,但没有公共/受保护的parent
变量。我正在使用Kotlin,因此parent
正在调用getParent()
。我在项目中对此进行了测试,但它并没有真正起作用。它将减少问题,但仍然是如此抱歉,但它没有帮助((如何在某些片段或视图中在关键侦听器中使用它而不在活动中使用?嗨,哈瓦德。它真的解决了我的问题。非常感谢你。你是一个救生员))这在某些设备上解决了问题,但在其他设备上它仍然存在(例如,API 21上的Fire OS 5设备)我得到了“java.lang.NullPointerException:尝试调用虚拟方法'boolean android.view.ViewGroup.getTouchscreenBlocksFocus()'on a null object reference”。这个答案发布后有什么变化吗?问题是关于重新循环视图,而不是关于leanback库