android中的“收藏夹列表” - 重新更改评级栏

时间:2014-02-06 11:20:33

标签: java android eclipse listview

我想在我的应用中列出收藏夹。 我正在使用arrayadapter。

我有一个字符串和一个评级栏,只有一颗星! 我希望如果你按下星星一次,它会点亮星星(并使它成为最喜欢的) 当你再次按它时,星星不会被填满...(现在它不再是最喜欢的了)

我应该在这里写些什么?如果问题,它甚至可以纠正吗?

public class ChooseFavorites extends Activity implements OnItemClickListener
{
    String[] stations;
    float[] rating;
    boolean[] ifCheacked;
    RatingAdapter ratingAdapter; 

ArrayAdapter<String> arr;
ListView list;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_choose_favorites);
    stations =  getResources().getStringArray(R.array.stations);
    rating = new float[stations.length];
    ifCheacked = new boolean[stations.length];
    Arrays.fill(ifCheacked, false);
    ratingAdapter = new RatingAdapter(this, R.layout.favorite_row, stations);
    list = (ListView)findViewById(R.id.stationsList1);
    list.setAdapter(ratingAdapter);
    list.setOnItemClickListener(this);

}




class RatingAdapter extends ArrayAdapter<String> 
{
    Context ctx;
    LayoutInflater inflater;
    TextView stationName;
    RatingBar star;


    public RatingAdapter(Context context, int textViewResourceId, String[] objects) 
    {
        super(context, textViewResourceId, objects);
        ctx = context;
        inflater = LayoutInflater.from(context);
    }



@Override
public View getView(int position, View convertView, ViewGroup parent) 
{
    View row = convertView;
    if(row==null)
    { // Object reuse
        inflater = getLayoutInflater();
        row = inflater.inflate(R.layout.favorite_row, parent, false);
    }
    stationName = (TextView)row.findViewById(R.id.textFavoriteItemInRow);
    stationName.setText(stations[position]);
    star= (RatingBar)row.findViewById(R.id.ratingBar1);
    if (!ifCheacked[position]) //ifChecked is false
    {
        star.setRating(rating[position]);
        star.setTag(position);
        ifCheacked[position] = true;
    }
    else
    {


    }
    star.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener()
    {
        public void onRatingChanged(RatingBar ratingBar, float rating2, boolean fromUser)
        {
            if(!fromUser) return;
            int index = (Integer)(ratingBar.getTag());
            rating[index] = rating2;
        }
    });
    return row;
}


    }

    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        // TODO Auto-generated method stub

    }
}

2 个答案:

答案 0 :(得分:3)

可能您不应该使用RatingBar,而应使用CheckBox。我完全按照您的需要在我的某个应用中使用CheckBox

基本上您需要做的是以下内容:

res \ drawable \ 文件夹中,定义一个新的布局文件,假设您将其命名为 checkboxes.xml

在该文件中,您将定义如下内容:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_checked="true" android:drawable="@drawable/checkbox_star_down" />
  <item android:state_checked="false" android:drawable="@drawable/checkbox_star" />
</selector>

在我的情况下,两个绘图都是两个JPG图像,一个是星星闪耀,一个是关闭。

现在在您的行布局中,定义CheckBox而不是RatingBar,如下所示:

<CheckBox
   android:id="@+id/soloR"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_weight="0.6"
   android:onClick="somethingChanged"
   android:textSize="12sp"
   android:textColor="#FFFFFF"
   android:button="@drawable/checkboxes"
   android:text="@string/soloR" />

很好,您可能会看到android:button属性设置为您刚刚定义的checkboxes。完成后,删除star.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() ...实施,并将其替换为:

onCheckedChangeListener (CompoundButton.OnCheckedChangeListener listener) 

onCheckedChanged的听众提供了两个参数:CompoundButton buttonView, boolean isChecked

基本上,第二个告诉你你的星是否闪亮。您的其余代码似乎通常是合理的,但是:

  • 我不会进行row = convertView分配。这是我多次见过的一种做法,没有任何意义,直接在convertView实例上工作。

  • 我不知道你在ListView内有多少行,但如果它们太多或者它们难以渲染,我会考虑使用viewHolder秒。如果你还没有与他们合作,那么nice link可以解释这一点。

  • 我看到你在每一行都使用findViewById()。这可能会导致巨大的性能问题,因为这种调用非常昂贵。我会在你的类中保存两个drawable(假设你的星可能只有2个声明),并在构造函数中分配它们,所以你只处理它们一次 - 或者正如我之前所说,使用viewHolder s此

  • 请记住一件事:如果您没有保存更改的状态,那么一旦您的行&#34;消失&#34;从屏幕(例如,因为用户在列表中滚动)并且新呈现的行,您将看到先前的状态 - 即,不会保存更改。为此,您在ArrayAdapter扩展程序中处理数据非常重要,每次用户点击星标时,都会在班级中保存其状态。我的意思是构造函数参数的第三个:public RatingAdapter(Context context, int textViewResourceId, String[] objects)。现在你只需拨打super,但你不能保存它。请注意,这是您的工作数据,任何更改都应反映在该Object数组中,否则每次您渲染行时,都不会保存更改。例如:

    class RatingAdapter extends ArrayAdapter<String> 
    {
        Context ctx;
        LayoutInflater inflater;
        TextView stationName;
        RatingBar star;
        ArrayMap<String, Boolean> rowLayout = ArrayMap<String, Boolean>();
    
        public RatingAdapter(Context context, int textViewResourceId, String[] objects) 
        {
            super(context, textViewResourceId, objects);
            ctx = context;
            inflater = LayoutInflater.from(context);
    
            for (String rowText : (String) objects)
              rowLayout.put(rowText, false);  // Supposing all your initial stars will be off
        }
    

    现在,您只需同步getView()方法即可告知Android 应如何进行管理。例如,如果值是false,那就把它放在一起 - 否则,把闪亮的星星等等放在一起。

----编辑----

关于如何跟踪变化:我不知道你是否最终决定使用viewHolder,所以我只是说明全局案例。

所有变更并且您希望继续跟踪的内容都应该在getView()方法中完成。在该方法中,请参阅第二个参数是名为View的{​​{1}}。说得非常模糊,这是每一行的布局,即每行的所有内容都包含在每个convertView中。所以基本上,每行至少会调用convertView一次。

假设您有一个布局,其中getView()的ID为CheckBox,而lvCheckBox的ID为TextView。您可以通过调用来有效地获得其中任何一个,例如:

lvTextView

任何监听器也应该在TextView tv = (TextView) convertView.findViewById(R.id.lvTextView); 方法中定义(如前所述)。从您的代码开始,您似乎已经清楚了解到目前为止的事情。

现在,如何管理更改:考虑到您需要实现我之前发布的关于在getView()扩展中存储数据结构的内容,您应该注意3个概念:

  • ArrayListposition的第一个参数是调用渲染项的位置。但请注意,当您在getView()方法中定义听众时,您也可以访问此参数,这一点至关重要。

  • getView()getItem(position)是来自getItem()类的方法,它从列表中返回一个项目。在ArrayAdapter上调用此方法将返回正在呈现的项目。它会返回您position所属的类型,因此,如果您有ArrayAdapter个,那么您将获得String

  • String。每次数据集更改时,都必须在适配器上调用此方法。理想的方法是在调用Fragment / Activity中执行此操作,但如果您不能(例如,因为您不知道何时会被触发(侦听器)),您可以在您的内部获得适配器监听器并在监听器中调用此方法,这样:

    notifyDataSetChanged()

了解所有这些,只剩下一步了:从ArrayAdapter的数据集副本中删除该项目,您将使用final ListView lv = (ListView) findViewById(R.id.your_listview)); RatingAdapter adapter = (RatingAdapter) lv.getAdapter(); adapter.notifyDataSetChanged(); 了解该项目并致电getItem(position)在您的适配器上 - 如果您需要在其内部或从您的片段/活动中解雇,则从内部开始。

另一种(可能更简单)方法是在您的片段/活动中调用适配器上的notifyDataSetChanged().add,然后在其上调用.del。然而,这并非总是可行。

例如,我有一个notifyDataSetChanged()的自定义布局。这是我宣布它的方式:

ListView

我在private ArrayList<String> elemlist; elemlist.add("First row"); elemlist.add("Second one"); MultiLayoutArrayAdapter adapter = new MultiLayoutArrayAdapter(MyActivity.this, R.layout.my_custom_layout, elemlist);

中打电话
Activity

这会出现在我的行​​上。但有时你不想只是添加或删除,而是修改:这是你的情况(elemlist.add("Yet another row"); adapter.notifyDataSetChanged(); 听取被点击),所以当上述内容进入时行动。您必须使用CheckBox修改项目列表并将其从getItem(position)结构中删除,然后在rowLayout内调用notifyDataSetChanged()

答案 1 :(得分:0)

您可以通过复选框完成此操作。设置两个图像oncheck(setimage(高亮星))并取消选中(setimage(撤消图像))。

CheckBox fav;
boolean isCheck=false;

如果(!isCheck){

fav.setChecked(true);
                    checked.setBackgroundResource(R.drawable.blue_star);
                }else{

                    fav.setBackgroundResource(R.drawable.grey_star);

        fav.setChecked(false);
                }