Android fixed height on list item photo - android

I'm making an app that uses a listview that has section headers and content. For each header I want to use an image but the view is setting it's height to the image's and not the value that I set the height at. This is in my adapter:
#Override public View getView(int position, View convertView, ViewGroup parent) {
TextView view = (TextView) super.getView(position, convertView, parent);
view.setTextColor(Color.DKGRAY);
Item item = getItem(position);
if (item.type == Item.SECTION) {
if (position == 0) {
view.setBackgroundResource(R.drawable.myImage);
view.setHeight(400);
view.setMaxHeight(400);
}
else {
//deal with other views
}
}
return view;
}
I'm testing this by just setting the first item in the list as a photo, but as I said, the view isn't using 400px as the height. If I set the height the same way in the else block and just set the background as a color it works fine. I should note that I want to avoid just scaling the picture manually to fit because eventually I want the view to just show a frame of the full image and add a scrolling effect.

I'm not quite sure what you are asking. Do you want it only to only show 400px if there is an image and smaller if there is not? With the code you have does the image show?
I immediately want to rewrite your code like this:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = new TextView(mContext); // where mContext = context; appears in the adapter constructor
convertView.setTextColor(Color.DKGRAY);
Item item = getItem(position);
if (item.type == Item.SECTION) {
if (position == 0) {
convertView.setBackgroundResource(R.drawable.myImage);
convertView.setHeight(400);
convertView.setMaxHeight(400);
//need something like convertView.setText((String) item); to get text to show
}
else {
//deal with other views
}
}
return convertView;
}
I'd recommend using xml to define the layout for the row. Makes it far easier to customise the look of the row.

Related

Are convertViews being reused in a ListView?

I am using this code to layout my ListView, using a different layout based on some data:
#Override
public View getView(int i, View convertView, ViewGroup viewGroup) {
ViewHolder viewHolder;
MyInfo myInfo = getItem(i);
String label = myInfo.getLabel();
if (convertView == null) {
if (!"".equals(label)) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.info_grey, null);
Log.d(SapphireApplication.TAG, "GREY, label=" + label);
} else {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.info_plain, null);
Log.d(SapphireApplication.TAG, "PLAIN, label=" + label);
}
viewHolder = new ViewHolder();
viewHolder.tvLabel = convertView.findViewById(R.id.tvLabel);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder)convertView.getTag();
}
viewHolder.tvLabel.setText(label);
return convertView;
}
However, the Log.d is never done for some items in the list. Does that mean Android re-uses an existing convertView, causing it (in this case) to use the wrong layout?
Yes. They are being re-used. And that is the reason you are seeing that message log for few items only.
#Override
public View getView(int i, View convertView, ViewGroup viewGroup) {
if (convertView == null) {
// convertView is null. It means the ListView does not have a view to give to you
// This way, you need to create a new one.
// You will enter here until the ListView has enough Views to fill
// the screen.
// So, just inflate the view and set the View holder here.
// Don't customize your view here (set text, contenet etc)
// So, any log message here will be printed only when the ListView becomes visible (and when you scroll to next item)
// After that, views will be re-used so convertView will no longer be null
} else {
// ListView gave a convertView to you. It means that you are receiving a View
// that was created in the past and it is be re-used now.
// At this moment, convertView still has the content of the old item it was
// representing.
// This view was created in the statement above and after user scrolled the ListView
// it becomes hidden and ready to be re-used.
// Don't customize the view here.. just get the ViewHolder from the View
}
// Here you customize the View. Set content, text, color, background etc
// The ViewHolder is just a helpful class to help you to access
// all View inside the convertView without needing to perform the
// findViewById again.
return convertView;
}
In this basic example however, all convertViews are similar. They were inflated from the same layout.
This works fine for when you have a single view type per line. all items are similar but with different content.
This still works if you have small differences. For example, you can inflate same layout and control the visibility of some of its Views according to the position (position 1 has an image and position 2 don't).
However, there are some cases where you really need to inflate different layouts per row.
For example, the "grey" layout is very different from the "plain" layout. On this case, you need to update you
code as follows:
private static final int GREY = 1;
private static final int PLAIN = 2;
private static final int TOTAL_VIEW_TYPES = 2; // Grey and Plain
#Override
public int getViewTypeCount() {
// Tell the list view that you have two types of Views (Grey and plain)
return TOTAL_VIEW_TYPES;
}
#Override
public int getItemViewType(int position) {
// You must inform view type for given position
String label = myInfo.getLabel();
if (!"".equals(label)) {
return GREY;
} else {
return PLAIN;
}
}
#Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
if (convertView == null) {
// If view is null, you must create the view. But you need to create the
// correct view for given position
if(getItemViewType(position) == GREY) {
// Inflate grey;
} else {
// inflate plain
}
} else {
// convertView is not null. It is being reused.
// Android will give you the proper view here. If you are expecting
// a plain type, that's what you will get. Android won't re-use
// plain layout where you are expecting to have the grey layout.
// It will re-use the proper view for each position (following to the getItemViewType()).
// ListView is very robust.
}
// Update the view here.. Just remember that here you may have two different
// types of view.. grey or plain.
return convertView;
}
The most cool about theses concepts is that they are valid for any view that uses this View<->Adapter relation..
RecyclerView, ListView, Spinner, PagerView etc.

dynamic layouts in navigation drawer ruins the view

I'm facing some trouble with the navigation drawer adapter.
It's supposed to display items as follows: Favorito, Categorias, and small sub categories underneath categorias.
I programmed the navigation drawer adapter to use a big_layout.xml file by default, but if its position is greater than a certain value, then it uses a small_layout.xml file.
It works fine for the first few items, but the problem is when I scroll down to see the rest of the items, they use the big_layout.xml, and then when I scroll back up, the original big items change their view and use the small layout!
below is the code, and this is a screen shot of the bad results: http://i.stack.imgur.com/QWwts.jpg
#Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
LayoutInflater laoutInflater = (LayoutInflater)
context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (getItemId(position)>3)
view = laoutInflater.inflate(R.layout.drawer_list_item_small, null);
if (getItemId(position)<=3)
view = laoutInflater.inflate(R.layout.drawer_list_item, null);
}
ImageView icon = (ImageView) view.findViewById(R.id.icon);
icon.setImageResource(drawerItems.get(position).getIcon());
TextView title = (TextView) view.findViewById(R.id.title);
title.setText(drawerItems.get(position).getTitle());
return view;}
Is there anything wrong I'm doing ? , Is there something missing that might be responsible of making the view stable?
How can i fix this ?
Your issue is with recycling. When you scroll down and back up, the views using the small layout are no longer needed, and so are eligible for recycling - now, the view is not null, so the layout will not be reinitialised based on its position, but merely updated with the new content.
You can fix this by using ViewTypes in your list adapter class, overriding the following methods.
#Override
public int getItemViewType(int position) {
return (position > 3) ? 0 : 1;
}
#Override
public int getViewTypeCount() {
return 2;
}
Then, in your getView() you will not be given a view (for recycling) if it is of the wrong view type.
#Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
int layout = getLayoutForViewType(position);
view = LayoutInflater.from(parent.getContext()).inflate(layout, null);
}
...
return view;
}
private int getLayoutForViewType(int position) {
if (getItemViewType(position) == 0) {
return R.layout.blahblahblah;
}
return R.layout.bloobloobloo;
}

Creating a Listview with different textsize on each row

I want to create an listview that shows 5 rows at a time. It should have middle row visible with bigger text than the other rows. The 2nd and 4th rows visible but with text smaller than middle row and the 1st and 5th visible with smaller text again. So listview looks like a wheel running..
Listview comes up with lots of list values.
I tried but cant achieve an effect similar to this:
use Customized list view for this...
and in getView method set the size of text.
for example..
public View getView(int position, View convertView, ViewGroup parent) {
View = convertView;
view = layoutInflator.inflate(R.layout.listrow,null);
TextView tv =(TextView) view.findViewById(R.id.tv);
if(position==0){
tv.setTextSize(your text size here);
}
tv.setText("text");
return view;
}
As you want to make difference in every row depending on your condition you have to first catch the position of row you are getting in list item. After that you have to put in that list item your desire layout design or data.
If you want you can also change the layout design component from code as you are just trying to increase the size of textview. So at first get the position of list item by :
getItemViewType(int position) - returns information which layout type you should use based on position
After that just increase the size of your texview by : tvYourTextView.setSize("Your text size");
Check for details : HowTo: ListView, Adapter, getView and different list items’ layouts in one ListView
Happy coding!!!
try this.
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
convertView = layoutInflator.inflate(R.layout.customlistview_xml,
null);
TextView head = (TextView) convertView.findViewById(R.id.header);
if (position % 2 == 0) {
// you can vary these and check..
head.setTextSize(float value);
} if(position % 3 == 0) {
head.setTextSize(float value);
}
else {
head.setTextSize( normal float value);
}
Itemclass attach = new Itemclass();
attach = structure.get(position);
head.setText(attach.name);
}
return convertView;

Color with different color in list view

I have a simple list view and i have to color every alternative row with different color.
Is it possible to color listView with different color.
Yes. Assuming ArrayAdapter, you will have to do something like this:
public View getView(int position, View convertView, ViewGroup parent) {
...
if (position % 2 == 0) { // Even numbered row
// set a color as background for view
} else { // Odd numbered row
// set another color as background for view
}
...
}
Is it possible to color listView with different color.?
Yes, its possible. You can use a listview with custom adapter.
Follow this tutorial ..
Yes, its possible , for this use getView()
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = (ViewHolder) convertView.getTag();
if (position == 0){
holder.layout.setBackgroundColor(Color.RED);
}
if (position == 1){
holder.layout.setBackgroundColor(Color.BLUE);
}
}
So On.....

Android: ListView changing wrong row layout visibility

I have listview with hundred of items. Every item had a couple of LinearLayouts but ONE of them is Visibility.GONE! Every item has textviews and an image. On Image Click i want to set the LinearLayout with visibility.Gone to View.VISIBLE. It works fine until you scroll down the listview, then every 4th item has the same layout set to VISIBLE but i only need the Clicked one! Here is the getView method:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ImageView imgForClick;
View vi = convertView;
if (convertView == null)
vi = inflater.inflate(R.layout.custom_row, null);
final LinearLayout hiddenLayout = (LinearLayout)vi.findViewById(R.id.hiddenLayout);
imgForClick = (ImageView)vi.findViewById(R.id.imageView3);
imgForClick.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
hiddenLayout.setVisibility(View.VISIBLE);
}
});
return vi;
}
That's because you are recycling the views, so the layout gets changed on a click and then that layout is used in your other rows to save memory.
You need to remember the state of each of the rows to know whether or not the layout should be visible or not
Have something like this:
public View getView(final int position, View convertView, ViewGroup parent) {
...
if (shouldBeVisible.get(position)) {
hiddenLayout.setVisibility(View.VISIBLE);
} else {
hiddenLayout.setVisibility(View.GONE);
}
That way the layout will always be set one way or another.
shouldBeVisible is a List of something that lets you know which rows should have that layout visible or not.
EDIT--
An alternative is to remove view recycling, however this will dramatically hurt performance and should NOT be done, but I'm just explaining to list all your options.
You would remove the line
if (convertView == null)
Making Android always inflate a new view, instead of using the recycled one when possible.

Categories

Resources