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;
        }
}

之后就再也看不到了