-1

I'm trying to make a custom listview with multiple values, which have buttons for sorting. This way the listview can be sorted for different values, like year, name and price etc.

I'm still pretty new to Android Studio and coding in general, so if anything is just plain off, then i apologize!

Problem is, nothing is sorted when i press any of the buttons. I tried using a comparable, for sorting in ascending order numerically, but that doesn't seem to work (not getting any errors, just nothing happens).

Here is what i've tried, showing my custom rows first, and then custom list adapter:

My Custom Row Layout:

    <TextView
        android:layout_width="40dp"
        android:layout_height="35dp"
        android:layout_marginLeft="10dp"
        android:text="Time:"
        android:id="@+id/time_label_row"
        android:gravity="center"
        android:layout_weight="1"/>

    <TextView
        android:layout_width="40dp"
        android:layout_height="35dp"
        android:text="time"
        android:id="@+id/time_row"
        android:gravity="center"
        android:layout_weight="1"/>

    <TextView
        android:layout_width="40dp"
        android:layout_height="35dp"
        android:layout_marginLeft="10dp"
        android:text="Price:"
        android:id="@+id/price_label_row"
        android:gravity="center"
        android:layout_weight="1"/>

    <TextView
        android:layout_width="40dp"
        android:layout_height="35dp"
        android:text="price"
        android:id="@+id/price_row"
        android:gravity="center"
        android:layout_weight="1"/>

    <TextView
        android:layout_width="40dp"
        android:layout_height="35dp"
        android:layout_marginLeft="10dp"
        android:text="Year:"
        android:id="@+id/year_label_row"
        android:gravity="center"
        android:layout_weight="1"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="35dp"
        android:text="year"
        android:id="@+id/year_row"
        android:gravity="center"
        android:layout_weight="1"/>

</LinearLayout>

<View
    android:layout_width="match_parent"
    android:layout_height="1dp"
    android:background="@color/colorPrimaryDark"
    />

My Custom Listview (only the buttons insteresting here):

<LinearLayout
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="50dp">
<Button
    android:text="Time"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/sort_time"
    android:layout_weight="1"
    android:onClick="TimeSortClick"/>

<Button
    android:text="Price"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/sort_price"
    android:layout_weight="1"
    android:onClick="PriceSortClick"/>

<Button
    android:text="Year"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/sort_year"
    android:layout_weight="1"
    android:onClick="YearSortClick"/>

</LinearLayout>

<ListView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/list_view"
    android:smoothScrollbar="true"/>

My Custom Adapter:

public class CustomAdapter extends BaseAdapter {
String [] result1;
String [] result2;
String [] result3;
Context context;

private static LayoutInflater inflater=null;
public CustomAdapter(ListViewActivity mainActivity, String[] priceOrderList, String [] timeOrderList, String [] yearOrderList) {
    // TODO Auto-generated constructor stub
    result1=priceOrderList;
    result2=timeOrderList;
    result3=yearOrderList;
    context=mainActivity;
    inflater = ( LayoutInflater )context.
            getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
    // TODO Auto-generated method stub
    return result1.length;
}

@Override
public Object getItem(int position) {
    // TODO Auto-generated method stub
    return position;
}

@Override
public long getItemId(int position) {
    // TODO Auto-generated method stub
    return position;
}

public class Holder
{
    TextView tv;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    Holder holder=new Holder();
    View rowView;
    rowView = inflater.inflate(R.layout.row_layout, null);
    holder.tv=(TextView) rowView.findViewById(R.id.price_row);
    holder.tv.setText(result1[position]);
    holder.tv=(TextView) rowView.findViewById(R.id.time_row);
    holder.tv.setText(result2[position]);
    holder.tv=(TextView) rowView.findViewById(R.id.year_row);
    holder.tv.setText(result3[position]);
    rowView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Toast.makeText(context, "You Clicked "+result1[position], Toast.LENGTH_LONG).show();
        }
    });
    return rowView;
}

My ListView Activitiy(or activity where i inflate my custom listview):

public class ListViewActivity extends Activity implements View.OnClickListener {

ListView view_list;
Context context;

ArrayList priceOrder;
public static String [] priceOrderList={"50$","100$","120$","40$"};
public static String [] timeOrderList={"10min","12min","5min","4min"};
public static String [] yearOrderList={"2010","2011","2012","2004"};

private Button mTimeButton;
private Button mPriceButton;
private Button mYearButton;



@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_list_view);

    context=this;

    mTimeButton = (Button) findViewById(R.id.sort_time);
    mPriceButton = (Button) findViewById(R.id.sort_price);
    mYearButton = (Button) findViewById(R.id.sort_year);
    view_list = (ListView) findViewById(R.id.list_view);
    view_list.setAdapter(new CustomAdapter(this, priceOrderList, timeOrderList, yearOrderList));

    mTimeButton.setOnClickListener(this);
    mPriceButton.setOnClickListener(this);
    mYearButton.setOnClickListener(this);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public void onClick(View v) {
    if (v == mPriceButton){

        String pricesort = ("Sorting for Price");

        Toast.makeText(ListViewActivity.this, pricesort, Toast.LENGTH_SHORT).show();

        Comparator<String> StringAscComparator = new Comparator<String>() {

            public int compare(String app1, String app2) {

                String stringName1 = app1;
                String stringName2 = app2;

                return stringName1.compareToIgnoreCase(stringName2);
            }
        };

        Collections.sort(Arrays.asList(priceOrderList), StringAscComparator);

    } else if (v == mTimeButton){

        String timesort = ("Sorting for Time");

        Toast.makeText(ListViewActivity.this, timesort, Toast.LENGTH_SHORT).show();

        Comparator<String> StringAscComparator = new Comparator<String>() {

            public int compare(String app1, String app2) {

                String stringName1 = app1;
                String stringName2 = app2;

                return stringName1.compareToIgnoreCase(stringName2);
            }
        };

        Collections.sort(Arrays.asList(timeOrderList), StringAscComparator);

    } else if (v == mYearButton){

        String yearsort = ("Sorting for Year");

        Toast.makeText(ListViewActivity.this, yearsort, Toast.LENGTH_SHORT).show();

        Comparator<String> StringAscComparator = new Comparator<String>() {

            public int compare(String app1, String app2) {

                String stringName1 = app1;
                String stringName2 = app2;

                return stringName1.compareToIgnoreCase(stringName2);
            }
        };

        Collections.sort(Arrays.asList(yearOrderList), StringAscComparator);

    }
}

Anyways, thanks for the help! It's much appreciated!

  • Obviously using 3 arrays of Strings instead 1 array of POJO doesn't make sens ... you only sort one of the array wiout touching others, so even if you would inform the adapter that that had changed you will get wrong items (fx. priceOrder would not fit yearOrder) ... [another problem is String vs Numeric ordering](http://ideone.com/lWQPg5) ... – Selvin Oct 31 '16 at 13:53
  • Help us understand the meaning of the data a little better. Is a price associated with a time and a year such that a price/time/year makes up some kind of entity? And you just want to sort the entities on each of the different fields? I see you have one of each field on a list item... Or are you just changing the list from say, displaying prices to displaying times? – kris larson Oct 31 '16 at 13:57
  • @Selvin is there a different way to make such a listview that i attempted, where you could sort for all three values? I get my approach is wrong and doesn't make sense, but there's gotta be a different way to do it then? :) – Simon A. Callaghan Jensen Oct 31 '16 at 14:02
  • @kris larson yes time, price and year are supposed to be directly associated with each other, so that you can sort for all three values. Say you would want to sort the listview for years ascending from lowest, then you would just press the year sorting button. The 2 other values would follow suit for the year-values they where associated with. So 50$ - 10min - 2010 are supposed to be together. – Simon A. Callaghan Jensen Oct 31 '16 at 14:05
  • *So 50$ - 10min - 2010 are supposed to be together.* ... then use POJO : `class POJO { int year, int timeInMin, double price }` ... and use `ArrayList` (as in bazillions examples) ... so sorting by one of the field would sort whole ArrayList ... – Selvin Oct 31 '16 at 14:09
  • @Selvin I made a quick google search to try and figure out what you meant with POJO class (still new to programming, sorry) and i found this example making a similar listview: http://publicstaticdroidmain.com/2011/12/building-a-custom-multi-line-listview-in-android/ - The way he does it in this example would tie the data together right? If this wouldn't work, then do you know of any similar examples that could help me out? Thanks for the help! It's very much appreciated! – Simon A. Callaghan Jensen Oct 31 '16 at 14:30

2 Answers2

1

In his comment, @Selvin suggests using a POJO to associate your data, and that's a great idea. It's best to find appropriate data types for your data:

    public class Item {

        public BigDecimal price;  // why BigDecimal? http://stackoverflow.com/a/8148773/4504191

        public Duration time;     // this is from the new java.time API in v8

        public int year;          // java.time also has a Year class

    }

A proper class would have private fields with setters and getters (left as an exercise for the reader).

Now you just have a List<Item> in your adapter.

These data types will also make your comparison logic a little easier.

There's so many different ways you could do this. I think what I would do is create a method on the adapter to sort the list, specifying a comparator:

       public void sortUsing(Comparator<Item> comparator) {

           Collections.sort(list, comparator);
           notifyDataSetChanged();
       }

Then I would create three different comparators — one for each field — and pass the appropriate comparator when the corresponding sort button is pressed. Here's the time version:

        Comparator<Item> timeComparator = new Comparator<Item> {

            @Override
            int compare(Item lhs, Item rhs) {
                return lhs.time.compareTo(rhs.time);
            }
        }
kris larson
  • 30,387
  • 5
  • 62
  • 74
-1

Write a method to sort your array. Add one more parameter to your adapter constructor .onClick of btn assign the adapter again like view_list.setAdapter(new CustomAdapter(this, priceOrderList, sortArray(timeOrderList), yearOrderList,2)); based on the the new param assign the values into listview from adapter.

ps: sorry for writing comment this here , low rep :)

Shahal
  • 1,008
  • 1
  • 11
  • 29
  • calling `Adapter.notifyDatasetChanged` after sorting would do it better(without creating new `CustomAdapter` instance) ... but as i wrote in the comment, it will make another problem – Selvin Oct 31 '16 at 14:12
  • what other problem ? could you please mention it here ? – Shahal Oct 31 '16 at 14:45
  • *what other problem ? could you please mention it here ?* ... it seems like you do not understand: ***but as i wrote in the comment*** ? – Selvin Oct 31 '16 at 14:46