0

我正在使用房间数据库,并且我有一张表格,可以从中获取 LiveData 列表。在该表中有一个 Date 列,我在其中存储当前日期。默认选择当前日期,但用户也可以在向数据库中插入数据时更改日期。

我想以这种方式在回收站视图中显示这些数据 https://imgur.com/RYegFpG图片

我想根据月份和年份将这些数据划分为标题以及该月份年份的所有条目。

例如,用户在 2019 年 10 月插入数据,我希望这个“2019 年 10 月”作为 recyclerview 中的标题以及该月下面的所有条目。就像这样,所有月份的条目都应该以相同的方式显示,因为每个下个月成为标题,并且该月的条目在它下面。

我试图通过这样做来实现这一目标

if (!thisDate.equals(dBDate))
        {
            holder.transMonthWrapper.setVisibility(View.VISIBLE);

            if (IEList.getType().equalsIgnoreCase("income"))
            {
                String amount = ""+IEList.getAmount();
                holder.tvTransAmount.setText(amount);
                holder.tvTransAmount.setTextColor(Color.GREEN);

                holder.tvTransCategory.setText(IEList.getCategory());
                holder.tvTransCategory.setTextColor(Color.GREEN);
            }
            else
            {
                String amount = ""+IEList.getAmount();
                holder.tvTransAmount.setText(amount);
                holder.tvTransAmount.setTextColor(Color.RED);

                holder.tvTransCategory.setText(IEList.getCategory());
                holder.tvTransCategory.setTextColor(Color.RED);
            }

            thisDate = dBDate;

            holder.tvTransMonth.setText(thisDate);
        }

        else
        {
            holder.transMonthWrapper.setVisibility(View.GONE);

            if (IEList.getType().equalsIgnoreCase("income"))
            {
                String amount = ""+IEList.getAmount();
                holder.tvTransAmount.setText(amount);
                holder.tvTransAmount.setTextColor(Color.GREEN);

                holder.tvTransCategory.setText(IEList.getCategory());
                holder.tvTransCategory.setTextColor(Color.GREEN);
            }
            else
            {
                String amount = ""+IEList.getAmount();
                holder.tvTransAmount.setText(amount);
                holder.tvTransAmount.setTextColor(Color.RED);

                holder.tvTransCategory.setText(IEList.getCategory());
                holder.tvTransCategory.setTextColor(Color.RED);
            }
        }

但是这段代码中的问题是,当用户从设置中更改月份并将一些条目放入数据库时​​,那一年的月份条目已经存在于 recyclerview 中。它在 recyclerview 中创建该现有月份的另一个标题。但我希望将这些条目放在现有月份标题中,而不是创建该月的新标题。

在不使用外部库的情况下实现这一目标的最佳方法是什么,因为在这种情况下我不想依赖外部库。

我在编程方面相当新。

更新

活动中

 public void getTransactionData()
{
    adapter = new TransactionAdapter();
    recyclerView.setAdapter(adapter);

    incomeExpenseModel = ViewModelProviders.of(AllTransaction.this).get(IncomeExpenseViewModel.class);
    incomeExpenseModel.getIncomeExpenseData().observe(this, new Observer<List<IncomeExpense>>() {
        @Override
        public void onChanged(List<IncomeExpense> incomeExpenses) {

            adapter.setIncomeExpenseList(incomeExpenses);
        }
    });

在回收器适配器中

public void onBindViewHolder(@NonNull TransactionViewHolder holder, int position) {

    IncomeExpense IEList = incomeExpenseList.get(position);

    preferences = context.getSharedPreferences(settingPref, Context.MODE_PRIVATE);
    String dateFormat = preferences.getString("Date_Format", "MM.dd.yy");

    int lastIndex = incomeExpenseList.size() - 1;
    IncomeExpense IELastIndex = incomeExpenseList.get(lastIndex);

    String dateFrmDb= IELastIndex.getDate();
    DateFormat df=new SimpleDateFormat(dateFormat);
    Date d;

    try {
        d = df.parse(dateFrmDb);
        df=new SimpleDateFormat("MMMM yyyy");
        if (d != null) {
            dBDate = df.format(d);
        }
    } catch (ParseException e) {

        Toast.makeText(context, "Error" +e, Toast.LENGTH_SHORT).show();
    }

    if (!thisDate.equals(dBDate))
    {
        holder.transMonthWrapper.setVisibility(View.VISIBLE);

        if (IEList.getType().equalsIgnoreCase("income"))
        {
            String amount = ""+IEList.getAmount();
            holder.tvTransAmount.setText(amount);
            holder.tvTransAmount.setTextColor(Color.GREEN);

            holder.tvTransCategory.setText(IEList.getCategory());
            holder.tvTransCategory.setTextColor(Color.GREEN);
        }
        else
        {
            String amount = ""+IEList.getAmount();
            holder.tvTransAmount.setText(amount);
            holder.tvTransAmount.setTextColor(Color.RED);

            holder.tvTransCategory.setText(IEList.getCategory());
            holder.tvTransCategory.setTextColor(Color.RED);
        }

        thisDate = dBDate;

        holder.tvTransMonth.setText(thisDate);
    }

    else
    {
        holder.transMonthWrapper.setVisibility(View.GONE);

        if (IEList.getType().equalsIgnoreCase("income"))
        {
            String amount = ""+IEList.getAmount();
            holder.tvTransAmount.setText(amount);
            holder.tvTransAmount.setTextColor(Color.GREEN);

            holder.tvTransCategory.setText(IEList.getCategory());
            holder.tvTransCategory.setTextColor(Color.GREEN);
        }
        else
        {
            String amount = ""+IEList.getAmount();
            holder.tvTransAmount.setText(amount);
            holder.tvTransAmount.setTextColor(Color.RED);

            holder.tvTransCategory.setText(IEList.getCategory());
            holder.tvTransCategory.setTextColor(Color.RED);
        }
    }

}

@Override
public int getItemCount() {
    return incomeExpenseList.size();
}

public void setIncomeExpenseList(List<IncomeExpense> incomeExpenseList)
{
    this.incomeExpenseList = incomeExpenseList;
    notifyDataSetChanged();
}
4

3 回答 3

1

您不需要使用任何第三方库。您可以使用ExpandableListView它而不实际使其“扩展和折叠”来做您需要的完全相同的事情。请参阅我对这篇文章的回答。这里的优点是您可以像处理 一样轻松地处理它ExpandableListView,而无需自定义代码。您只需将一条线添加到其他标准ExpandableListView适配器。

@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
    ...
    ((ExpandableListView) parent).expandGroup(groupPosition);
    ...
}

您可以将部分标题设置为组视图,并将列表项设置为子项。在传递给适配器之前,您的数据结构需要更新。它必须是分组数据,而不是必须传递给可扩展适配器的普通列表(例如,类数组,每个实例都包含String组头和对象的属性ArrayListIncomeExpense。并且当您更新数据时,在相应的组中进行更新,而不是整个数据。

于 2019-11-01T07:45:24.933 回答
1

父回收站view

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".fragments.PhotoFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_photo"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical"
        android:clipToPadding="false"
        android:paddingBottom="170dp">

    </androidx.recyclerview.widget.RecyclerView>

</FrameLayout>

它的适配器

public class PhotoAdapter extends RecyclerView.Adapter<PhotoAdapter.ViewHolder> {

    private static final String TAG = "PhotoAdapter";
    private Map<String, List<Photo>> photoMap;
    private Context context;
    private PhotoCategoryAdapter photoCategoryAdapter;
    private List<String> keysList;

    public PhotoAdapter(Map<String, List<Photo>> photoMap, Context context, List<String> keysList) {
        this.photoMap = photoMap;
        this.context = context;
        this.keysList = keysList;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new ViewHolder(LayoutInflater.from(parent.getContext())
                .inflate(R.layout.row_photo, parent, false));
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        String date  = keysList.get(position);
        holder.lblTakenDate.setText(date);

        List<Photo> photoList = photoMap.get(date);
        String size = ("( "+ photoList.size() + " )");
        holder.lblCountPhotos.setText(size);

        setRecyclerView(holder, context, photoList);

    }

    @Override
    public int getItemCount() {
        return photoMap.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.rv_photo_category) RecyclerView recyclerView;
        @BindView(R.id.lbl_taken_date_photo) TextView lblTakenDate;
        @BindView(R.id.lbl_count_images_photo) TextView lblCountPhotos;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }
}

Recyclerview里面的Reyclerview

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="5dp">

    <TextView
        android:id="@+id/lbl_taken_date_photo"
        android:textColor="@android:color/black"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="5dp"
        android:textSize="14dp"
        android:hint="23-Aug-2018" />

    <TextView
        android:id="@+id/lbl_count_images_photo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="5dp"
        android:layout_toRightOf="@id/lbl_taken_date_photo"
        android:hint="(2)"
        android:textSize="12sp" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_photo_category"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/lbl_taken_date_photo"
        android:layout_marginTop="10dp"
        android:background="@color/light_grey" />

</RelativeLayout>

它的适配器

public class PhotoCategoryAdapter extends RecyclerView.Adapter<PhotoCategoryAdapter.ViewHolder> {

    private static final String TAG = "PhotoCategoryAdapter";
    private List<Photo> photoList;
    private Context context;

    public PhotoCategoryAdapter(List<Photo> photoList, Context context) {
        this.photoList = photoList;
        this.context = context;

    }

    @NonNull
    @Override
    public PhotoCategoryAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.row_category_photo, parent, false));
    }


    @Override
    public void onBindViewHolder(@NonNull PhotoCategoryAdapter.ViewHolder holder, int position) {
        Photo photo = photoList.get(position);

        RequestOptions myOptions = new RequestOptions() .format(DecodeFormat.PREFER_ARGB_8888).
                fitCenter().override(100, 100).placeholderOf(R.drawable.ic_image);

        Glide.with(context)
                .applyDefaultRequestOptions(myOptions)
                .asBitmap()
                .load(photo.getImage())
                .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
                .into(holder.imgVImages);
    }

    @Override
    public int getItemCount() {
        return photoList.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        @BindView(R.id.imgv_images_category_photo)
        ImageView imgVImages;
        @BindView(R.id.imgv_selected_icon_photo) ImageView imgVSelectedPhoto;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }
}

内部recyclerview的行

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_margin="5dp"
    android:layout_width="80dp"
    android:layout_height="80dp">

    <ImageView
        android:id="@+id/imgv_images_category_photo"
        android:scaleType="fitXY"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <ImageView
        android:id="@+id/imgv_selected_icon_photo"
        android:visibility="gone"
        android:layout_width="15dp"
        android:layout_height="15dp"
        android:layout_margin="10dp"
        android:src="@drawable/ic_select"
        android:layout_alignParentEnd="true"/>

</RelativeLayout>

将数据发送到适配器的活动或片段

public class PhotoFragment extends Fragment {

    @BindView(R.id.rv_photo) RecyclerView recyclerView;

    private PhotoAdapter photoAdapter;
    private ArrayList<Photo> photoList;
    private ArrayList<String> keyList;
    private Map<String,List<Photo>> map;

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

        init();
        setRecyclerViewAdapter();
        new PhotoAsync(getContext()).execute();

        return view;
    }

    private void init(){
        map = new HashMap<>();
        keyList = new ArrayList<>();
        photoList = new ArrayList<>();
    }

    //set layout manager to recyclerView
    private void setRecyclerViewAdapter() {
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
    }

    //get list of images
    @RequiresApi(api = Build.VERSION_CODES.Q)
    private List<Photo> getAllImages(){
        Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        String[] projection = {MediaStore.Images.ImageColumns.DATA, MediaStore.Images.ImageColumns.DATE_TAKEN};
        Cursor c = null;
        ArrayList<Photo> photoList = new ArrayList<>();

        if (u != null) {
            c = getContext().getContentResolver().query(u, projection, null, null, null); }

        if ((c != null) && (c.moveToFirst())) {
            do {
                Photo photo = new Photo();
                String path = c.getString(c.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATA));

                String takenDate = c.getString(c.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATE_TAKEN));
                long millisecond = Long.parseLong(takenDate);
                String date = DateFormat.format("dd-MMM-yyyy", new Date(millisecond)).toString();

                try{
                    photo.setImage(path);
                    photo.setDate(date);
                    photoList.add(photo);
                }
                catch(Exception e)
                { }

            }
            while (c.moveToNext());
        }
        //reverse photoList
        Collections.reverse(photoList);

        return photoList;
    }

    public class PhotoAsync extends AsyncTask<Void, Void,  Void> {
        private Context context;

        public PhotoAsync(Context context) {
            this.context = context;
        }

        @RequiresApi(api = Build.VERSION_CODES.Q)
        @Override
        protected Void doInBackground(Void... params) {
            getPhotoList();
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            photoAdapter = new PhotoAdapter(map, context, keyList);
            recyclerView.setAdapter(photoAdapter);
            photoAdapter.notifyDataSetChanged();
        }

        @Override
        protected void onPreExecute() {
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.Q)
    private void getPhotoList(){
        photoList.addAll(getAllImages());

        for (Photo string : photoList) {
            if (!keyList.contains(string.getDate()))
                keyList.add(string.getDate());
            else;
        }

        for (String s : keyList){
            ArrayList<Photo> photos = new ArrayList<>();
            for (Photo s1 : photoList) {
                if (s1.getDate().equals(s))
                    photos.add(s1);
                else;
            }
            map.put(s, photos);
        }
    }
}
Here is the logic which you have to apply 
1. Find all the common dates from the data list 
   for example you data list is : 
   List<Model> dataList = new ArrayList<>();
   dataList.add(new Model("23/10/19"));
   dataList.add(new Model("23/10/19"));
   dataList.add(new Model("23/09/19"));
   dataList.add(new Model("23/10/19"));
   dataList.add(new Model("27/09/19"));
   dataList.add(new Model("23/10/19"));

   List<String> commonList = new ArrayList<>();
   for(Model m : dataList){
       if(!commonList.contains(model.getDate()))
             commonList.add(m.getDate());
       else
           Log.d("Dates", commonList);
   }

   Above function will help in getting all common dates

   //Here map store date with data which has common date
   Map<String, List<Model>> map = new HashMap<>(); 
   List<Model> objectsofCommonDate = new ArrayList();

   for(String date: commonList){
       objectsofCommonDate.clear();
       for(Model model : dataList){
           if(model.getData.contains(date))
               objectsofCommonDate.add(model);
           else
             \\do nothing
       }
       map.put(data, objectsOfCommonDate);
   }


   and pass map to main recyclerview adapter along with commonDateList;
于 2019-11-01T09:54:57.787 回答
1
  1. 首先在你的 setIncomeExpenseList 函数中清除你以前的列表。
  2. 然后重新分配包含来自数据库的完整数据的新列表。
  3. 将 notifyDataSetChanged() 更改为 notify() 或 notifyAll()。

    public void setIncomeExpenseList(List<IncomeExpense> incomeExpenseList) { this.incomeExpenceList.clear(); this.incomeExpenseList = incomeExpenseList; notify(); }

于 2019-11-01T12:55:38.693 回答