java - 如何使用过滤的 RecyclerView 和 OnClickListener 从 ArrayList 中删除项目
问题描述
检查下面的更新。
我正在为爬楼梯挑战制作一个应用程序,该应用程序跟踪所采取的日期和步数(用户输入,不是自动的)。我有一个ArrayList
包含以下三个变量的存储对象:
String date
Int steps
Instant timeStamp
该应用程序有两个输入按钮,一个用于整数步长输入,一个用于日期选择。创建了一种简单的方法来按所选日期过滤可见列表,以及您的每日进度与当天楼梯的每日目标的几个视觉指标。
我正在使用 Instant 变量作为时间戳来尝试解决OnClickListener
从过滤列表中选择项目位置而不是在未过滤列表中选择相应项目的问题。为此,我使用 OnClickListener 报告的位置从过滤后的 ArrayList 中的关联项目中获取 timeStamp 变量,然后将该 timeStamp 与未过滤中的项目进行比较,ArrayList
并获取匹配项目的 indexOf。
RecyclerView
当您选择日期时,所有过滤的 ArrayLists 都会正确显示。
问题在于删除项目。如果我只将项目添加到一个日期,那么您可以按照您的预期删除和添加项目。
如果我添加到一个日期,然后另一个日期,当它们正确显示时,这些项目将从正确的位置删除,但在您第一次添加项目的日期,无论这是否是当前选择的日期。
我觉得我在这里遗漏了一些相对简单的东西,我的大脑对这个项目太饱和了,看不到它。
主要活动:
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private ExampleAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
Date temp_curr_date = Calendar.getInstance().getTime();
SimpleDateFormat df = new SimpleDateFormat("dd-MMM-yyyy");
String sel_date = df.format(temp_curr_date);
String curr_date = df.format(temp_curr_date);
double daily_total;
int progress = 0;
double daily_goal = 7.5;
TextView textView1;
TextView textView2;
TextView textViewFlights;
ProgressBar pb;
List<ExampleItem> mExampleList;
List<ExampleItem> filteredList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ----- LOAD SAVED ARRAY LIST -----
loadData();
// ----- SET VARIABLES -----
daily_total = totalOutput(mExampleList, sel_date);
textView1 = findViewById(R.id.total);
textView1.setText(String.valueOf(daily_total));
textViewFlights = findViewById(R.id.flights);
pb = findViewById(R.id.progress_bar);
pb.setProgress(getProgress(mExampleList, sel_date), true);
// ----- BUILD RECYCLERVIEW -----
buildRecyclerView();
filter(sel_date);
// ----- ADD STEPS DIALOGUE -----
setAddStepButton();
// ----- CALENDAR DIALOGUE -----
setDateChangeButton();
}
public double totalOutput(List<ExampleItem> steps, String date) {
try{
int temp_total = 0;
double flight_total;
for (int a = 0; a < steps.size(); a++) {
if (date.equals(steps.get(a).getText1()))
temp_total += steps.get(a).getText2();
}
flight_total = round(temp_total / 16.0, 2);
return flight_total;
} catch (Exception e){
return 0.0;
}
}
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
public static int toInt(double value) {
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(0, RoundingMode.HALF_UP);
return bd.intValue();
}
public static Date getDate(int year, int month, int day) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month);
cal.set(Calendar.DAY_OF_MONTH, day);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
private void saveData(){
SharedPreferences sharedPreferences = getSharedPreferences("shared preferences", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
Gson gson = new Gson();
String json = gson.toJson(mExampleList);
editor.putString("task list", json);
editor.apply();
}
private void loadData(){
SharedPreferences sharedPreferences = getSharedPreferences("shared preferences", MODE_PRIVATE);
Gson gson = new Gson();
String json = sharedPreferences.getString("task list", null);
Type type = new TypeToken<ArrayList<ExampleItem>>() {}.getType();
mExampleList = gson.fromJson(json, type);
if (mExampleList == null){
mExampleList = new ArrayList<>();
}
}
private int getProgress(List<ExampleItem> steps, String date){
int daily_progress_int;
try{
int temp_progress = 0;
double flight_total;
for (int a = 0; a < steps.size(); a++) {
if (date.compareTo(steps.get(a).getText1()) == 0)
temp_progress += steps.get(a).getText2();
}
flight_total = round(temp_progress / 16.0, 2);
daily_progress_int = toInt((flight_total/daily_goal)*100);
return daily_progress_int;
} catch (Exception e){
return 0;
}
}
private void addProgress(double x, int prog){
int daily_progress_int = toInt((x/daily_goal)*100);
if (progress <= 100-daily_progress_int){
progress = progress + prog;
pb = findViewById(R.id.progress_bar);
pb.setProgress(daily_progress_int, true);
} else if (progress + daily_progress_int > 100){
pb = findViewById(R.id.progress_bar);
pb.setProgress(100, true);
}
}
private void removeProgress(double x, int prog){
int daily_progress_int = toInt((x/daily_goal)*100);
progress = progress - prog;
if (progress <= 100) {
pb = findViewById(R.id.progress_bar);
pb.setProgress(daily_progress_int, true);
} else {
pb = findViewById(R.id.progress_bar);
pb.setProgress(0, true);
}
}
public void addItem(String date, int steps, Instant ts){
mExampleList.add(new ExampleItem(date, steps, ts));
filter(sel_date);
}
public void removeItem(final int position){
final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
View viewInflated = LayoutInflater.from(MainActivity.this).inflate(R.layout.confirm, (ViewGroup) findViewById(android.R.id.content), false);
builder.setCancelable(true);
builder.setView(viewInflated);
builder.setPositiveButton("Yup",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mExampleList.remove(position);
mAdapter.notifyDataSetChanged(position);
filter(sel_date);
daily_total = totalOutput(mExampleList, sel_date);
textView1 = findViewById(R.id.total);
textView1.setText(String.valueOf(daily_total));
removeProgress(daily_total,progress);
if (daily_total == 1.0){
textViewFlights.setText("flight");
} else {
textViewFlights.setText("flights");
}
saveData();
}
});
builder.setNegativeButton("Nope", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
public void buildRecyclerView(){
mRecyclerView = findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mAdapter = new ExampleAdapter(mExampleList);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(new ExampleAdapter.OnItemClickListener() {
@Override
public void onItemClick(int position) {
Instant test = filteredList.get(position).getTimeStamp();
for (ExampleItem item : mExampleList){
if (test.compareTo(item.getTimeStamp()) == 0){
removeItem(mExampleList.indexOf(item));
}
});
}
public void filter(String text){
filteredList = new ArrayList<>();
for (ExampleItem item : mExampleList){
if (item.getText1().toLowerCase().contains(text.toLowerCase())){
filteredList.add(item);
}
}
mAdapter.filterList(filteredList);
}
public void setAddStepButton(){
FloatingActionButton fab = findViewById(R.id.addSteps);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
View viewInflated = LayoutInflater.from(MainActivity.this).inflate(R.layout.add_steps, (ViewGroup) findViewById(android.R.id.content), false);
// Step input
final EditText input = viewInflated.findViewById(R.id.input);
builder.setView(viewInflated);
// OK Button
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (input.getText().length() != 0) {
try {
int in = Integer.parseInt(String.valueOf(input.getText()));
if (in > 0) {
Instant timeStamp = Instant.now();
addItem(sel_date, in, timeStamp);
dialog.dismiss();
} else {
dialog.cancel();
}
} catch (Exception e) {
dialog.cancel();
}
daily_total = totalOutput(mExampleList, sel_date);
textView1 = findViewById(R.id.total);
textView1.setText(String.valueOf(daily_total));
addProgress(daily_total, progress);
mAdapter.notifyDataSetChanged();
filter(sel_date);
if (daily_total == 1.0){
textViewFlights.setText("flight");
} else {
textViewFlights.setText("flights");
}
saveData();
} else{
dialog.cancel();
}
}
});
// Cancel Button
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.show();
}
});
}
public void setDateChangeButton(){
FloatingActionButton fabcal = findViewById(R.id.calendarButton);
fabcal.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
LayoutInflater inflater = (LayoutInflater)getApplicationContext().getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout ll= (LinearLayout)inflater.inflate(R.layout.calendar, null, false);
CalendarView cv = (CalendarView) ll.getChildAt(0);
long milliseconds = 0;
try {
Date d = df.parse(sel_date);
milliseconds = d.getTime();
} catch (ParseException e) {
e.printStackTrace();
}
cv.setDate(milliseconds);
cv.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
@Override
public void onSelectedDayChange(
@NonNull CalendarView view,
int year,
int month,
int dayOfMonth)
{
Date temp_sel_date = getDate(year, month, dayOfMonth);
sel_date = df.format(temp_sel_date);
textView2 = findViewById(R.id.daily_total);
if (sel_date.equals(curr_date)){
textView2.setText("Today");
} else {
String dt_day = (String) DateFormat.format("dd", temp_sel_date);
String dt_month = (String) DateFormat.format("MMM", temp_sel_date);
textView2.setText(dt_month + " " + dt_day);
}
daily_total = totalOutput(mExampleList, sel_date);
textView1 = findViewById(R.id.total);
textView1.setText(String.valueOf(daily_total));
pb = findViewById(R.id.progress_bar);
pb.setProgress(getProgress(mExampleList, sel_date), true);
mAdapter.notifyDataSetChanged();
filter(sel_date);
}
});
new AlertDialog.Builder(MainActivity.this)
.setView(ll)
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
}
}
).show();
}
});
}
}
适配器类:
public class ExampleAdapter extends RecyclerView.Adapter<ExampleAdapter.ExampleViewHolder> {
private static List<ExampleItem> mExampleList;
private static List<ExampleItem> exampleListFull;
private OnItemClickListener mListener;
public interface OnItemClickListener{
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener){
mListener = listener;
}
public static class ExampleViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView1;
public ImageView mDeleteImage;
public ExampleViewHolder(View itemView, final OnItemClickListener listener) {
super(itemView);
mTextView1 = itemView.findViewById(R.id.textView);
mDeleteImage = itemView.findViewById(R.id.image_delete);
mDeleteImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (listener != null){
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION){
Instant test = mExampleList.get(position).getTimeStamp();
for (ExampleItem item : exampleListFull){
int compare = test.compareTo(item.getTimeStamp());
if (compare == 0){
int delIndex = exampleListFull.indexOf(item);
position = delIndex;
}
}
listener.onItemClick(position);
}
}
}
});
}
}
public ExampleAdapter(List<ExampleItem> exampleList){
this.mExampleList = exampleList;
exampleListFull = new ArrayList<>(exampleList);
}
@NonNull
@Override
public ExampleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.example_item, parent, false);
ExampleViewHolder evh = new ExampleViewHolder(v, mListener);
return evh;
}
@Override
public void onBindViewHolder(@NonNull ExampleViewHolder holder, int position) {
ExampleItem currentItem = mExampleList.get(position);
if (currentItem.getText2() == 1.0){
holder.mTextView1.setText(currentItem.getText2() + " step");
} else {
holder.mTextView1.setText(currentItem.getText2() + " steps");
}
}
@Override
public int getItemCount() {
return mExampleList.size();
}
public void filterList(List<ExampleItem> filteredList){
mExampleList = filteredList;
notifyDataSetChanged();
}
}
如果有人有任何想法,我很乐意听取您的意见!
更新:包含的代码现在反映了用户建议的更改并且功能齐全。
解决方案
也许将 onClickListner 放在您的 adpater-class 中可能会更好。所以您可以控制每张卡片是否应该可点击...或者如果您想在卡片之间放置任何广告
GGK
推荐阅读
- splash-screen - 用户获取 - 谷歌广告结果与实际用户获取不匹配
- android - 自定义AlertDialog如何访问android.R.id.custom
- mysql - 使用 SYSTEM 时如何使用 MySQL Docker 修复日志中的时间戳,忽略夏令时?
- javascript - 使用 JS 计算相关连续概率 n 次
- http - Golang HTTP Timeout 测试,没有按预期超时
- html - 在网格中对齐图像
- python - PIL 如何打开 sRGB 图像?
- node.js - node.js- 在 Sequelize 中获取先前的数据值
- java - 如果数组中有重复的数字,该程序似乎不起作用
- reentrantlock - 可重入锁是否使函数可重入?