Android ListView和ToggleButton

Android ListView和ToggleButton,android,android-listview,android-togglebutton,Android,Android Listview,Android Togglebutton,我看了所有其他简单的问题,但找不到我想要的答案。我有一个列表视图,每个列表项都包含一个切换按钮。我有两个问题: 当滚动列表时按下其中一个列表项上的切换按钮时,项目被回收;假设我点击了第一个项目(一次只显示三个项目),每四个单元格就会打开一个切换按钮 由于这是一个切换按钮,我只希望打开按钮的一个实例,因此如果它打开了单个列表项,则ListView中可能打开了ToggleButton的所有其他项都应该关闭 任何帮助都将不胜感激。我的适配器代码如下所示: public class RSSFeedI

我看了所有其他简单的问题,但找不到我想要的答案。我有一个列表视图,每个列表项都包含一个切换按钮。我有两个问题:

  • 当滚动列表时按下其中一个列表项上的切换按钮时,项目被回收;假设我点击了第一个项目(一次只显示三个项目),每四个单元格就会打开一个切换按钮

  • 由于这是一个切换按钮,我只希望打开按钮的一个实例,因此如果它打开了单个列表项,则ListView中可能打开了ToggleButton的所有其他项都应该关闭

任何帮助都将不胜感激。我的适配器代码如下所示:

public class RSSFeedItemListAdapter extends ArrayAdapter<RSSItem> {

    private Context context;
    private List<RSSItem> items;
    private int resource;
    private Podcast podcast;
    private boolean[] playpauseState;

    public RSSFeedItemListAdapter(Context context, int resource, List<RSSItem> items, Podcast podcast) {
        super(context, resource, items);
        this.items = items;
        this.context = context;
        this.resource = resource;
        this.podcast = podcast;
        playpauseState = new boolean[this.items.size()];
    }


    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        Viewholder vh;
        if (convertView == null) {

            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(resource, parent, false);

            Typeface custom_font = Typeface.createFromAsset(context.getAssets(), "fonts/RobotoCondensed-Bold.ttf");
            vh = new Viewholder();
            vh.title = (TextView) convertView.findViewById(R.id.podcast_feeditem_title);
            vh.title.setTypeface(custom_font);
            vh.desc = (TextView) convertView.findViewById(R.id.podcast_feeditem_description);
            vh.image = (ImageView) convertView.findViewById(R.id.podcast_feeditem_image);
            vh.pubDate = (TextView) convertView.findViewById(R.id.podcast_feeditem_pubdate);
            vh.collectionName = (TextView) convertView.findViewById(R.id.podcast_feeditem_collection_name);
            vh.playpause = (ToggleButton) convertView.findViewById(R.id.podcast_feeditem_play_pause_cta);
            vh.playpause.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    int position = (Integer) buttonView.getTag();
                    playpauseState[position] = isChecked;
                }
            });
            convertView.setTag(vh);
        } else {
            vh = (Viewholder) convertView.getTag();
        }

        vh.playpause.setChecked(playpauseState[position]);
        vh.playpause.setTag(position);


        RSSItem rssItem = items.get(position);
        vh.title.setText(rssItem.getTitle());
        vh.desc.setText(Jsoup.parse(rssItem.getDescription()).text());
        Picasso.with(context).load(podcast.getArtworkExtraLarge()).into(vh.image);

        // TODO detect the local and show the right format
        // TODO the date format should match the date format from the rssfeedhandler code
        if (rssItem.getPubDate() != null) {
            vh.pubDate.setText(vh.simpleDateFormat.format(rssItem.getPubDate()));
        }

        // vh.playpause.setChecked(playpauseState[position]);
        vh.collectionName.setText(podcast.getCollectionName());
        return convertView;
    }


    /**
     *
     */
    static class Viewholder {
        ImageView image;
        TextView title;
        TextView desc;
        TextView pubDate;
        TextView collectionName;
        ToggleButton playpause;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("d MMM", Locale.UK);

    }
公共类RSSFeedItemListAdapter扩展了ArrayAdapter{
私人语境;
私人清单项目;
私有int资源;
私人播客;
私有财产;
公共RSSFeedItemListAdapter(上下文上下文、int资源、列表项、播客){
超级(上下文、资源、项目);
这个项目=项目;
this.context=上下文;
这个资源=资源;
this.podcast=podcast;
playpauseState=新布尔值[this.items.size()];
}
@凌驾
公共视图getView(最终整数位置、视图转换视图、视图组父视图){
视窗座;
if(convertView==null){
LayoutInflater充气器=(LayoutInflater)context.getSystemService(Activity.LAYOUT\u充气器\u SERVICE);
convertView=充气机。充气(资源,父项,false);
Typeface custom_font=Typeface.createFromAsset(context.getAssets(),“font/robotoconned Bold.ttf”);
vh=新的视窗支架();
vh.title=(TextView)convertView.findViewById(R.id.podcast\u feeditem\u title);
vh.title.setTypeface(自定义字体);
vh.desc=(TextView)convertView.findViewById(R.id.podcast\u feeditem\u description);
vh.image=(ImageView)convertView.findViewById(R.id.podcast\u feeditem\u image);
vh.pubDate=(TextView)convertView.findViewById(R.id.podcast\u feeditem\u pubDate);
vh.collectionName=(TextView)convertView.findViewById(R.id.podcast\u feeditem\u collection\u name);
vh.playpause=(切换按钮)convertView.findViewById(R.id.podcast\u feeditem\u play\u pause\u cta);
vh.playpause.setOnCheckedChangeListener(新建CompoundButton.OnCheckedChangeListener()){
@凌驾
检查更改后的公共无效(复合按钮视图,布尔值已检查){
int position=(整数)按钮view.getTag();
playpauseState[位置]=已检查;
}
});
convertView.setTag(vh);
}否则{
vh=(Viewholder)convertView.getTag();
}
vh.playpause.setChecked(playpauseState[位置]);
vh.播放暂停.设置标签(位置);
RSSItem RSSItem=items.get(位置);
vh.title.setText(rssItem.getTitle());
vh.desc.setText(Jsoup.parse(rssItem.getDescription()).text());
毕加索.with(context).load(podcast.getartworkextralige()).into(vh.image);
//TODO检测本地文件并显示正确的格式
//TODO日期格式应与rssfeedhandler代码中的日期格式匹配
if(rssItem.getPubDate()!=null){
vh.pubDate.setText(vh.simpleDateFormat.format(rssItem.getPubDate());
}
//vh.playpause.setChecked(playpauseState[位置]);
vh.collectionName.setText(podcast.getCollectionName());
返回视图;
}
/**
*
*/
静态类视窗夹{
图像视图图像;
文本视图标题;
文本视图描述;
文本视图发布日期;
TextView collectionName;
切换按钮播放暂停;
SimpleDataFormat SimpleDataFormat=新的SimpleDataFormat(“d MMM”,Locale.UK);
}

我花了大约10个小时才弄明白这一点。如果你还没有找到解决方案,我写了一封很晚的回信

列表视图基本上是在一个真正的wierd上工作的(相当聪明)非常仔细地显示项目的方式,它基于滚动重新绘制项目,并且可以在屏幕上查看。这意味着它根据当前视图必须适应的内容动态创建项目。分开来看,想告诉我解决方案吗?来吧

在适配器getView()方法中,只需将选中状态设置为该项的适当值。 (或)如果您使用的是ImageView,只需根据on或OFF设置适当的图像资源即可 i、 e


乍一看,您的代码看起来不错,但我没有发现任何问题。虽然我更喜欢使用getView()参数中的'position'变量,而您通过按钮的标记传递它。我会更改为vh.playpaise.setTag(Integer.valueOf(position))-只是我不确定默认情况下int是否转换为整数,或者是否有带int参数的setTag方法?我建议用ide调试代码。我认为,togglebutton set checked对于android来说有缺陷。尝试将其全部设置为true。作为一种解决方法,我将使用imageview并为checked状态设置不同的图像。pr问题是它仍然不起作用。我已经尝试了这两种方法。好的,我看到Integer可以自动转换为int,它的自动取消装箱功能MD1948同意,我将其作为图像视图重新编写,并使用存储在数组列表中的viewmodel来记住每个列表项的状态
  public View getView(int position, View convertView, ViewGroup parent) {
           ImageView toggle = (ImageView) convertView.findViewById(R.id.toggle);
           if(toggle_array(postion) == 1)
               toggle.setImageResource(R.drawable.on);
           } else {
               toggle.setImageResource(R.drawable.off);
           }
        }