gpt4 book ai didi

当项目滚动出来时,Android listSelector 仍然部分可见

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:46:05 26 4
gpt4 key购买 nike

图片显示问题:Venus项目已滚动,但它的选择是可见的。

Venus item is scrolled out but it's selection is visible

我看过 Hanged listSelector in ListView我正在按照建议使用形状/渐变,但仍然没有运气。

设备:适用于 Android 的 MS VS 模拟器,Android 4.2 XHDPI API-17
IDE:Android Studio 2. 在 Windows 7 WM 上。

布局,主要 Activity

<?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="vertical" >

<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:choiceMode="singleChoice"
android:drawSelectorOnTop="false"
android:scrollingCache="false"
android:animationCache="false"
android:listSelector="@drawable/list_selector">
</ListView>

</LinearLayout>

列表选择器
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:drawable="@drawable/item_pressed" />
<item
android:drawable="@drawable/item_selected" />
</selector>

drawables,item_pressed
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<gradient
android:angle="90"
android:endColor="#0000ff"
android:startColor="#0000ff" />

</shape>

item_selected
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<gradient
android:angle="90"
android:endColor="#00ff00"
android:startColor="#00ff00" />

</shape>

和 Activity 代码
package com.example.listdemo;

import android.app.ListActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;

public class MainActivity extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

ArrayAdapter adapter = ArrayAdapter.createFromResource(this, R.array.Planets, R.layout.myitem);
setListAdapter(adapter);
}
}

哪里 Planets只是一个字符串数组(太阳、水星、金星、地球、火星、木星...)和 myitem只是一个 TextView自定义高度。

请问我哪里错了?

编辑
为了澄清这个问题,它与默认列表选择行为有关。那是关于没有 android:state_xxx 的列表选择器项属性。不要太注意相应的可绘制名称。我准备重命名 @drawable/item_selected@drawable/item_default .让我知道它是否有助于澄清问题,我会重命名它。

最佳答案

tl;博士 不要在列表选择器上设置默认的 Drawable。

当你给列表选择器一个默认的 Drawable 时就会出现这个问题。我的意思是在您的列表选择器定义中,您有一个 item没有状态要求的标签,这使得 item不经意间的默认 可绘制。您可以阅读更多关于选择器的信息 here .

您的列表选择器代码:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:drawable="@drawable/item_pressed" />
<item
android:drawable="@drawable/item_selected" /> <-- this is what I'm referring to
</selector>

修复

您遇到的问题是由始终绘制列表选择器引起的(即使选择器不在屏幕上)。通常这不是问题,因为列表选择器是透明的(因此是不可见的)。但是,由于您为列表选择器提供了默认背景,这意味着每当列表选择器出现在屏幕上时,它都是可见的,从而导致您观察到的奇怪行为。相反,您真正想要的是仅在实际选择项目时才显示此背景。

为此,首先我们必须从列表选择器中删除默认背景。然后我们需要一种新的方式来指示所选项目。由于您指定了 android:choiceMode="singleChoice"在您的 ListView 中,ListView 会将您的列表项视为复选框列表。因此,当用户检查其中一项时,它的激活状态将设置为 true。但是,默认情况下,TextViews 在激活时不会显示任何视觉效果。要在选中时显示特定背景,我们需要使用可以显示激活状态的列表项布局。一种方法是将 ListView 项目 View 的背景更改为选择器并定义要用于激活状态的 Drawable。

例如:

适配器代码:
ArrayAdapter adapter = ArrayAdapter.createFromResource(this, 
R.array.Planets, R.layout.myitem);

我的项目.xml:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
style="?android:attr/spinnerItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/item_background"
android:paddingTop="16dp"
android:paddingBottom="16dp"/>

item_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/item_selected" android:state_activated="true" />
</selector>

或者如果你很懒惰:
ArrayAdapter adapter = ArrayAdapter.createFromResource(this, 
R.array.planets_array, android.R.layout.simple_list_item_activated_1);

进一步阅读

从 Android 的文档来看,我所说的是否属实并不完全清楚,因此您可能会问我的回答是否可信。本节专为那些寻求可靠答案的人和非常好奇的人而设。

要了解列表选择器的工作原理和编程方式,我们需要深入研究 Android 源代码。首先, ListView 的逻辑核心实际上是在一个名为 AbsListView 的类(class)中举行的(如果您没有下载源代码,您可以引用 this )。深入研究这个类的源代码,我们会发现一些与选择器相关的有用字段/函数:
  • mSelector : 这是选择器的 Drawable(你用 android:listSelector 指定的那个)
  • mSelectorRect :这个字段决定了选择器的绘制位置和选择器的大小
  • mSelectedPosition :存储所选项目的索引(该字段实际上在类 AdapterView 中更深地声明)
  • positionSelector(...) :更新选择器的绘制位置
  • drawSelector(...) : 绘制选择器
  • trackMotionScroll(...) :包含ListView的逻辑的滚动行为

  • 现在我们已经了解了环境,我们终于可以了解列表选择器行为的核心逻辑。这一切都归结为 trackMotionScroll(...) 中的这几行代码:
    boolean trackMotionScroll(int deltaY, int incrementalDeltaY) {
    ...
    if (!inTouchMode && mSelectedPosition != INVALID_POSITION) {
    // if we are not in touch mode and there is a selected item then
    // we do a quick check if the selected item is on screen
    final int childIndex = mSelectedPosition - mFirstPosition;
    if (childIndex >= 0 && childIndex < getChildCount()) {
    // if the selected item is on screen, we move the selector to
    // where the selected item is
    positionSelector(mSelectedPosition, getChildAt(childIndex));
    }
    } else if (mSelectorPosition != INVALID_POSITION) {
    // if we are in touch mode and there is a selected item then
    // we do a quick check if the selected item is on screen
    final int childIndex = mSelectorPosition - mFirstPosition;
    if (childIndex >= 0 && childIndex < getChildCount()) {
    // if the selected item is on screen, we move the selector to
    // where the selected item is
    positionSelector(INVALID_POSITION, getChildAt(childIndex));
    }
    } else {
    // otherwise, if nothing is selected, hide the selector (don't draw it)
    mSelectorRect.setEmpty();
    }
    ...
    }

    上面的源代码 fragment 已从原始内容中编辑,以包含评论。

    在这里,我们终于找到了解释所观察到的行为的逻辑:列表选择器是 只有隐藏时 mSelectorPosition == INVALID_POSITION或者,在英语中,当没有选择的项目时。否则,如果项目在屏幕上,则它被定位在所选项目上,否则不会对其位置进行任何更改。

    所以当你滚动 ListView并且所选项目离开屏幕,列表选择器只是停留在所选项目解释观察到的幽灵列表选择器的最后一个位置。

    最后的想法

    从使用 ListViews 开始,我不得不说整个事情的设计不是很好,而且可能非常有问题。我强烈建议使用它的继任者 RecyclerView ,只要可以。

    关于当项目滚动出来时,Android listSelector 仍然部分可见,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36697055/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com