2012-03-13 78 views
5

我有一个包含自定义行的ListView。这个自定义行具有以下UI元素更改列表项选择的视图属性

  1. ImageView的imageView1,imageView2
  2. TextView的textview1,textView2,textView3

要求是每当列表选择行有将以下更改

imageView1背景,颜色发生变化

imageView1颜色发生变化

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

textview2颜色,大小改变

textview3颜色,大小改变

什么将是这个设计的最佳方式?

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

我们可以在这将对下列回调方法列表视图设置setOnItemSelectedListener:

我)onItemSelected

II)onNothingSelected

但是没有回调方法,它提供的细节项目失去了重点。这是一个更好的地方做出改变?

在此先感谢。

+0

”AFAIK我们不能在选择器中应用样式,有没有更好的方法来处理这个问题而不是处理java代码?如果你不能在选择器中做到这一点,除Java之外还可以做什么?也许你可以重写默认选择器引用的样式属性? – nmr 2012-03-15 03:21:56

+0

样式可用于更改背景颜色/ drawable.It无助于更改字体大小。我也需要为每个子视图指定选择器吗?在java代码中,在getView()中。 – 2012-03-16 03:22:50

回答

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的情况下,设置它们,并让框架采取跟踪,其中选择行和没被选的照顾。 “

0

我有一个粗糙的方式...但它是非常重的过程... 一旦一个项目被选中刷新你的列表视图...只为选定的项目,它应该显示特定的字体等...和商店在填充适配器中的视图时,某些变量中所选项目的ID与其匹配...

0

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

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

现在在ListView的Adapter类中。作为

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

在getView 写条件,不要忘了写在适配器类这两种方法,

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

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

谢谢soni。但是,这意味着要重新为所选的每个项目重新绘制listView。这可以以任何方式避免吗?当“底层数据已经被改变”时,notifyDataSetChanged()应该被调用,这在这里不是这种情况。有没有框架来支持这种情况下的支持? – 2012-03-17 20:39:25

+0

@khotmanish nope .. :) :(..我只是有这个想法在我的脑海里,我认为这将适用于你.. – MKJParekh 2012-03-19 05:26:04

0

Khotmanish,

我不知道你的意思通过最有效办法。有很多方法非常快速,但它往往取决于你事先知道的事情和你不知道的事情。还必须了解的是,尽管流行的神话,动态视图属性被严重误解,但高效。谷歌的人员在UI开发方面做得非常出色。

如果你知道它的时间提前,你可以简单地创建一个StateListDrawable为每个视图,并将其应用到每个你通过你的适配器中运行。

要构建StateListDrawable,创建一个:

StateListDrawable _drawStates; 

然后,对于每个状态,添加您需要的绘制:

_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 
} 

重要的是要注意,这样做动态有一些注意事项,当涉及到背景颜色是很重要的。你必须从点击的视图中获取子...不是ListView。其次,当改变背景颜色时,你实际上正在改变背景Drawables。这意味着所有其他“有状态”属性都会消失,并且您必须手动将其更改回来(如果您希望以此开始)。现在

,更受欢迎,但少了几分灵活的方法是建立你StateListDrawable XML格式。有许多资源可以学习如何在Android开发者网站上执行此操作。

希望这有助于 FuzzicalLogic

+0

感谢您的回应模糊逻辑。然而StateListDrawable只会改变颜色/ drawables,它赢得'这对于改变字体大小有很大的帮助,另外我对onSelect状态更感兴趣,而不是onClicked状态(我将使用轨迹球而不是onTouch),因此onListItemClick不会帮助我:(无论如何感谢您的简要回答:) – 2012-03-21 04:45:09