swap items in a Gridview trouble with the dropped position in Android - android

i have been trying to swap items in a Grid view, and this is where i got:
xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/parent_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<GridView
android:id="#+id/grid_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:horizontalSpacing="10dip"
android:numColumns="4"
android:verticalSpacing="10dip" />
</RelativeLayout>
main activity class:
public class MainActivity extends Activity implements OnDragListener,
OnItemLongClickListener {
ArrayList drawables;
GridView gridView;
private BaseAdapter adapter;
private int draggedIndex = -1;
private int droppedIndex = -1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
drawables = new ArrayList();
drawables.add(R.drawable.ic_launcher);
drawables.add(R.drawable.ic_launcher1);
drawables.add(R.drawable.ic_launcher2);
drawables.add(R.drawable.ic_launcher);
drawables.add(R.drawable.ic_launcher);
drawables.add(R.drawable.ic_launcher);
drawables.add(R.drawable.ic_launcher);
drawables.add(R.drawable.ic_launcher);
gridView = (GridView) findViewById(R.id.grid_view);
gridView.setOnItemLongClickListener(MainActivity.this);
gridView.setAdapter(adapter = new BaseAdapter() {
#Override
// Get a View that displays the data at the specified position in
// the data set.
public View getView(int position, View convertView,
ViewGroup gridView) {
// try to reuse the views.
ImageView view = (ImageView) convertView;
// if convert view is null then create a new instance else reuse
// it
if (view == null) {
view = new ImageView(MainActivity.this);
}
view.setImageResource((Integer) drawables.get(position));
view.setTag(String.valueOf(position));
return view;
}
#Override
// Get the row id associated with the specified position in the
// list.
public long getItemId(int position) {
return position;
}
#Override
// Get the data item associated with the specified position in the
// data set.
public Object getItem(int position) {
return drawables.get(position);
}
#Override
// How many items are in the data set represented by this Adapter.
public int getCount() {
return drawables.size();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onDrag(View view, DragEvent dragEvent) {
switch (dragEvent.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
// Ignore this event
return true;
case DragEvent.ACTION_DRAG_ENTERED:
// Ignore this event
return true;
case DragEvent.ACTION_DRAG_EXITED:
// Ignore this event
return true;
case DragEvent.ACTION_DRAG_LOCATION:
// Ignore this event
return true;
case DragEvent.ACTION_DROP:
// Dropped inside a new view\
adapter.notifyDataSetChanged();
ImageView v2 = (ImageView)view.getParent();
final int position1 = gridView.getPositionForView(v2);
if (position1 >= 0)
{
final long droppedIndex = gridView.getAdapter().getItemId(position1);
}
Object item1 = gridView.getAdapter().getItem(draggedIndex);
Object item2 = gridView.getAdapter().getItem(droppedIndex);
drawables.remove(draggedIndex);
drawables.remove(droppedIndex);
drawables.add(droppedIndex,item1);
drawables.add(draggedIndex,item2);
draggedIndex = -1;
droppedIndex = -1;
adapter.notifyDataSetChanged();
case DragEvent.ACTION_DRAG_ENDED:
//
view.setOnDragListener(null);
return true;
}
return false;
}
#Override
public boolean onItemLongClick(AdapterView gridView, View view,
int position, long row) {
ClipData.Item item = new ClipData.Item((String) view.getTag());
ClipData clipData = new ClipData((CharSequence) view.getTag(),
new String[] { ClipDescription.MIMETYPE_TEXT_PLAIN }, item);
view.startDrag(clipData, new View.DragShadowBuilder(view), null, 0);
view.setVisibility(View.INVISIBLE);
draggedIndex = position;
return true;
}
}
my problem is in DragEvent.ACTION_DROP. I works like this:
I drag one item and, when drop it in another place, the item disappears. And that is all.
Supposedly, first retrieve both positions: the position of the item dragged (draggedIndex) and the position where the item is dropped (droppedIndex). After, i remove both items and add them to the array again in the opposite positions (the item dragged goes to droppedIndex and the other goes to the draggedIndex, so they are exchanged/swaped)
I wonder if it is a good way to do this, or if i made any mistakes trying to retrieve the dropped position (droppedIndex).
any ideas?

Before removing the item , just add the item into dropped position. Then remove the corresponding item by incrementing the dropped position by 1.
case DragEvent.ACTION_DROP:
....
drawables.add(droppedIndex,item1);
drawables.add(draggedIndex+1,item2);
drawables.remove(draggedIndex+2);
drawables.remove(droppedIndex+2);
....
hope this will help you.

I took a slightly different approach to get the dropped index. For an ACTION_DROP event, getX() and getY() return the X and Y position of the drag point at the moment of the drop, using the coordinate system of the View that received the drop (i.e. the gridview).
float dropX = event.getX();
float dropY = event.getY();
Once you have the x and y co-ordinates you can calculate the corresponding row and column in your grid view, and then use something like the following to get the index of the object in your data array (I have a 4 x 4 grid):
index = row * 4 + column;
Finally, I'm using an array list (targetDrawables) to hold the references to my gridview contents, so to reorder use:
targetDrawables.remove(draggedIndex);
targetDrawables.add(droppedIndex, draggedContents);
// Invalidate the view to force a redraw of the Grid View
imageAdapter.notifyDataSetChanged();

Your code is fine; just replace
Object item1 = gridView.getAdapter().getItem(draggedIndex);
Object item2 = gridView.getAdapter().getItem(droppedIndex);
drawables.remove(draggedIndex);
drawables.remove(droppedIndex);
drawables.add(droppedIndex,item1);
drawables.add(draggedIndex,item2);
with
Collections.swap(drawables, draggedIndex, droppedIndex);
It swaps position of list and now it works!

Related

custom listview adapter selected item increment textview

I used https://github.com/wdullaer/SwipeActionAdapter to swipe each items on listview
once i swipe one of the item, textview text will increment to one. The problem if i will scroll the list, the textview will return to each default value which is 0 and some hidden items also incrementing.
Code for onswipe event:
switch (direction) {
case SwipeDirections.DIRECTION_FAR_LEFT:
selectedText = (TextView) getViewByPosition(position, getListView()).findViewById(R.id.txtNumber);
selectedText.setText(String.valueOf(Integer.parseInt(selectedText.getText().toString()) + 1));
break;
and adapter code:
JSONArray jsonArray = null;
try {
jsonArray = new JSONArray(data);
} catch (JSONException e) {
e.printStackTrace();
}
String[] strArr = new String[jsonArray.length()];
ArrayList<String> arrayList = new ArrayList<String>();
for (int i = 0; i < jsonArray.length(); i++) {
try {
strArr[i] = jsonArray.getJSONObject(i).getString("name");
arrayList.add(jsonArray.getString(i));
stringAdapter = new ArrayAdapter<String>(
this,
R.layout.items,
R.id.txtName,
new ArrayList<String>(Arrays.asList(strArr))
);
setListAdapter(stringAdapter);
stringAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
items.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="100sp"
android:background="#drawable/listview_style"
android:padding="8dp"
android:descendantFocusability="blocksDescendants">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imageView"
android:src="#mipmap/ic_launcher"
android:layout_centerVertical="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Text"
android:id="#+id/txtName"
android:textSize="20sp"
android:gravity="center"
android:ellipsize="none"
android:singleLine="false"
android:scrollHorizontally="false"
android:layout_centerVertical="true"
android:layout_marginLeft="20sp"
android:layout_marginRight="20sp"
android:layout_toRightOf="#+id/imageView"
android:layout_toLeftOf="#+id/txtNumber"
android:layout_toStartOf="#+id/txtNumber"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:id="#+id/txtNumber"
android:textSize="25sp"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginRight="40dp"
android:layout_marginEnd="40dp"
/>
</RelativeLayout>
i'm thinking of item position is not valid or view is not valid.
anyidea how to solve this. thanks
UPDATE
Incrementing now working properly, but item name is not populating. See attached
The problem is that listview cheats. It's a recycling view so what happens is that you actually just have the same like 10 views you are currently seeing. When you scroll far enough that the view goes away, it appears again as the view that just came into view. To do this, it got rid of the old view, asked the adapter to make this trashed view into something that will look like the new view (which is awesome for memory and quick view creation).
This is why your items go away, because the views are recycled by the listview using the adapter after you scroll away. If you really want to see this, try making swipe turn the visibility of your view to INVISIBLE, then you'll notice views all over the place just being missing. Because they are the same view.
In short, swipe must change the data used to build the view. Any changes to the view itself will either be wiped away, or mess up the other views (things like visibility and .transform() are not often reset by adapters), which are really just the same view again.
public class SwipeActivity extends AppCompatActivity {
SwipeActionAdapter mAdapter;
private class YourCustomRowEntry {
String displayString;
int swipes;
public YourCustomRowEntry( String displayString, int swipes) {
this.swipes = swipes;
this.displayString = displayString;
}
}
private class Holder {
public TextView textName, textNumber;
public ImageView imageView;
public Holder(TextView textName, TextView textNumber, ImageView imageView) {
this.textName = textName;
this.textNumber = textNumber;
this.imageView = imageView;
}
}
ArrayList<YourCustomRowEntry> mDataYouEditThatBacksTheAdapter = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_swipe);
for (int i = 1; i <= 200; i++) {
mDataYouEditThatBacksTheAdapter.add(new YourCustomRowEntry("Row " + i,0));
}
BaseAdapter customAdapter = new BaseAdapter() {
#Override
public int getCount() {
return mDataYouEditThatBacksTheAdapter.size();
}
#Override
public Object getItem(int position) {
return mDataYouEditThatBacksTheAdapter.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View itemView;
Holder viewHolder;
if (convertView != null) {
itemView = convertView; //if you already made this view, and it's being recycled use that.
viewHolder = (Holder)convertView.getTag(); //And fetch the already findByViews things.
}
else {
//if this is the first time, inflate the view.
itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.items, parent, false);
TextView textName = (TextView)itemView.findViewById(R.id.txtName);
TextView textNumber = (TextView)itemView.findViewById(R.id.txtNumber);
ImageView imageView = (ImageView)itemView.findViewById(R.id.imageView);
viewHolder = new Holder(textName,textNumber,imageView);
itemView.setTag(viewHolder); //store the data in the view's tag.
}
YourCustomRowEntry ycre = mDataYouEditThatBacksTheAdapter.get(position);
viewHolder.textName.setText(ycre.displayString);
viewHolder.textNumber.setText("" + ycre.swipes); // Gotta tell it that this is a string and not a resource.
//You would also set the imageView from the saved set of data here too.
return itemView;
}
};
ListView listView = (ListView)findViewById(R.id.myActivitysListView);
// Wrap your content in a SwipeActionAdapter
mAdapter = new SwipeActionAdapter(customAdapter);
// Pass a reference of your ListView to the SwipeActionAdapter
mAdapter.setListView(listView);
// Set the SwipeActionAdapter as the Adapter for your ListView
listView.setAdapter(mAdapter);
// Listen to swipes
mAdapter.setSwipeActionListener(new SwipeActionAdapter.SwipeActionListener() {
#Override
public boolean hasActions(int position) {
// All items can be swiped
return true;
}
#Override
public boolean shouldDismiss(int position, int direction) {
// Only dismiss an item when swiping normal left
return false;
//return direction == SwipeDirections.DIRECTION_NORMAL_LEFT;
}
#Override
public void onSwipe(int[] positionList, int[] directionList) {
for (int i = 0; i < positionList.length; i++) {
int direction = directionList[i];
int position = positionList[i];
switch (direction) {
case SwipeDirections.DIRECTION_FAR_LEFT:
mDataYouEditThatBacksTheAdapter.get(position).swipes++; //add 1 to swipes;
mAdapter.notifyDataSetChanged();
break;
case SwipeDirections.DIRECTION_FAR_RIGHT:
mDataYouEditThatBacksTheAdapter.get(position).swipes--; //subtract 1 to swipes;
mAdapter.notifyDataSetChanged();
break;
}
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_swipe, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Video of it working:
https://youtu.be/6wPF2OOKu2U
Save the array you use to back your listview. You need to have that so you can change it and get the Adapter to build new views. notifyDataSetChanged() and it updates the and rebuilds the views, from the original data structure it saved. Meaning you need to modify that data, not the view. This properly writes a class and uses that to build the views.

GridView, Get Item's parent View

I'm trying to send clicks to my child elements in GridView with a single touch event. So far, I can retrieve the data of the child element, but cannot perform a click on it.
Let me explain a bit more on the layout of things...
GridView - Touch Event Handler here...
LinearLayout - onClick listeners here...
TextView - Just some text...
An adapter fills GridView with LinearLayout's who have onClick events defined. These layouts contain TextViews where TextView.setText("Some data from my dataset")
I have an onTouch listener which is currently listening to touch events on the GridView, and is successfully finding the data of TextView depending on the position of the finger.
How do I get the TextView's parent view, and call performClick at the user's finger position?
This is the current click handler, containing what I've got so far...
Assume GridView & Adapter are initialised properly...
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = MotionEventCompat.getActionMasked(event);
switch(action)
{
case (MotionEvent.ACTION_DOWN) :
case (MotionEvent.ACTION_MOVE) :
int position = GridView.pointToPosition((int)event.getX(),(int)event.getY());
if (position != -1)
{
// I have looked at the other .get methods, and doing GridView.getXYZ (Where XYZ could be any method) and couldn't get anywhere...
String item = Adapter.getItem(position);
Log.d("TouchEvent","Action was DOWN/MOVE on " + item);
return true;
}
case (MotionEvent.ACTION_UP) :
Log.d("TouchEvent","Action was UP");
return true;
case (MotionEvent.ACTION_CANCEL) :
Log.d("TouchEvent","Action was CANCEL");
return true;
case (MotionEvent.ACTION_OUTSIDE) :
Log.d("TouchEvent","Movement occurred outside bounds " +
"of current screen element");
return true;
default :
return true;
}
}
});
Thanks!
Also thought to mention, this GridView is contained within a fragment. I doubt it would change the world, but might affect the solutions you guys have.
Aaahh.. Something we need to try,
Implement method like,
private View getViewByPosition(GridView gridView, int position) {
int firstPosition = gridView.getFirstVisiblePosition();
int lastPosition = gridView.getLastVisiblePosition();
if ((position < firstPosition) || (position > lastPosition))
return null;
return gridView.getChildAt(position - firstPosition);
}
Now, call this method,
if (position != -1)
{
// I have looked at the other .get methods, and doing GridView.getXYZ (Where XYZ could be any method) and couldn't get anywhere...
GridView gridView = (GridView) v;
View touchedView = getViewByPosition(gridView, position);
String item = Adapter.getItem(position);
Log.d("TouchEvent","Action was DOWN/MOVE on " + item);
return true;
}
Try this
gridview.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView parent, View v,
int position, long id)
{ // Send intent to SingleViewActivity Intent i = new Intent(getApplicationContext(), SingleViewActivity.class); // Pass image index
i.putExtra("id", position);
startActivity(i);
}
});
After this create SingleViewActivity.java class
public class SingleViewActivity extends Activity { #Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.single_view);
// Get intent data Intent i = getIntent();
// Selected image id
int position = i.getExtras().getInt("id"); ImageAdapter imageAdapter = new ImageAdapter(this);
ImageView imageView = (ImageView) findViewById(R.id.SingleView); imageView.setImageResource(imageAdapter.mThumbIds[position]); }
}

Android banner ads not displaying in Listview as expected

I'm attempting to create a listview which has banner ads at every nth interval. In my code, it's every 6 items. I've based my code on the example here. The example provided is based on having a banner ad at the first and last of the listview, so I've encountered problems when trying to intersperse the banner ads within the listview at equal intervals. Specifically, my ads don't display every 6th time. The result I have from the code below is displaying two consecutive ads at positions 7,8 and then my third at position 13. I'm not sure what could be causing the ad at position 8 to appear.
Any idea how I can fix this?
Code below...
Firstly, the creation of my SimpleCursorAdapter, which contains about 14 strings to display in the listview in this case.
// Create and populate listview
final ListView listview = (ListView) findViewById(android.R.id.list);
// SimpleCursorAdapter method
Cursor c = dbh.getAllCategoriesCursor();
startManagingCursor(c);
String[] from = new String[] { "name" };
int[] to = new int[] { R.id.category_label};
// Now create an array adapter and set it to display using our row
SimpleCursorAdapter cursorAdapter =
new SimpleCursorAdapter(this, R.layout.rowlayout, c, from, to, 0);
setListAdapter(new ListViewAdapter(this, cursorAdapter));
And here is my ListViewAdapter, extending the BaseAdapter class
public class ListViewAdapter extends BaseAdapter {
private Activity mContext;
private SimpleCursorAdapter listAdapter;
private LayoutInflater mLayoutInflater;
private int k = 6; // interval ad every 6 items
int baseItems;
int noAds; // used for listview offset
// Constructor takes in a BaseAdapter
public ListViewAdapter(Activity activity, SimpleCursorAdapter delegate) {
mContext = activity;
listAdapter = delegate;
baseItems = listAdapter.getCount();
noAds = baseItems / k;
mLayoutInflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
// Total count includes list items and ads.
return baseItems + noAds;
}
#Override
public Object getItem(int position) {
// Return null if an item is an ad. Otherwise return the delegate item.
if (isItemAnAd(position)) {
return null;
}
return listAdapter.getItem(getOffsetPosition(position));
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getViewTypeCount() {
return listAdapter.getViewTypeCount() + noAds;
}
#Override
public int getItemViewType(int position) {
if (isItemAnAd(position)) {
return listAdapter.getViewTypeCount();
} else {
return listAdapter.getItemViewType(getOffsetPosition(position));
}
}
#Override
public boolean areAllItemsEnabled() {
return false;
}
#Override
public boolean isEnabled(int position) {
return (!isItemAnAd(position)) && listAdapter.isEnabled(getOffsetPosition(position));
}
private boolean isItemAnAd(int position) {
// Place an ad at the first and last list view positions.
// -- should override for every kth positions
if (position == 0) return false;
// Calculate offsets caused by ads already embedded
int offset = 0;
if (position > k){
int div = position / k;
offset = div;
}
return ((position-offset) % k == 0);
}
// Get the position that is offset by the insertion of the ads
private int getOffsetPosition(int position) {
return position - noAds;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Display every n list items
if (isItemAnAd(position)) {
if (convertView instanceof AdView) {
// Don’t instantiate new AdView, reuse old one
return convertView;
} else {
// Create a new AdView
AdView adView = new AdView(getApplicationContext());
adView.setAdSize(AdSize.BANNER);
adView.setAdUnitId(BANNER_AD_ID);
// Disable focus for sub-views of the AdView to avoid problems with
// trackpad navigation of the list.
for (int i = 0; i < adView.getChildCount(); i++)
{
adView.getChildAt(i).setFocusable(false);
}
adView.setFocusable(false);
// Convert the default layout parameters so that they play nice with
// ListView.
float density = getApplicationContext().getResources().getDisplayMetrics().density;
int height = Math.round(AdSize.BANNER.getHeight() * density);
AbsListView.LayoutParams params = new AbsListView.LayoutParams(
AbsListView.LayoutParams.MATCH_PARENT,
height);
adView.setLayoutParams(params);
AdRequest bannerIntermediateReq = new AdRequest.Builder()
.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
.addTestDevice("d9e108ab") //means that a test ad is shown on my phone
.build();
adView.loadAd(bannerIntermediateReq);
return adView;
}
} else {
// Offload displaying other items to the delegate
return listAdapter.getView(position - (int) Math.ceil(position / k),
convertView, parent);
}
}
}
Update 9/6... Found a workaround of sorts that creates an ad at the nth interval, followed by all following ads at n-1 intervals. So if I set n=8 I'll get an ad inserted after 8 list items, after ads inserted every 7 items after that. I'm quite happy to settle for this given the amount of time I've sunk into it. It's probably an off-by-one bug somewhere that I cannot find whatsoever. Hope this helps someone at some point. Here's the modifications:
private boolean isItemAnAd(int position) {
if (position < k) return false;
// Calculate current offset caused by ads already embedded
if (position==k){
return true;
}
else {
return isItemAnAd(position-k);
}
}
and
// Get the position that is offset by the insertion of the ads
private int getOffsetPosition(int position) {
int currentNoAds = position / k;
return position - currentNoAds;
}
and, in getView...
return listAdapter.getView(getOffsetPosition(position) ,
convertView, parent);

Scroll View relative to parent View

Hi Guys My question is very simple
I want to add images in a row like a flowlayout or GridLayout as you can see in the Image below
Above that layout i want to add a button such that it comes in between rows.
When i scroll my grid View , the button Image also scrolls respective with the gridview.
Can any one suggest me some ideas how it can be possible
If it's always a fourth item - than must be no problem.
Impelment a GridView with android:numColumns="3"
In your Adapter implement three view types
The idea is to add two blank items in a second row and a button to the middle.
private static final int TYPE_NORMAL = 0;
private static final int TYPE_BLANK = 1;
private static final int TYPE_BUTTON = 2;
#Override
public int getViewTypeCount() {
return 3;
}
#Override
public int getCount() {
return yourdata.size() + 3;
}
// return your real data by skipping row with the button
#Override
public Object getItem(int position) {
if (position > 3) {
position += 3;
}
return yourdata.get(position);
}
// return your real data ID by skipping row with the button The button probably should catch it's own onClickListemer
#Override
public long getItemId(int position) {
if (position > 3) {
position += 3;
}
return yourdata.get(position).getId();
}
#Override
public int getItemViewType(int position) {
switch(position) {
case 4:
case 6:
return TYPE_BLANK;
case 5:
return TYPE_BUTTON;
default:
return TYPE_NORMAL;
}
}
// only your items should be clickable
#Override
public boolean isEnabled(int position) {
return position < 4 && position > 6;
}
// nope, only your specific data items are enabled.
#Override
public boolean areAllItemsEnabled() {
return false;
}
In yout getView method just check the item view type and inflate the proper view.
For more details implementing adapters with multiple item types refer to example of ListView with section headers etc.
How to generate a ListView with headers above some sections?
http://w2davids.wordpress.com/android-sectioned-headers-in-listviews/

Gallery- viewing more than one picture

I have a working Gallery that shows one picture at a time and can be "swiped" to rotate through the images. I want to have the option of the user to view 2 or 3 pictures at a time by using the menu and selecting how many to show. So far Ive tried adjusting the Gallery width, and LinearLayout params and all crash the Activity. any advice would be appreciated.
I declare and initialize the Gallery here and have the onOptionsItemSelected method sekeleton.
public class SpeechAppActivity extends Activity implements OnClickListener{
//Menu Items
// Class variables
Gallery myGallery;
ImageView imageView;
MyDBAdapter db;
Item item1;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
db = new MyDBAdapter(this);
db.insertEntry(item1 = new Item("Bathtub", "Bathroom", "Typical", "Clean", "fill, wash", "Round, deep", "Bathroom", "Toilet, Bathroom", R.drawable.ic_launcher));
Log.i("item", "item: " + item1.toString());
// Bind the gallery defined in the main.xml
// Apply a new (customized) ImageAdapter to it.
myGallery = (Gallery) findViewById(R.id.myGallery);
myGallery.setAdapter(new ImageAdapter(this));
//myGallery.setLayoutParams(new Gallery.LayoutParams(250, 250));
myGallery.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View v,
int position, long id) {
}
public void onNothingSelected(AdapterView<?> parent) {
}
});
public boolean onOptionsItemSelected(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.settings:
startActivity(new Intent(this, Prefs.class));
return true;
case R.id.show1:
//myGallery.findViewById(R.id.myGallery).setLayoutParams(new Gallery.LayoutParams(500, 250));
return true;
case R.id.show2:
//myGallery.findViewById(R.id.myGallery).setLayoutParams(new Gallery.LayoutParams(500, 250));
return true;
case R.id.show3:
//myGallery.findViewById(R.id.myGallery).setLayoutParams(new Gallery.LayoutParams(500, 250));
return true;
}
return false;
}
This is the Image Adapter class for the Gallery
public class ImageAdapter extends BaseAdapter {
/** The parent context */
private Context myContext;
// Put some images to project-folder: /res/drawable/
// format: jpg, gif, png, bmp, ...
private int[] myImageIds = { R.drawable.apple, R.drawable.orange,
R.drawable.ic_launcher };
/** Simple Constructor saving the 'parent' context. */
public ImageAdapter(Context c) {
this.myContext = c;
}
// inherited abstract methods - must be implemented
// Returns count of images, and individual IDs
public int getCount() {
return this.myImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
// Returns a new ImageView to be displayed,
public View getView(int position, View convertView,
ViewGroup parent) {
// Get a View to display image data
ImageView iv = new ImageView(this.myContext);
iv.setImageResource(this.myImageIds[position]);
// Image should be scaled somehow
//iv.setScaleType(ImageView.ScaleType.CENTER);
iv.setScaleType(ImageView.ScaleType.CENTER_CROP);
//iv.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
//iv.setScaleType(ImageView.ScaleType.FIT_CENTER);
//iv.setScaleType(ImageView.ScaleType.FIT_XY);
//iv.setScaleType(ImageView.ScaleType.FIT_END);
//iv.setScaleType(ImageView.ScaleType.FIT_START);
// Set the Width & Height of the individual images
//get scale for finding dip of a set # of pixels
final float scale = parent.getContext().getResources().getDisplayMetrics().density;
iv.setLayoutParams(new Gallery.LayoutParams((int) (300 * scale + 0.5f), (int) (250 * scale + 0.5f)));
return iv;
}
}// ImageAdapter
In your adapter,
Use View object (witn custom view) and put ImageView inside it.
This was you can put more than one images per view.
Best results can be achieved by few layout files based on number of images and using correct one according to user selection.
Let me know if you need more specific code template.

Categories

Resources