更改列表项选择的视图属性

时间:2012-03-13 00:20:01

标签: android listview focus

我有一个包含自定义行的ListView。此自定义行具有以下UI元素

  1. ImageView imageView1,imageView2
  2. TextView textview1,textView2,textView3
  3. 要求是每当列表行被选中时,都会有以下更改

    imageView1背景,颜色已更改

    imageView1颜色已更改

    textview1颜色,大小和字体是变化

    textview2颜色,尺寸改变

    textview3颜色,尺寸改变

    为此设计最好的方法是什么?

    AFAIK我们无法在选择器中应用样式。有没有更好的方法来处理这个而不是在java代码中处理?

    我们有setOnItemSelectedListener,可以在Listview上设置,它将具有以下回调方法:

    i)onItemSelected

    ii)onNothingSelected

    然而,没有回调方法提供失去焦点的项目的细节。这是一个更好的地方吗?

    提前致谢。

4 个答案:

答案 0 :(得分:2)

我认为你想要做的是创建一个Compound Control。您可以在样本// ApiDemos子目录的SDK目录中找到一个示例(如果您没有这些目录,可能需要下载Android source。)

我要做的是创建一个继承自用于自定义行的任何布局类的类。我们假设这个例子是LinearLayout。在子类构造函数中,您可以从资源中扩展布局,找到子视图并将它们附加到实例变量,并将LinearLayout返回给调用者。

在这个子类中,你可以覆盖setSelected并以你想要的任何方式操纵子视图。

以下是我根据您的帖子描述的示例:

public class MyCustomLayout extends LinearLayout {
    public ImageView imageView1;   // These are public since you likely want
    public ImageView imageView2;   // to set them in your Adapter.
    public TextView textView1;
    public TextView textView2;
    public TextView textView3;

    public MyCustomLayout(Context ctxt) {
        super(ctxt);

        // The call below attaches the items in the mycustomlayout.xml file to this
        // instance, which serves as the root element in the layout.
        LayoutInflater.from(ctxt).inflate(R.layout.mycustomlayout, this, true);

        imageView1 = (ImageView)findViewById(R.id.imageview1);
        imageView2 = (ImageView)findViewById(R.id.imageview2);
        textView1 = (TextView)findViewById(R.id.textview1);
        textView2 = (TextView)findViewById(R.id.textview2);
        textView3 = (TextView)findViewById(R.id.textview3);
    }

    @Override
    public void setSelected(boolean selected) {
        super.setChecked(selected);
        if (selected) {
            imageView1.setBackgroundColor(0xFFFF0000); // whatever color you want
            // Do all the rest of the setting of your subviews here for
            // the case when the row is selected.
        } else {
            imageView1.setBackgroundColor(0xFF000000); // whatever color you want
            // Do all the rest of the setting of your subviews here for
            // the case when the row is not selected
        }
    }
}

现在,在mycustomlayout.xml文件中,您希望使用<merge>标记,以便不创建不需要的布局:

<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <ImageView
        android:id="@+id/imageview1" />
    <ImageView
        android:id="@+id/imageview2" />
    <TextView
        android:id="@+id/textview1" />
    <TextView
        android:id="@+id/textview2" />
    <TextView
        android:id="@+id/textview3" />
</merge>

显然,我已经省略了上面子视图的所有配置,但您应该了解如何设置XML文件。如果你不想愚弄XML和LayoutInflater,你也可以在代码中执行此操作。您可以在Android开发博客上查看this helpful blog post,该博客最后讨论了类似的案例。

然后,在您的适配器getView中,您可以创建(或回收)MyCustomLayout的实例,进行设置,并让框架负责跟踪哪些行被选中以及哪些行是没被选中。

答案 1 :(得分:0)

我有一种粗暴的方式......但它过程非常重... 选择一个项目后,刷新列表视图...仅针对所选项目,它应显示特定字体等...并将所选项目的ID存储在某个变量中以匹配它,同时填充适配器中的视图... < / p>

答案 2 :(得分:0)

在活动级别获取一个静态整数变量selectedPos

在onItemSelected中,变量selectedPos = position和onNothingSelected将其设置为-1,并为适配器对象调用notifyDataSetChanged()。

现在在ListView的Adapter类中。 将getView中的条件写为

if(position == selectedPos)
{
   // set color and background to view
}

并且不要忘记在适配器类中编写这两个方法,

@Override
public int getItemViewType(int position) {
 return position;
}

@Override
public int getViewTypeCount() {
 return _ArrayListObject.size();
}

答案 3 :(得分:0)

Khotmanish,

我不确定你最有效的方式是什么意思。有很多方法非常快速,但它通常取决于你提前知道什么,你不知道什么。还必须要理解的是,动态视图属性被严重误解,但尽管有流行的神话,但效率很高。谷歌的人在UI开发方面做得非常出色。

如果您提前知道,可以为每个View创建一个StateListDrawable,并在运行适配器时将其应用于每个View。

要构建StateListDrawable,请创建一个:

StateListDrawable _drawStates;

然后,对于每个州,添加您需要的drawable:

_drawStates.add(new int[] {android.R.attr.state_pressed}, _newImage);

这与适配器的getView()方法中的以下行一样简单:

v.setBackgroundDrawable(_drawStates);

或者,您可以根据选择动态更改背景。这可以在OnListItemClick()中完成。您看,OnListItemClick()会为您提供已点击的确切视图。完成此操作后,您可以通过id找到该子项并更改其属性并invalidate()。我经常使用这个技巧。为我节省了大量内存,但我没有做任何真正处理器密集的事情。您几乎可以在此处更改任何属性而无需任何处理。这是一个例子:

@Override protected void onListItemClick(final ListView inList, final View v, final int atPos, final long rowID)
{//Get the Child, set the properties
    ImageView _img = (ImageView)(v.findViewById(R.id.app_package));
    _img.setBackgroundColor(myClickedColor);
    _img.invalidate();  // <---- BEST Option
// ... OR ...
    v.invalidate();     // <---- 2nd Best Option
// ... OR ...
    inList.invalidate();  // <---- Last resort or specialized implementation
}

重要的是要注意,在背景颜色方面,动态执行此操作会有一些注意事项。您必须从Clicked View中获取子项...而不是ListView。其次,在更改背景颜色时,实际上是在改变背景Drawables。这意味着所有其他“有状态”属性都会消失,您必须手动更改它(如果您希望它开始)。

现在,一种更流行但不太灵活的方法是在XML中构建StateListDrawable。有许多资源可以在Android Developer网站上了解如何执行此操作。

希望这有帮助, FuzzicalLogic