Java – How to swap images in a GridView (Android)

How to swap images in a GridView (Android)… here is a solution to the problem.

How to swap images in a GridView (Android)

I’m working on a slider puzzle Android app, so I’m using a GridView to display 16 images representing graph blocks. One of the figure blocks will consist of a pure white image representing the background. The idea is that if the user clicks on any tile adjacent to the white tile, the selected tile and the white tile will swap places.

I’m trying to achieve this by setting the white plot block to the graph block of the user’s choice, and vice versa. I saved the location of the white plot block (which starts at position 15) in the variable masterTilePos and referenced the image in my R.drawable file using the ImageAdapter Integer array, set the image at masterValPos as the image at the selected index, and added the selected image to the white plot block. However, when I run the program, the graph block only switches successfully on the first time: after that, it doesn’t work and the order of the graph blocks in the GridView is broken. I think this might be because the array just refers to the actual image object, but I’m not sure how to do that; It’s been three days since I had this issue. Here is my code :

//GRID VIEW

public class MainActivity extends ActionBarActivity { 

int masterTilePos = 15;
GridView gridview;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

gridview = (GridView) findViewById(R.id.gridview);
    gridview.setAdapter(new ImageAdapter(this));

gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {

public void onItemClick(AdapterView<?> parent, View v,
                                int position, long id) {

These methods check if a neighboring tile is white, if there is one,  swap() is called

if(checkUp(position) || checkDown(position) || checkLeft(position) || checkRight(position)) { 

swap(position);

}

}
    });

}

public void swap(int pos) {

ImageAdapter updater = new ImageAdapter(this);

This is where I try to switch the images, and seems to be the source of the problem

int val = updater.mThumbIds[masterTilePos];
    updater.mThumbIds[masterTilePos] = updater.mThumbIds[pos];  
    updater.mThumbIds[pos] = val;

updater.notifyDataSetChanged();
    gridview.setAdapter(updater);
    gridview.invalidateViews();

masterTilePos = pos;

}

}

IMAGE ADAPTER

public class ImageAdapter extends BaseAdapter {

private Context mContext;

public ImageAdapter(Context c) {

mContext = c;

}

public int getCount() {

return mThumbIds.length;
}

public Object getItem(int position) {

return null;
}

public long getItemId(int position) {
    return 0;
}

 create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {

ImageView imageView;

if (convertView == null) {

 if it's not recycled, initialize some attributes

DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();

int width = metrics.widthPixels / 4;
        int height = metrics.heightPixels / 4;

imageView = new ImageView(mContext);

imageView.setLayoutParams(new GridView.LayoutParams(width, height));

imageView.setScaleType(ImageView.ScaleType.FIT_XY);
        imageView.setPadding(1, 1, 1, 1);
    }

else {

imageView = (ImageView) convertView;
    }

imageView.setImageResource(mThumbIds[position]);
    return imageView;
}

 the array containing references to the images

public Integer[] mThumbIds = {

R.drawable.pic1,
        R.drawable.pic2,
        R.drawable.pic3,
        R.drawable.pic4,
        R.drawable.pic5,
        R.drawable.pic6,
        R.drawable.pic7,
        R.drawable.pic8,
        R.drawable.pic9,
        R.drawable.pic10,
        R.drawable.pic11,
        R.drawable.pic12,
        R.drawable.pic13,
        R.drawable.pic14,
        R.drawable.pic15,
        R.drawable.background

};

}

Can anyone help me with this so that I can successfully switch images within the grid? Thank you.

Solution

In onCreate you are doing:

gridview.setAdapter(new ImageAdapter(this));

Therefore, you created an adapter but did not assign it to any variables. This is wrong!

Then, each time you swap you create a new adapter:

ImageAdapter updater = new ImageAdapter(this);

And you set it to the current adapter:

gridview.setAdapter(updater);

This is also wrong.

You have to do this:

  1. OnCreate -> creates the adapter and assigns it to variables (properties) of the object
  2. Then you just need to use that variable.

Then, if you run into problems, debug your logic in the SWAP method.

    //GRID VIEW

public class MainActivity extends ActionBarActivity { 

int masterTilePos = 15;
GridView gridview;
ImageAdapter imageAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

gridview = (GridView) findViewById(R.id.gridview);
    imageAdapter= new ImageAdapter(this);
    gridview.setAdapter(imageAdapter);

gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {

public void onItemClick(AdapterView<?> parent, View v,
                                int position, long id) {

These methods check if a neighboring tile is white, if there is one,  swap() is called

if(checkUp(position) || checkDown(position) || checkLeft(position) || checkRight(position)) { 

swap(position);

}

}
    });

}

public void swap(int pos) {

This is where I try to switch the images, and seems to be the source of the problem

int val = imageAdaptor.mThumbIds[masterTilePos];
    imageAdapter.mThumbIds[masterTilePos] = imageAdapter.mThumbIds[pos];
    imageAdapter.mThumbIds[pos] = val;

imageAdapter.notifyDataSetChanged();
    gridview.invalidateViews();

masterTilePos = pos;
  }
}

IMAGE ADAPTER

public class ImageAdapter extends BaseAdapter {

private Context mContext;

public ImageAdapter(Context c) {
    mContext = c;
}

public int getCount() {
    return mThumbIds.length;
}

public Object getItem(int position) {
    return null;
}

public long getItemId(int position) {
    return 0;
}

 create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {

ImageView imageView;

if (convertView == null) {

 if it's not recycled, initialize some attributes
        DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();

int width = metrics.widthPixels / 4;
        int height = metrics.heightPixels / 4;

imageView = new ImageView(mContext);

imageView.setLayoutParams(new GridView.LayoutParams(width, height));

imageView.setScaleType(ImageView.ScaleType.FIT_XY);
        imageView.setPadding(1, 1, 1, 1);
    }

else {
        imageView = (ImageView) convertView;
    }

imageView.setImageResource(mThumbIds[position]);
    return imageView;
}

 the array containing references to the images

public Integer[] mThumbIds = {
        R.drawable.pic1,
        R.drawable.pic2,
        R.drawable.pic3,
        R.drawable.pic4,
        R.drawable.pic5,
        R.drawable.pic6,
        R.drawable.pic7,
        R.drawable.pic8,
        R.drawable.pic9,
        R.drawable.pic10,
        R.drawable.pic11,
        R.drawable.pic12,
        R.drawable.pic13,
        R.drawable.pic14,
        R.drawable.pic15,
        R.drawable.background
  };
}

Related Problems and Solutions