I've got a GridView (Android). I would like to hide one of it's columns and then access to it's values.
Is it possible?
Update: based on your reply, I think it best you hold your data in a map, rather than using an invisible column...
Example:
HashMap<Integer, Integer> map_positionToId = new HashMap<Integer, Integer>();
map_positionToId.put(position, id);
int id = map_positionToId.get(position);
There is no easy setting to flip on gridview to make a column invisible that I am aware of.
However, below is a suggestion to try... It may take a bit of trial and error to pull off correctly:
This is the getView method for your gridView adapter:
public View getView(int position, View convertView, ViewGroup parent) {
//You want your if(convertView == null) code here.
//As we can't set visibility of a null object;
....
// Assuming u want to blank the 3rd column, in a 3 column gridview
if(position % 3 == 0)
convertView.setVisibility(View.INVISIBLE); //u can try gone too?
else
convertView.setVisibility(View.VISIBLE);
// rest of your code...
}
You might also play around with padding / margins, and view width, to get the desired effect if you are trying to push the invisible column off the screen.
Related
How can I open specific position in listview? Let me tell what's my requirement and what I tried!
It's table of contents where when we are in page no 100, and when we click table of contents, it displays 100th page by highlighting. This is the requirment.
But in my case what's happening is, it keeps on scrolling and user needs to wait till the scrolling stops at 100th page. I used setSelection but it doesn't work.
So if I use smoothScrollingToPosition , it keeps on scrolling to stop at specific position. So my requirement is without scrolling directly to open specific page.
Below is the logic. I applied listview in constructor of the class Adapter.
In adapter,
#Override
public final View getView(final int position, View convertView, final ViewGroup parent) {
int type = getItemViewType(position);
if ((convertView == null) || (((Integer) convertView.getTag()) != type)) {
convertView = createView(position);
convertView.setTag(type);
}
final BaseTableOfContents node = getItem(position);
for(int i=0; i<mNodes.size();i++){
BaseTableOfContents nodes = mNodes.get(i);
if(okayToHighlightAnchorNode(nodes,i)==true){ //only when true, it lands to specific position.
Log.v("nodes","nodes"+okayToHighlightAnchorNode(nodes,i) + nodes.getText() + i);
// returnValue.getListView().setSelection(i); //but this is not working.
returnValue.getListView().smoothScrollToPosition(i,i); //this keeps on scrolling to specific page instead of directly landing to the specific page.
}
}
For a direct scroll use this below code:
getListView().setSelection(21);// anylistview.setSelection(21);
For a smooth scroll use this:
getListView().smoothScrollToPosition(21);//anylistview.smoothScrollToPosition(21);
You can do this -
yourListView.smoothScrollToPositionFromTop(position,offset,duration);
where position is where you want to scroll , duration is number of milliseconds taken to scroll, and offset is the distance in pixel
I have a list in my app, and it's implemented as an AbsListView, so that when we are working on a smaller screen (phone) it's a List and when we are on a larger screen (tablet) it's a Grid.
All works well.
Now I want to add in a header item which is completely different from the regular items on my list - it has a completely different xml file. It's always the first item in the list.
I've added in code to my Adapter class like so:
public override View GetView(int position, View convertView, ViewGroup parent)
{
SavedInfo subViews = null;
var rowView = convertView;
var channel = items[position];
// don't want to reuse if our previous view was a header
if (rowView?.Tag != null)
{
subViews = rowView.Tag as SavedInfo;
}
// try to put in a different view if there is a header shown
// special id value for header is -1
if (position == 0)
{
subViews = null;
}
if (subViews == null)
{
if (position == 0)
{
rowView = context.Activity.LayoutInflater.Inflate(Resource.Layout.header_layout, null);
// Do setup stuff with this layout
rowView.Tag = null;
return rowView;
}
rowView = context.Activity.LayoutInflater.Inflate(cellLayout, null);
// Do stuff with regular layout, take savedInfo from Tag
rowView.Tag = subViews;
}
// other adjustments to the regular layout
return rowView;
}
So that's fine in a regular list - I have one header item and lots of regular items. However, when I switch to GridView (which uses the same adapter) my "header" item is now just the first cell in the grid.
What I want it to be is more or less the same as it is in the list view - a single column which fills the width of the screen, then followed by the regular grid. The point is I want an item which fills all the columns across, but scrolls up with the grid. Is there a way to do this? I understand I might need to replace with some sort of custom Adapter View. Does anyone have an example of code doing a grid with one item filling multiple grid columns?
Thanks
Turns out this is not possible - the recommended way to put in a header is to use a CoordinatorLayout and a CollapsingToolbarLayout while changing the ListView to a RecyclerView
The Problem
My way to add the view makes every fifth item to add the view when i only want one position to have this "Mängd" row.
Why Can i only edit listitems when they are visible on the screen.
The child will be static at 5 items even though i got like 20 item....
Is there any way to only say that item 1 will have this and not
position - firstvisibleposition
i think this is the problem with the listview
My code is not understandable at the time because of other things so i hope you get my problem anyways.
This is my main question
It seems like the thing i add to position 0 also happens to 6 and 12 Why is ListView this wierd ?
It's on swedish, but this is what i got with list view.
Every listview item has a empty Linearlayout that i add a view to when i press the down arrow button. the problem is that every fifth item gets this or i can only click on the first 5.
I dont get why they make ListView so complicated. i want to be able to get a child that is in the list without seening it!
CODE getView
public View getView (int position, View convertView, ViewGroup parent){
if (convertView == null)
{
convertView = LayoutInflater.from(getContext()).inflate(R.layout.view_meal_item_editable, null);
}
convertView.setOnTouchListener(new ItemSwipeListener(position,
getResources().getDisplayMetrics().density));
convertView.setClickable(true);
// Lookup view for data population
TextView food_item_name = (TextView) convertView.findViewById(R.id.food_item_name);
food_item_name.setHint("hello");
}
Where i add the view
View view = searchResultList.getAdapter().getView(position, searchResultList.getChildAt(position - searchResultList.getFirstVisiblePosition()), searchResultList);
LinearLayout extendedView = (LinearLayout)view.findViewById(R.id.extended_food_information);
View convertExtendedView = LayoutInflater.from(this).inflate(R.layout.change_amount_on_food_view, null);
extendedView.addView(convertExtendedView);
It's recommended to use a header view if you do this stuff only for the first element.
Otherwise it will be better if you add your extra view in getView() method, something like:
if(position==0){
// add extra view
} else {
// remove extra view if exist
}
Or you can remove the IF condition: if (convertView == null), so you will inflate a new layout each time, it will solve your problem but this is not good for list performance
I'm trying to perform something like the GMail app does: when long touching several List view items their background colour is changed so that the user notices that something happened.
My problem is to keep those items visually selected (with the background colour changed) when the device orientation is changed. I tried this with little luck:
ListView lv = getListView();
ItemAdapter adapter = (ItemAdapter)lv.getAdapter();
if (adapter == null) return;
for (Item q : mSelectedItems) {
int position = adapter.getItemPosition(q);
if (position == -1) continue;
View itemView = lv.getChildAt(position);
if (itemView == null) continue;
itemView.setBackgroundColor(getResources().getColor(R.color.orange));
}
I call this method from the onRestoreInstanceState() callback, but I receive a null in itemView because it seems that the listView hasn't been filled up yet, so there are no children at the moment. I tried to call this method from the onResume with no luck as well.
What's the proper way to accomplish this?
I found the solution by myself. The proper way to accomplish this is the custom Adapter created to fill the view. Create the adapter providing a context (the Activity that has the information of which items should be painted this way or that way) and call it to get the items whose background must be changed. When iterating on the listview to paint, if the current item is one of those, paint it differently. Example:
public View getView(int position, View convertView, ViewGroup parent) {
...
RelativeLayout itemLayout =
(RelativeLayout) LayoutInflater.from(mContext).inflate(R.layout.my_layout, parent,
false);
if (((MyActivity) mContext).isItemSelected(item)) {
itemLayout.setBackgroundColor(mContext.getResources().getColor(R.color.orange));
}
}
I wanted to know how I may go about creating a loop for setting a specific background colour to each of my listview items in a reoccurring pattern. Say I have 10 items and 4 colours and I want the 10 items to be coloured in order of the pattern and for it to repeat, until the items are all coloured. Considering I have the following colours in an Integer Array:
int[] colours = {Color.RED, Color.BLUE, Color.GREEN, Color.MAGENTA};
Well, I would implement a custom Adapter or a ViewBinder for this.
In case of an Adapter, for example ArrayAdapter you have to override the getView method
...
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
view = getActivity().getLayoutInflater().inflate(R.layout.item, null);
}
view.setBackgroundColor(colors[position % colors.length]);
return view;
}
....
First off, you have to be clear about two things:
This should go in the process of getView()
getView() renders your rows, but it doesn't sequentially. Performance depends very much on your layout implementation, but you cannot guarantee your rows will be rendered in order.
That said, I think there could be a way to do this:
Prior to passing your data to your ArrayAdapter, define an extra variable in your ArrayList, you should use a class if you're not yet using it.
Assign it the number of the background you want to set it. Ideally, this should be an int with the Color.YOURCOLOR you want to set it.
Once processing within your getView() method, get that data for the row and simply call:
YourClass item = (YourClass) getItem[position];
convertView.setBackgroundColor(item.getMyColor());