java - 如何创建自定义 Android Listview 标题并将它们分组为几天

标签 java android xml listview

我的目标是创建一个应用程序来显示按天分组的数据列表。实际截图见下图。

Screenshot of the app that I want to have

为了实现这个设计,我使用了自定义数组列表适配器来实现这个设计。下面是我的 DiaryListAdapter

类文件
public class DiaryListAdapter extends ArrayAdapter<Records> {

/**
 * Adapter context
 */
Context mContext;

/**
 * Adapter View layout
 */
int mLayoutResourceId;

int selectedItem = -1;


private Records _records;

public DiaryListAdapter(Context context, int layoutResourceId, ArrayList<Records> recordItems) {
    super(context, layoutResourceId, recordItems);

    this.mContext = context;
    this.mLayoutResourceId = layoutResourceId;
}

private static class ViewHolder {
    TextView diaryTime, diarySysDia, diaryPul, itemDate, itemToday;
    LinearLayout llDiaryHead;
}



/**
 * Returns the view for a specific item on the list
 */
@Override
public View getView(int position, View convertView, ViewGroup parent) {


    // Declare the new object
    ViewHolder viewHolder;

    if (convertView == null) {



        LayoutInflater inflater = (LayoutInflater) mContext
                .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);

        convertView = inflater.inflate(R.layout.lv_diarycontent_adapter, null);

        // Instantiate the object
        viewHolder = new ViewHolder();

        viewHolder.itemDate = (TextView) convertView.findViewById(R.id.itemDate);
        viewHolder.itemToday = (TextView) convertView.findViewById(R.id.itemToday);
        viewHolder.diaryTime = (TextView) convertView.findViewById(R.id.itemTime);
        viewHolder.diarySysDia = (TextView) convertView.findViewById(R.id.itemSysDia);
        viewHolder.diaryPul = (TextView) convertView.findViewById(R.id.itemPulse);
        viewHolder.llDiaryHead = (LinearLayout) convertView.findViewById(R.id.ll_diaryhead);


        convertView.setTag(R.id.TAG_DIARY_VIEWHOLDER_ID, viewHolder);

    } else {

        // Instantiate the new object
        viewHolder = (ViewHolder) convertView.getTag(R.id.TAG_DIARY_VIEWHOLDER_ID);

    }

    // Declare the reminder object
    _records = getItem(position);

    if (_records.getIsDateHead()) {

        // Hide the layout header
        viewHolder.llDiaryHead.setVisibility(View.VISIBLE);

        // Display the value on textview
        viewHolder.itemDate.setText(FormatterMgr.DSPLY_DATE_LSTVIEW.format(_records.getRecordCreatedOn()));

        // Display the value inside the content
        viewHolder.diaryTime.setText(_records.getRecordCreatedOn().toString());
        viewHolder.diarySysDia.setText(_records.getSys() + "/" + _records.getDia());
        viewHolder.diaryPul.setText(Float.toString(_records.getHr()));


    } else {

        // Hide the layout header
        viewHolder.llDiaryHead.setVisibility(View.GONE);

        // Display the value inside the content
        viewHolder.diaryTime.setText(_records.getRecordCreatedOn().toString());
        viewHolder.diarySysDia.setText(_records.getSys() + "/" + _records.getDia());
        viewHolder.diaryPul.setText(Float.toString(_records.getHr()));
    }




    convertView.setTag(R.id.TAG_DIARY_LIST_ID, _records);


    return convertView;
}

public void setSelectedItem(int selectedItem) {
    this.selectedItem = selectedItem;
}

下一节课是DiaryFragment。这是我编写要在页面内显示的 ListView 的 UI 代码隐藏文件。这是我在尝试显示 ListView 并相应地按天分组时遇到困难的代码。

public class DiaryFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_DIARY = "diary";
private static final String ARG_PARAM2 = "param2";

// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;


RecordsTableHelper rth;

HashSet<String> uniqueSet;
ArrayList<Records> mRecordsArrayList;
ListView mDiaryListView;


/**
 * Use this factory method to create a new instance of
 * this fragment using the provided parameters.
 *
 * @param param1 Parameter 1.
 * @param param2 Parameter 2.
 * @return A new instance of fragment DiaryFragment.
 */
// TODO: Rename and change types and number of parameters
public static DiaryFragment newInstance(String param1, String param2) {
    DiaryFragment fragment = new DiaryFragment();
    Bundle args = new Bundle();
    args.putString(ARG_DIARY, param1);
    args.putString(ARG_PARAM2, param2);
    fragment.setArguments(args);

    return fragment;
}

public DiaryFragment() {
    // Required empty public constructor
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        mParam1 = getArguments().getString(ARG_DIARY);
        mParam2 = getArguments().getString(ARG_PARAM2);

    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_diary, container, false);


    // Declare the database to retrieve all the data from the table
    DatabaseHelper _dbHelper = DBMgr.openConnection(getContext());
    rth = new RecordsTableHelper(_dbHelper.getDatabase());


    // Get all the records value and store inside an array list
    mRecordsArrayList = new ArrayList<Records>(rth.getAllRecords());
    Collections.sort(mRecordsArrayList, new RecordsComparator()); // Sort all the arraylist according to its date time


    //mRecordsArrayListSize = mRecordsArrayList.size();

    mDiaryListView = (ListView)view.findViewById(R.id.listViewDiary);
    mDiaryListView.setOnItemClickListener(new OnPlandetailsitemClickListener());

    setHasOptionsMenu(true);

    return view;
}





@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.menu_diary, menu);
    super.onCreateOptionsMenu(menu,inflater);
}


@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_adddiary) {
        Intent intent = new Intent(getActivity(), NewDiaryActivity.class);
        startActivityForResult(intent, ActivityResults.newdiaryactivityresult);

        // Create Animation
        getActivity().overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
    }

    return super.onOptionsItemSelected(item);
}

@Override
public void onResume() {
    super.onResume();


    // Get the total day sum from the database
    int totalUniqueDays = getTotalUniqueDays();


    /* Declare the database to retrieve all the data from the table
    DatabaseHelper _dbHelper = DBMgr.openConnection(getContext());
    rth = new RecordsTableHelper(_dbHelper.getDatabase());
    */


    // 1) Create a for loop
    for (int i = 0; i<mRecordsArrayList.size(); i++) {




        Log.d("NON REPEATED DAYS", FormatterMgr.DB_DATE.format(mRecordsArrayList.get(i).getRecordCreatedOn()));

        // Set the first column header
        if (i==0) {
            // Add it into the arraylist
            mRecordsArrayList.get(i).setDateHead(true);

        }





        // 2) Inside the for loop, set the comparison of unique value occurs in the record array list method by checking the getUniqueDaysPos method
        // 3) If the unique value occurred, set the date head inside the arraylist
        // 4) Store the arraylist into the adapter

        /*
        // Get the total number of repeated days
        int totalRepeatedDays = getTotalRepeatedDays(mRecordsArrayList.get(i).getRecordCreatedOn());

        for (int j = 0; j<totalRepeatedDays; j++) {
            if (j==0) {
                // Add it into the arraylist
                mRecordsArrayList.get(j).setDateHead(true);
            }
        }
        */



    }


    DiaryListAdapter adapter = new DiaryListAdapter(getActivity(),
            R.layout.lv_diarycontent_adapter, mRecordsArrayList);
    mDiaryListView.setAdapter(adapter);


}

//response the click on listview
//the click listener for pastplan listview
private class OnPlandetailsitemClickListener implements ListView.OnItemClickListener {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

        DiaryListAdapter adapter = (DiaryListAdapter) mDiaryListView.getAdapter();

        adapter.setSelectedItem(position);
        mDiaryListView.setAdapter(adapter);

        // Get the ID
        Records _records = (Records)view.getTag(R.id.TAG_DIARY_LIST_ID);


        //Direct to the reminder info activity
        Intent intent = new Intent(getActivity(), NewDiaryActivity.class);
        intent.putExtra(IntentResults.newDiary_id_val, _records.getRecord_id());

        startActivityForResult(intent, ActivityResults.inforeminderactivityresult);

        // Create Animation
        getActivity().overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
    }
}




// Get the overall number of non repeated days inside record database
public int getTotalUniqueDays() {



    // Declare the current date and next date as 0
    String currentDate, nextDate = null;

    // Declare the result as 0. The result will be produce the outcome of the final result
    int result = 0;

    ArrayList<String> tempRecordsArrayList = new ArrayList<String>();

    // Declare the database to retrieve all the data from the table
    for (int i = 0; i<mRecordsArrayList.size(); i++) {

        // Convert the date time to date
        currentDate = FormatterMgr.DB_DATE.format(mRecordsArrayList.get(i).getRecordCreatedOn());

        tempRecordsArrayList.add(currentDate);


    }
    uniqueSet = new HashSet<String>();
    uniqueSet.addAll(tempRecordsArrayList);
    return uniqueSet.size();
}


public ArrayList<Integer> getUniqueDaysPos() {

    // 1) Get the unique set and store into arraylist
    ArrayList<String> tempUniqueSet = new ArrayList<String>(uniqueSet);

    // 2) Get the full set of record array list
    ArrayList<Records> tempRecordsSet = mRecordsArrayList;

    // 3) Create the object of null arraylist integer
    ArrayList<Integer> uniqueDaysPos = new ArrayList<Integer>();

    // 4) Loop through the fullset arraylist and produce the result of the position of unique dates inside the full set of array list
    for (int i = 0; i<tempRecordsSet.size(); i++) {

        // 5) Store the unique dates position inside the set of integer arraylist
        uniqueDaysPos.add(tempRecordsSet.indexOf(tempUniqueSet));
    }


    return uniqueDaysPos;
}

public int getTotalRepeatedDays(Date dateValue) {

    // Declare the database to retrieve all the data from the table
    DatabaseHelper _dbHelper = DBMgr.openConnection(getContext());
    rth = new RecordsTableHelper(_dbHelper.getDatabase());

    // Get all the records value and store inside an array list
    ArrayList<Records> mRecordsDateRepeatedList = rth.getAllRecordsByDate(dateValue);


    return mRecordsDateRepeatedList.size();

}


 }

下面是列表适配器的 lv_diarycontent_adapter XML 文件。在这种情况下,DiaryListAdapter 背后的代码将根据每条记录的条件切换标题。

<?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<!-- START OF HEAD LAYOUT -->
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingLeft="15dp"
    android:paddingTop="5dp"
    android:paddingBottom="5dp"
    android:orientation="horizontal"
    android:id="@+id/ll_diaryhead"
    android:background="@color/colorPrimary">


    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="0.3">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Mon 1, 1976"
            android:id="@+id/itemDate"
            android:layout_alignParentLeft="true"
            android:textAppearance="?android:attr/textAppearanceListItemSmall"
            android:textStyle="bold"
            android:textColor="@color/font_color_white"
            android:layout_marginBottom="5dp" />





    </LinearLayout>


    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="0.7">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=""
            android:id="@+id/itemToday"
            android:textAppearance="?android:attr/textAppearanceListItemSmall"
            android:textStyle="bold"
            android:textColor="@color/font_color_white" />

    </LinearLayout>

</LinearLayout>
<!-- END OF HEAD LAYOUT -->


<!-- START OF BODY LAYOUT -->
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">



    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="0.25"
        android:gravity="center_horizontal">

       <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="10:30"
            android:id="@+id/itemTime"
            android:textAppearance="?android:attr/textAppearanceListItemSmall"
            android:layout_marginBottom="5dp" />





    </LinearLayout>


    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="0.5"
        android:gravity="center_horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="120/75"
            android:id="@+id/itemSysDia"
            android:textAppearance="?android:attr/textAppearanceListItemSmall"
            ></TextView>

    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="0.25"
        android:gravity="center_horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="80"
            android:id="@+id/itemPulse"
            android:textAppearance="?android:attr/textAppearanceListItemSmall"
            ></TextView>

    </LinearLayout>

</LinearLayout>
<!-- END OF BODY LAYOUT -->

我现在不得不创建 ListView 并将记录分组到日期中。 到目前为止,我的尝试是按日期按升序对记录进行排序,并用数据填充 ListView 。我尝试使用嵌套的 for 循环和唯一天数,并在其中循环重复的天数。但是,它不起作用。

感谢您花时间阅读本文,如果您有任何疑问,我们很乐意回答您的所有问题!

最佳答案

你可以试试..& android 看起来像下面这样 enter image description here

  1. 创建一个项目
  2. 复制并粘贴到 activity_main.xml

       <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
       android:orientation="vertical" >
    
         <!-- Content Here -->
    
     <LinearLayout
       android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:layout_weight=".1"
       android:background="#f1e7ce"
      android:orientation="vertical">
    
    
      <ListView
           android:id="@+id/listview"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"/>
    
        </LinearLayout>
    
    
    </LinearLayout>
    
  3. 创建section_header.xml 并粘贴以下代码

     <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:orientation="vertical" >
    
       <TextView 
           android:id="@+id/section_header"
           android:layout_width="match_parent"
           android:layout_height="30dp"
           android:background="#ff0092f4"
           android:textColor="#FFFFFF"
           android:text="Header"
           android:textSize="17sp"
          android:padding="4dp" />
    
       </LinearLayout>
    
  4. 创建row_item.xml 并粘贴以下代码

      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:orientation="horizontal" >
    
    
    <TextView 
         android:id="@+id/time_time"
         android:layout_width="0dp"
         android:layout_height="70dp"
         android:layout_weight="1"
         android:textSize="20sp" 
         android:text="12.00 PM"
         android:layout_marginLeft="15dp"
         android:gravity="center_vertical"
         android:textColor="#cc222222"/>
    
       <TextView 
          android:id="@+id/tv_item_sysdia"
          android:layout_width="0dp"
          android:layout_height="match_parent"
          android:layout_weight="1"
          android:textSize="15sp" 
          android:text="120/75"
          android:textColor="#cc222222"
          android:layout_marginRight="10dp"
          android:gravity="center_vertical|center"/>
    
     <TextView
         android:id="@+id/tv_item_plus"
         android:layout_width="0dp"
         android:layout_height="match_parent"
         android:layout_weight="1"
         android:textSize="15sp"
         android:text="80"
         android:textColor="#cc222222"
         android:layout_marginRight="10dp"
         android:gravity="center_vertical|center"/>
    
      </LinearLayout>
    
  5. 创建类 ItemModel 并粘贴以下代码

        public class ItemModel implements Comparable<ItemModel>{
         private  boolean isSectionHeader;
         private String itemTime;
         private String itemSysDia;
         private String itemPulse;
         private String date;
    
         public ItemModel(String itemTime, String itemSysDia, String itemPulse, String date) {
        this.itemTime = itemTime;
        this.itemSysDia = itemSysDia;
        this.itemPulse = itemPulse;
        this.date =date;
        isSectionHeader = false;
     }
    
      public String getItemTime() {
            return itemTime;
     }
    
    public void setItemTime(String itemTime) {
        this.itemTime = itemTime;
     }
    
    public String getItemSysDia() {
       return itemSysDia;
       }
    
       public void setItemSysDia(String itemSysDia) {
          this.itemSysDia = itemSysDia;
        }
    
     public String getItemPulse() {
         return itemPulse;
       }
    
      public void setItemPulse(String itemPulse) {
          this.itemPulse = itemPulse;
      }
    
       public String getDate() {
        return date;
        }
    
       public void setDate(String date) {
             this.date = date;
           }
    
       public boolean isSectionHeader() {
           return isSectionHeader;
      }
    
      @Override
      public int compareTo(ItemModel itemModel) {
          return this.date.compareTo(itemModel.date);
     }
    
      public void setToSectionHeader() {
        isSectionHeader = true;
       }
       }
    
  6. MainActivity中粘贴下面的代码

       public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
    
          ArrayList<ItemModel> itemsList = new ArrayList<>();
          ListView list = (ListView) findViewById(R.id.listview);
          itemsList = sortAndAddSections(getItems());
          ListAdapter adapter = new ListAdapter(this, itemsList);
         list.setAdapter(adapter);
      }
    
    
         private ArrayList sortAndAddSections(ArrayList<ItemModel> itemList)
       {
    
         ArrayList<ItemModel> tempList = new ArrayList<>();
          //First we sort the array
        Collections.sort(itemList);
    
          //Loops thorugh the list and add a section before each sectioncell start
        String header = "";
          for(int i = 0; i < itemList.size(); i++)
          {
               //If it is the start of a new section we create a new listcell and add it to our array
             if(!(header.equals(itemList.get(i).getDate()))) {
               ItemModel sectionCell = new ItemModel(null, null,null,itemList.get(i).getDate());
              sectionCell.setToSectionHeader();
              tempList.add(sectionCell);
               header = itemList.get(i).getDate();
           }
            tempList.add(itemList.get(i));
        }
    
        return tempList;
       }
    
    
      public class ListAdapter extends ArrayAdapter {
    
           LayoutInflater inflater;
            public ListAdapter(Context context, ArrayList items) {
            super(context, 0, items);
              inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            }
    
         @Override
           public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            ItemModel cell = (ItemModel) getItem(position);
    
           //If the cell is a section header we inflate the header layout
              if(cell.isSectionHeader())
             {
               v = inflater.inflate(R.layout.section_header, null);
    
              v.setClickable(false);
    
               TextView header = (TextView) v.findViewById(R.id.section_header);
               header.setText(cell.getDate());
            }
             else
            {
               v = inflater.inflate(R.layout.row_item, null);
                 TextView time_time = (TextView) v.findViewById(R.id.time_time);
                TextView tv_item_sysdia = (TextView) v.findViewById(R.id.tv_item_sysdia);
    
             TextView tv_item_plus = (TextView) v.findViewById(R.id.tv_item_plus);
    
              time_time.setText(cell.getItemTime());
              tv_item_sysdia.setText(cell.getItemSysDia());
              tv_item_plus.setText(cell.getItemPulse());
    
    
             }
           return v;
          }
          }
    
    
      private ArrayList<ItemModel>  getItems(){
    
        ArrayList<ItemModel> items = new ArrayList<>();
       items.add(new ItemModel("10.30", "120/10","80","Tue,31 Oct 17"));
        items.add(new ItemModel("10.30", "142/95","95","Tue,31 Oct 17"));
       items.add(new ItemModel("15.30", "120/95","200","Tue,31 Oct 17"));
       items.add(new ItemModel("20.30", "120/10","80","Tue,29 Oct 17"));
       items.add(new ItemModel("10.30", "120/10","50","Tue,29 Oct 17"));
    
       items.add(new ItemModel("10.30", "140/10","80","Tue,28 Oct 17"));
       items.add(new ItemModel("10.30", "30/75","40","Tue,28 Oct 17"));
       items.add(new ItemModel("10.30", "150/80","70","Tue,28 Oct 17"));
    
        return  items;
         }
        }
    
  7. 您可以从 GitHub 下载该项目:https://github.com/enamul95/CustomHeaderWith

  8. 可以看教程链接:http://www.iyildirim.com/tech-blog/creating-listview-with-sections

关于java - 如何创建自定义 Android Listview 标题并将它们分组为几天,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38427007/

相关文章:

java - Java 中的逻辑和循环问题

java - Java 中的加密技术保留输入文本的格式

xml - 使用 WebService 将产品添加到 PrestaShop 1.6.0.9

xml - 让 JAXB 运行得更快

c# - 使用 LINQ 解析 XML 获取子元素

java - 具有相同标识符值的不同对象已与该 session 相关联

java - 如何在二叉树中找到下一个顺序后继者?

Android布局重力不起作用

安卓布局 : fit View under Action Bar

java.net.SocketTimeoutException (安卓)