I'm about to program an app for controlling some LED-based gadgets around the house. To have multiply devices on one activity I used a page view with a view adapter to be able to select between the linked devices. Currently, I'm stuck with deleting views from the container. As soon as I delete the View, it disappears but leaves a blanc space inside my ViewPager as you can see in the picture below. I tried everything suggested by other users, like returning
POSITION_NONE
when overwriting the
getItemPosition
method. I provide you with the code of my pageViewAdapter. I hope someone can suggest a solution to that problem. I'm very stuck here.
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(){
}
}
I really hope you can help. Thanks.
First edit:
I edited my code as Michiel suggested. I now call a deleteCardItem() method to remove the data from my dataset like shown below.
public void deleteCardItem(int position){
mData.remove(position);
notifyDataSetChanged();
}
With notifyDatasetChanged beeing called, the system takes over and calls getItemPosition(). Ive edited this method as well like Michiel suggested.
@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;
}
}
Problem now is, that i can not compare the given "object" with any dataset, because "object" is a View object and mData is my Arraylist aka dataset. That leads to a starnge behaviour in my app. The card will not disapear anymore. It is shown but the data is deleted. I would appreciate further help.
To fully destroy the view itself you should try to write destroyItem
like this:
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
mViews.set(position, null);
}
So the View object is fully destroyed.
And also try to set the View to null in deleteCardItem
@Override
public void deleteCardItem(int position){
mData.remove(position);
mViews.set(position, null);
notifyDataSetChanged();
}
And also try to search for the View instead of the Data inside of getItemPosition
.
@Override
public int getItemPosition(@NonNull Object object) {
int position = mViews.indexOf(object);
if(position == -1){
return POSITION_NONE;
}else{
return position;
}
}
After that, you don't see them anymore