How to order elements in Grid View - android

I have a Grid View adapter where all is in this code:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View v = convertView;
CheckBox check = null;
ImageView pic = null;
if (convertView == null) { // if it's not recycled, initialize some
// attributes
LayoutInflater vi = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.check_box_and_imageview, null);
}
pic = (ImageView)v.findViewById(R.id.imageView);
check = (CheckBox) v.findViewById(R.id.checkBox);
check.setTag(position);
ImageLoader loader = new ImageLoader(mContext);
//this loads image from given url
loader.DisplayImage(url[position], pic);
return v;
}
Here i create a view with check box and image view. There is the problem because image view is different size and gridview make aligment by both size checkbox and image view. But i want to order element by check box.
For better explanation what i want to do will show this pic:
This i want to do. How ever my image views isn't all same size. Now i will illustrate how it looks:
So this don't suite me. I want to make alignment not all checkbox and imageview. But just that check boxes would be under checks boxes.
So isn't this possible to do with gird view ?

Check if the convertView is null:
If it is null it's time to inflate a new View for this GridView's element. You could also use the holder pattern to cache looking for the composing Views(instead of searching with findViewById everytime)(You use the setTag element for the inflated View but it's a piece of data from the Node data element ?!? What do you plan to do with it?!?)

Related

Android ListView actions repeat in different items

I have a custom layout for a Listview, each row item contains a button that when clicked it shows a small imageview in the item, however the actions i perform in one item, repeats for another item down the list, for example, if i click the button in item 1, the imageview will show up in item 1 and item 10, if i click the button in item 2, the Imageview will show up on item 2 and item 11 and while i scroll it will keep repeating in different items, heres the code for my custom adapter:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
mparent = parent;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.places_item, parent, false);
holder = new ViewHolder();
holder.placeimage = (CircularImageView) convertView.findViewById(R.id.locationimage_pilayout);
holder.addbtn = (TextView) convertView.findViewById(R.id.addbtn_pilayout);
holder.delbtn = (TextView) convertView.findViewById(R.id.delbtn_pilayout);
holder.oribtn = (TextView) convertView.findViewById(R.id.oribtn_pilayout);
holder.placename = (TextView) convertView.findViewById(R.id.locationname_pilayout);
holder.selected = (ImageView) convertView.findViewById(R.id.selected_pilayout);
holder.origin = (ImageView) convertView.findViewById(R.id.origin_pilayout);
holder.swipeLayout = (SwipeRevealLayout) convertView.findViewById(R.id.swipe_pilayout);
holder.mainLayout = (LinearLayout) convertView.findViewById(R.id.main_pilayout);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final Place item = getItem(position);
/*
my code assigning the button click listener and assigning the views
*/
return convertView;
}
Am i missing something? im sure this could be a simple fix, but i havent found it yet. any help would be kindly appreciated.
In ListView the individual views for rows, get reused. For example, let's say the window can show up to 10 rows inside the ListView. Now when you scroll down, the 1st view gets out of the window from the top, and a new 11th view comes into the window from the bottom. In order to save memory and CPU power, Android uses the same 1st view for the 11th view. That's the purpose of convertView and the if (convertView == null) {} else {} code.
So the reason why the image is being shown in the 1st item and also in the 11th item, is that they are exactly one view object. To tackle this issue, in the getView() method, you need to reset every attribute of every view and don't rely on the defaults.
So adding a line like the one below, will get rid of the mentioned problem:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// all your code ...
holder.placeImage.setImageResource(0); //<-- This clears any previously set image.
return convertView;
}

How to set gridview within listview item and click on each grid item with uniq posion and click evant

I want to foll list view with image grid date wise.First get Date list of image and then after get image path list of particular date wise image list.and finally I fill list and grid of particular date wise image(No of images and date not fixed),have a look screen shot.
Date wise images display in Grid View
And now my problem is, When I set click listener on image and add check mark image on click then image add in two position, Why I don't know.and second is when I scroll down list view then check mark visible gone.
I want to select multiple image and add check mark image and perform operation like "Delete image" and "Share image"
Like this
I call grid adapter of each list item , look my code tell me what's wrong
Custom List View adapter : get View method
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View row = convertView;
ViewHolder viewHolder = new ViewHolder();
DateSortedImageItem item = getItem(position);
if (row == null) {
row = mInflator.inflate(R.layout.row_date_sorted_image_list, parent, false);
viewHolder.tv_date = (TextView) row.findViewById(R.id.tv_row_date);
viewHolder.rowGridView = (GridView) row.findViewById(R.id.gv_row_item);
viewHolder.tv_date.setText(item.getDate());
row.setTag(viewHolder);
gridAdapter = new GridAdapter(context, R.layout.row_sorted_image_gridview_item,
item.getDateSortedImageList(), position);
viewHolder.rowGridView.setAdapter(gridAdapter);
} else {
row.getTag();
}
return row;
}
private class ViewHolder {
TextView tv_date;
GridView rowGridView;
}
and my grid adapter code is :
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater mInflater = ((Activity) getContext()).getLayoutInflater();
convertView = mInflater.inflate(R.layout.row_sorted_image_gridview_item, parent, false);
}
view = convertView;
final SquareImageView imageView = (SquareImageView) view.findViewById(R.id.iv_test_row_grid_img);
final ImageView iv_checked = (ImageView) view.findViewById(R.id.iv_checked);
final ImageView iv_unChecked = (ImageView) view.findViewById(R.id.iv_unchecked);
view.setTag(arrList.get(position).toString());
File f = new File(arrList.get(position).toString());
System.out.println("arrList size >>" + arrList.size());
Picasso.with(context).load(Uri.fromFile(f)).resize(100, 100).centerCrop().placeholder(R.drawable.ic_launcher)
.error(R.drawable.ic_close_black).into(imageView);
I just set Grid View image. And now i set imageview click ivent and add check mark then add check mark event two places and scroll down then visible gone also.
What's wrong hear and how to set click event of image view unique.
Finally I want to design Look like Google "Photos" app.
Suggest me any example or library:
First you should create a POJO as below
public class AlbumItem {
private String headerStr;
private List<ChildItem> children;
//getter - setter....
public class ChildItem {
private String childName;
private boolean isSelected;
//getter - setter.....
}
}
Now use this POJO inside your main adapter.
and in the second adapter handle the selection logic means if isSelected is true then show iv_checked otherwise show iv_unchecked.
Please let me know if you need further explanation.
Hope it will help you.

Android - GridView forcing update on data change

I've implemented this sample (2. Custom Adapter example)
http://www.mkyong.com/android/android-gridview-example/
and it works.
I then wanted to "refresh" the data with a new set, which didn't work until I did this:
imageAdapter.notifyDataSetChanged();
and then removed the following check in the ImageAdapter getView method :
if (convertView == null) {
Here is my current getView method
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView;
// if (convertView == null) { // stopped my GridView from updating !!
if (true)
{
gridView = new View(context);
// get layout from mobile.xml
gridView = inflater.inflate(R.layout.mobile, null);
// set value into textview
TextView textView = (TextView) gridView
.findViewById(R.id.grid_item_label);
textView.setText(mobileValues[position]);
// set image based on selected text
ImageView imageView = (ImageView) gridView
.findViewById(R.id.grid_item_image);
imageView.setImageResource(R.drawable.square);
} else {
gridView = (View) convertView;
}
return gridView;
}
I'm concerned it is now doing unnecessary processing over and over - i.e. inflating view multiple times?
Should I be creating a new GridView every time this is called ?
it didn't work because the following rows
TextView textView = (TextView) gridView
.findViewById(R.id.grid_item_label);
textView.setText(mobileValues[position]);
// set image based on selected text
ImageView imageView = (ImageView) gridView
.findViewById(R.id.grid_item_image);
imageView.setImageResource(R.drawable.square);
go outside the if/else. The check if (convertView == null) is necessary. If you don't have it you will inflate n different views, with n == getCount(). For n large it will be a problem. And you probably want to implement the android ViewHolder pattern, to give your users the best UX possible.
As correctly pointed out by #Vzsg, get rid also of gridView = new View(context);. It an additional useless allocation
I usually just update the adapter with the new results, and set it to the GridView.
So in your example, when I want to update my GridView - I do the following.
gridView.setAdapter(newAdapter);
You can have a utility method, such as that will make get a new Adapter much easier.
private ArrayAdapter getAdapter(String [] data){...}

GridView with customs view

I don't know if it is possible, but actually I wouldn't see why not.
Can we do a grid view not just with ImageView but with a custom view.
I am trying to make a grid view of a view composed of an ImageView and a TextView.
I know that everything happens in my Adapter getView's function but I can't figure out how to do it.
public View getView(int position, View convertView, ViewGroup parent) {
View cases = findViewById(R.id.fileUnitLayout);
if (convertView == null) {
convertView = new View(mContext);
} else {
cases = convertView;
}
return cases;
}
My view has an id of R.id.fileUnitLayout. Let's say my inner TextView has an id of A and my inner ImageView has an id of B. How can I fill them ?
Thank you,
You should not need to override getView to accomplish this, necessarily. GridView is an AdapterView so you can provide an adapter that will display what you want via setAdapter
You could, for example, use SimpleAdapter to provide an xml file that is used for each grid view item.

ListView in ArrayAdapter order get's mixed up when scrolling

I have a ListView in a custom ArrayAdapter that displays an icon ImageView and a TextView in each row. When I make the list long enough to let you scroll through it, the order starts out right, but when I start to scroll down, some of the earlier entries start re-appearing. If I scroll back up, the old order changes. Doing this repeatedly eventually causes the entire list order to be seemingly random. So scrolling the list is either causing the child order to change, or the drawing is not refreshing correctly.
What could cause something like this to happen? I need the order the items are displayed to the user to be the same order they are added to the ArrayList, or at LEAST to remain in one static order. If I need to provide more detailed information, please let me know. Any help is appreciated. Thanks.
I was having similar issues, but when clicking an item in the custom list, the items on the screen would reverse in sequence. If I clicked again, they'd reverse back to where they were originally.
After reading this, I checked my code where I overload the getView method. I was getting the view from the convertedView, and if it was null, that's when I'd build my stuff. However, after placing a breakpoint, I found that it was calling this method on every click and on subsequent clicks, the convertedView was not null therefore the items weren't being set.
Here is an example of what it was:
public View getView(int position, View convertView, ViewGroup parent)
{
View view = convertView;
if (view == null)
{
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.listitemrow, null);
RssItem rssItem = (RssItem) super.getItem(position);
if (rssItem != null)
{
TextView title = (TextView) view.findViewById(R.id.rowtitle);
if (title != null)
{
title.setText(rssItem.getTitle());
}
}
}
return view;
}
The subtle change is moving the close brace for the null check on the view to just after inflating:
public View getView(int position, View convertView, ViewGroup parent)
{
View view = convertView;
if (view == null)
{
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.listitemrow, null);
}
RssItem rssItem = (RssItem) super.getItem(position);
if (rssItem != null)
{
TextView title = (TextView) view.findViewById(R.id.rowtitle);
if (title != null)
{
title.setText(rssItem.getTitle());
}
}
return view;
}
I hope this helps others who experience this same problem.
To further clarify the answer of farcats below in more general way, here is my explanation:
The vi.inflate operation (needed here for parsing of the layout of a row from XML and creating the appropriate View object) is wrapped by an if (view == null) statement for efficiency, so the inflation of the same object will not happen again and again every time it pops into view.
HOWEVER, the other parts of the getView method are used to set other parameters and therefore should NOT be included within the if (view == null) statement.
Similarily, in other common implementation of this method, some textView, ImageView or ImageButton elements need to be populated by values from the list[position], using findViewById and after that .setText or .setImageBitmap operations.
These operations must come after both creating a view from scratch by inflation and getting an existing view if not null.
Another good example where this solution is applied for BaseAdapter appears in BaseAdapter causing ListView to go out of order when scrolled
The ListView reuses view objects when you scroll. Are you overriding the getView method? You need to make sure you set each property for every view, don't assume that it will remember what you had before. If you post that method, someone can probably point you at the part that is incorrect.
I have a ListView, AdapterView and a View (search_options) that contains EditText and 3 Spinners. ListView items are multiple copies of (search_options) layout, where user can add more options in ListView then click search to send sql query built according to users options.
I found that convertView mixing indecies so I added a global list (myViews) in activity and passed it to ArrayAdapter. Then in ArrayAdapter (getView) I add every newly added view to it (myViews).
Also on getView instead of checking if convertView is null, I check if the global list (myViews) has a view on the selected (position).. It totally solved problems after losing 3 days reading the internet!!
1- on Activity add this:
Map<Integer, View> myViews = new HashMap<>();
and then pass it to ArrayAdapter using adapter constructor.
mSOAdapter = new SearchOptionsAdapter(getActivity(), resultStrs, myViews);
2- on getView:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
ViewHolder viewHolder;
if (!myViews.containsKey(position)) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
view = inflater.inflate(R.layout.search_options, parent, false);
/// ...... YOUR CODE
myViews.put(position, view);
FontUtils.setCustomFontsIn(view, getContext().getAssets());
}else {
view = myViews.get(position);
}
return view;
}
Finally no more mixing items...

Categories

Resources