Android - 从 pageView 中删除对象导致空白 space
Android - removing Object from pageView results in blank space
我正准备编写一个应用程序来控制房子周围的一些基于 LED 的小工具。为了在一个 activity 上拥有多个设备,我使用了带有视图适配器的页面视图,以便能够 select 在链接的设备之间。目前,我坚持从容器中删除视图。一旦我删除视图,它就会消失,但会在我的 ViewPager 中留下空白 space,如下图所示。我尝试了其他用户建议的一切,比如返回
POSITION_NONE
覆盖时
getItemPosition
方法。我为您提供了我的 pageViewAdapter 的代码。我希望有人可以提出解决该问题的方法。我很困在这里。
package com.example.fabsinnenraumgestaltung;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.cardview.widget.CardView;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import java.util.ArrayList;
import java.util.List;
public class CardPagerAdapter extends PagerAdapter implements CardAdapter {
ViewPager viewPager;
MainActivity mainActivity;
private List<CardView> mViews;
private List<CardItem> mData;
private float mBaseElevation;
public CardPagerAdapter(MainActivity mainActivity, ViewPager viewPager) {
mData = new ArrayList<>();
mViews = new ArrayList<>();
this.mainActivity = mainActivity;
this.viewPager = viewPager;
}
public void addCardItem(CardItem item) {
mViews.add(null);
mData.add(item);
}
public float getBaseElevation() {
return mBaseElevation;
}
@Override
public CardView getCardViewAt(int position) {
return mViews.get(position);
}
@Override
public int getCount() {
return mData.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
mData.set(position, null);
mViews.set(position, null);
notifyDataSetChanged();
}
@Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
@Override
public int getItemPosition(@NonNull Object object) {
return super.getItemPosition(object);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Button deleteButton;
Button editButton;
View view = LayoutInflater.from(container.getContext())
.inflate(R.layout.device_card_layout, container, false);
deleteButton = view.findViewById(R.id.deleteButton);
editButton = view.findViewById(R.id.editButton);
deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
System.out.println("delete");
deleteCardOperation(viewPager.getCurrentItem(), container);
}
});
editButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
System.out.println("edit");
int currentCard = viewPager.getCurrentItem();
}
});
container.addView(view);
bind(mData.get(position), view);
CardView cardView = (CardView) view.findViewById(R.id.itemCard);
if (mBaseElevation == 0) {
mBaseElevation = cardView.getCardElevation();
}
cardView.setMaxCardElevation(mBaseElevation * MAX_ELEVATION_FACTOR);
mViews.set(position, cardView);
return view;
}
private void bind(CardItem item, View view) {
TextView titleTextView = (TextView) view.findViewById(R.id.itemText);
TextView ipTextView = (TextView) view.findViewById(R.id.itemIPAdress);
TextView statusView = (TextView) view.findViewById(R.id.itemActiveStatus);
titleTextView.setText(item.getName());
ipTextView.setText(item.getIp());
statusView.setText(item.getStatus());
}
private void deleteCardOperation(int cardIndicator, ViewGroup desV){
CardItem x = mData.get(cardIndicator);
AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity, android.R.style.Theme_Material_Dialog_Alert);
builder.setTitle("Confirm");
builder.setMessage("Are you sure you want to delete this device: "+ x.getName() + " ?");
builder.setPositiveButton("YES", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
destroyItem(desV, cardIndicator, getCardViewAt(cardIndicator));
dialog.dismiss();
}
});
builder.setNegativeButton("NO", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// Do nothing
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.show();
}
private void editCard(){
}
}
我真的希望你能帮上忙。谢谢。
第一次编辑:
我按照 Michiel 的建议编辑了我的代码。我现在调用 deleteCardItem() 方法从我的数据集中删除数据,如下所示。
public void deleteCardItem(int position){
mData.remove(position);
notifyDataSetChanged();
}
调用 notifyDatasetChanged 后,系统接管并调用 getItemPosition()。我按照 Michiel 的建议编辑了这个方法。
@Override
public int getItemPosition(@NonNull Object object) {
//return super.getItemPosition(object);
int position = mData.indexOf(object);
if(position == -1){
return POSITION_NONE;
}else{
return position;
}
}
现在的问题是,我无法将给定的“对象”与任何数据集进行比较,因为“对象”是一个视图对象,而 mData 是我的 Arraylist 又名数据集。这会导致我的应用程序出现异常行为。
卡片不会再消失。它显示但数据被删除。
我将不胜感激。
我主要看到三个问题。首先,您看到空白 space,因为该项目未被删除;相反,它被设置为空。当在 destroyItem()
中调用 mData.set(position, null);
时,结果数组将是 [(CardItem), null, (CardView)]
。这个数组的大小还是3。解决办法:调用mData.remove(position)
.
其次,PagerAdapter
有责任调用所有用@Override
注解的函数。当你调用 notifyDatasetChanged()
时,它会调用 destroyItem()
。您应该更改 mData
,调用 notifyDatasetChanged()
并让 PagerAdapter
完成它的工作。它将删除视图本身并为您调用 destroyItem()
,因此您可以进行额外的清理,例如从 mView
.
中删除视图
第三,如果这只是一次性项目,您可以保留它。但是,如果这是一个长期项目,您可以查看 fi。 SOLID 或其他设计原则。一个例子:你的 PagerAdapter 应该只做一件事和一件事。它应该只将您的数据集 mData 与您的视图连接起来,知道它还处理更新 mData、显示对话框等。再比如:你对MainActivity的引用可以换成Context;该代码仍然有效,但无需任何额外工作即可用于其他活动或片段。
长话短说:
// This is called by the PagerAdapter itself
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
mViews.remove(position);
}
// Call this when the user taps yes
private void deletePage(int position) {
mData.remove(position);
notifyDataSetChanged();
}
要完全破坏视图本身,您应该尝试这样写 destroyItem
:
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
mViews.set(position, null);
}
所以View对象被完全销毁了。
并尝试在 deleteCardItem
中将 View 设置为 null
@Override
public void deleteCardItem(int position){
mData.remove(position);
mViews.set(position, null);
notifyDataSetChanged();
}
并且还尝试在 getItemPosition
中搜索视图而不是数据。
@Override
public int getItemPosition(@NonNull Object object) {
int position = mViews.indexOf(object);
if(position == -1){
return POSITION_NONE;
}else{
return position;
}
}
之后就再也看不到了
我正准备编写一个应用程序来控制房子周围的一些基于 LED 的小工具。为了在一个 activity 上拥有多个设备,我使用了带有视图适配器的页面视图,以便能够 select 在链接的设备之间。目前,我坚持从容器中删除视图。一旦我删除视图,它就会消失,但会在我的 ViewPager 中留下空白 space,如下图所示。我尝试了其他用户建议的一切,比如返回
POSITION_NONE
覆盖时
getItemPosition
方法。我为您提供了我的 pageViewAdapter 的代码。我希望有人可以提出解决该问题的方法。我很困在这里。
package com.example.fabsinnenraumgestaltung;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.cardview.widget.CardView;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import java.util.ArrayList;
import java.util.List;
public class CardPagerAdapter extends PagerAdapter implements CardAdapter {
ViewPager viewPager;
MainActivity mainActivity;
private List<CardView> mViews;
private List<CardItem> mData;
private float mBaseElevation;
public CardPagerAdapter(MainActivity mainActivity, ViewPager viewPager) {
mData = new ArrayList<>();
mViews = new ArrayList<>();
this.mainActivity = mainActivity;
this.viewPager = viewPager;
}
public void addCardItem(CardItem item) {
mViews.add(null);
mData.add(item);
}
public float getBaseElevation() {
return mBaseElevation;
}
@Override
public CardView getCardViewAt(int position) {
return mViews.get(position);
}
@Override
public int getCount() {
return mData.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
mData.set(position, null);
mViews.set(position, null);
notifyDataSetChanged();
}
@Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
@Override
public int getItemPosition(@NonNull Object object) {
return super.getItemPosition(object);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Button deleteButton;
Button editButton;
View view = LayoutInflater.from(container.getContext())
.inflate(R.layout.device_card_layout, container, false);
deleteButton = view.findViewById(R.id.deleteButton);
editButton = view.findViewById(R.id.editButton);
deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
System.out.println("delete");
deleteCardOperation(viewPager.getCurrentItem(), container);
}
});
editButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
System.out.println("edit");
int currentCard = viewPager.getCurrentItem();
}
});
container.addView(view);
bind(mData.get(position), view);
CardView cardView = (CardView) view.findViewById(R.id.itemCard);
if (mBaseElevation == 0) {
mBaseElevation = cardView.getCardElevation();
}
cardView.setMaxCardElevation(mBaseElevation * MAX_ELEVATION_FACTOR);
mViews.set(position, cardView);
return view;
}
private void bind(CardItem item, View view) {
TextView titleTextView = (TextView) view.findViewById(R.id.itemText);
TextView ipTextView = (TextView) view.findViewById(R.id.itemIPAdress);
TextView statusView = (TextView) view.findViewById(R.id.itemActiveStatus);
titleTextView.setText(item.getName());
ipTextView.setText(item.getIp());
statusView.setText(item.getStatus());
}
private void deleteCardOperation(int cardIndicator, ViewGroup desV){
CardItem x = mData.get(cardIndicator);
AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity, android.R.style.Theme_Material_Dialog_Alert);
builder.setTitle("Confirm");
builder.setMessage("Are you sure you want to delete this device: "+ x.getName() + " ?");
builder.setPositiveButton("YES", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
destroyItem(desV, cardIndicator, getCardViewAt(cardIndicator));
dialog.dismiss();
}
});
builder.setNegativeButton("NO", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// Do nothing
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.show();
}
private void editCard(){
}
}
我真的希望你能帮上忙。谢谢。
第一次编辑:
我按照 Michiel 的建议编辑了我的代码。我现在调用 deleteCardItem() 方法从我的数据集中删除数据,如下所示。
public void deleteCardItem(int position){
mData.remove(position);
notifyDataSetChanged();
}
调用 notifyDatasetChanged 后,系统接管并调用 getItemPosition()。我按照 Michiel 的建议编辑了这个方法。
@Override
public int getItemPosition(@NonNull Object object) {
//return super.getItemPosition(object);
int position = mData.indexOf(object);
if(position == -1){
return POSITION_NONE;
}else{
return position;
}
}
现在的问题是,我无法将给定的“对象”与任何数据集进行比较,因为“对象”是一个视图对象,而 mData 是我的 Arraylist 又名数据集。这会导致我的应用程序出现异常行为。 卡片不会再消失。它显示但数据被删除。 我将不胜感激。
我主要看到三个问题。首先,您看到空白 space,因为该项目未被删除;相反,它被设置为空。当在 destroyItem()
中调用 mData.set(position, null);
时,结果数组将是 [(CardItem), null, (CardView)]
。这个数组的大小还是3。解决办法:调用mData.remove(position)
.
其次,PagerAdapter
有责任调用所有用@Override
注解的函数。当你调用 notifyDatasetChanged()
时,它会调用 destroyItem()
。您应该更改 mData
,调用 notifyDatasetChanged()
并让 PagerAdapter
完成它的工作。它将删除视图本身并为您调用 destroyItem()
,因此您可以进行额外的清理,例如从 mView
.
第三,如果这只是一次性项目,您可以保留它。但是,如果这是一个长期项目,您可以查看 fi。 SOLID 或其他设计原则。一个例子:你的 PagerAdapter 应该只做一件事和一件事。它应该只将您的数据集 mData 与您的视图连接起来,知道它还处理更新 mData、显示对话框等。再比如:你对MainActivity的引用可以换成Context;该代码仍然有效,但无需任何额外工作即可用于其他活动或片段。
长话短说:
// This is called by the PagerAdapter itself
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
mViews.remove(position);
}
// Call this when the user taps yes
private void deletePage(int position) {
mData.remove(position);
notifyDataSetChanged();
}
要完全破坏视图本身,您应该尝试这样写 destroyItem
:
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
mViews.set(position, null);
}
所以View对象被完全销毁了。
并尝试在 deleteCardItem
@Override
public void deleteCardItem(int position){
mData.remove(position);
mViews.set(position, null);
notifyDataSetChanged();
}
并且还尝试在 getItemPosition
中搜索视图而不是数据。
@Override
public int getItemPosition(@NonNull Object object) {
int position = mViews.indexOf(object);
if(position == -1){
return POSITION_NONE;
}else{
return position;
}
}
之后就再也看不到了