Making a custom adapter show categorized items inside listview - android

I want to accomplish the below :
I want to categorize the items inside the listview, however, my listviews tend to appear only one rowed because I am only giving it one one (custom xml, extended custom baseadapter)
I checked this link , however it does not seem to do what I want to accomplish, any hints ?

You could add an initially hidden (View.GONE) header to your row's XML and fill it and show it when a category change is detected.
Another more efficient option would be inflating / creating and adding this header (which could be any kind of View or ViewGroup) programmatically when the category change is detected.
For example (first option):
row.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rowContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/txtGroupHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:padding="4dp"
android:background="#drawable/group_header_gradient"
android:gravity="center"
android:textColor="#android:color/white" />
<ImageView
android:id="#+id/imgLogo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:layout_marginLeft="3dp"
android:layout_marginRight="5dp"
android:layout_alignParentLeft="true"
android:layout_below="#id/txtGroupHeader" />
</RelativeLayout>
Adapter code
#Override
public View getView(int position, View convertView, ViewGroup parent){
View res = null;
Pojo ev = (Pojo)this.getItem(position);
Integer prevItemType = null;
//Get the type of the previous pojo in the list
if(position > 0){
Pojo prevEv = (Pojo)this.getItem(position - 1);
if(prevEv != null){
prevItemType = prevEv.getType();
}
}
//Determine if this view should have a header
boolean addHeaderView = !(prevItemType != null && prevItemType.equals(ev.getType()));
if(convertView != null){
res = convertView;
}else{
res = mInflater.inflate(R.layout.row, null);
}
TextView txtHeader = (TextView)res.findViewById(R.id.txtGroupHeader);
if(addHeaderView){
String typeName = Database.getTypeDescription(ev.getType());
if(typeName != null){
txtHeader.setText(typeName.toUpperCase(Locale.US));
}
txtHeader.setVisibility(View.VISIBLE);
}else{
txtHeader.setVisibility(View.GONE);
}
//Regular row
ImageView imgLogo = (ImageView)res.findViewById(R.id.imgLogo);
// ... imgLogo.setImageBitmap ...
// ... etc ...
return res;
}
Hope it helps.

Related

How can i make a spinner prompt multiline?

I have a spinner that allows me to not show the first item in the list, but i can set my custom prompt. However whenever the prompt text spans more than one line it is cut off at the view bounds. How can i make the spinner prompt expand to accommodate more text?
I have tried modifying the view passed into the adapter to have multiple lines and also to ellipsize at the end, but nothing works.
Images for clarity:
With one line of text,
With several lines,
This is my code:
languagesSpinner.setAdapter(new ArrayAdapter<>(EditProfileNationalityActivity.this, R.layout.no_default_spinner_item, new String[] {""}));
if(data.length>0) {
String countries = spokenLanguages.toString().substring(0, spokenLanguages.toString().length() - 2);
languagesSpinner.setPrompt(countries);
} else {
Log.e("setting prompt to default");
languagesSpinner.setPrompt("Please select languages");
}
and this is the xml file:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_gravity="center_vertical"
android:textColor="#android:color/black"
android:textSize="18sp"
android:ellipsize="end"
android:lines="2"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:paddingLeft="1dp"
android:paddingRight="1dp"
android:background="?android:attr/activatedBackgroundIndicator" />
Per request, xml definition of spinner is as follows:
<com.package.views.NoDefaultSpinner
android:id="#+id/registration_stage_4_country_languages"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:clickable="false" />
NoDefaultSpinner.java can be found here: https://github.com/geftimov/android-components/blob/master/components/src/main/java/com/eftimoff/components/views/spinners/nodefault/NoDefaultSpinner.java
I have modified it to have a custom getView() method in the SpinnerProxy like this:
if (position < 0) {
if (layoutResource == -1) {
layoutResource = R.layout.no_default_spinner_item;
}
final TextView v =
(TextView) ((LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE)).inflate(
layoutResource, parent, false);
v.setText(getPrompt());
v.setPadding(0, 5, 0, 5);
return v;
}
return obj.getView(position, convertView, parent);
}
I edited your source code:
adapter = new ArrayAdapter<>(EditProfileNationalityActivity.this, R.layout.no_default_spinner_item, new String[] {""});
adapter.setDropDownViewResource(R.layout.no_default_spinner_item);
languagesSpinner.setAdapter(adapter);

Android ExpandableListView item images disappear

I have to display a list of football players in a list. No problem about that, everything works fine but the little flags for the nationality are disappearing while I scroll down my list.
Here is what it should look like : list item player OK
And here is the result I have after some scrolling : list item player NOK
I also have an Image for the portrait of the player and another one to show the shirt which are working fine.
Here is some part of my code (I only put some parts of it to reduce the size and to put away what's working but feel free to ask for more if you need) :
My item list layout (partial layout, you won't get the same result as the image show) :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="3dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingTop="3dp"
android:orientation="horizontal" >
<ImageView
android:id="#+id/portrait"
android:layout_width="32dp"
android:layout_height="32dp"
android:background="#drawable/portrait_default" />
<LinearLayout
android:id="#+id/nationalityLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal" >
<ImageView
android:id="#+id/logoNationality"
android:layout_width="13dp"
android:layout_height="13dp"
android:layout_marginRight="3dp" />
<TextView
android:id="#+id/nationality"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:textSize="13dp" />
</LinearLayout>
<LinearLayout
android:id="#+id/shirt"
android:layout_width="40dp"
android:layout_height="32dp"
android:gravity="center_horizontal" >
<TextView
android:id="#+id/number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="5dp" />
</LinearLayout>
</LinearLayout>
I have a holder for my items :
private class ChildViewHolder {
public ImageView portrait;
public ImageView logoNationality;
public TextView nationality;
public LinearLayout nationalityLayout;
public LinearLayout shirt;
public TextView number;
public void reset() {
portrait.setImageBitmap(null);
portrait.setBackgroundResource(R.drawable.portrait_default);
nationalityLayout.setVisibility(View.VISIBLE);
nationality.setText("");
number.setText("");
}
}
And the getChildView from my adapter (with flags being a map filled while putting items in the adapter list and playerShirt a BitmapDrawable loaded before) :
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
ChildViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.liste_item, null);
holder = new ChildViewHolder();
holder.portrait = (ImageView) convertView.findViewById(R.id.portrait);
holder.nationalityLayout = (LinearLayout) convertView.findViewById(R.id.nationalityLayout);
holder.logoNationality = (ImageView) convertView.findViewById(R.id.logoNationality);
holder.nationality = (TextView) convertView.findViewById(R.id.nationality);
holder.shirt= (LinearLayout) convertView.findViewById(R.id.shirt);
holder.number = (TextView) convertView.findViewById(R.id.number);
convertView.setTag(holder);
} else {
holder = (ChildViewHolder) convertView.getTag();
holder.reset();
}
FootPlayer player = children.get(groupPosition).get(childPosition);
// Doing nothing with portrait for now
if (player.getNationality() != null) {
holder.nationalityLayout.setVisibility(View.VISIBLE);
holder.nationality.setText(player.getNationality());
if (player.getNatImg() != null) {
holder.logoNationality.setImageDrawable(flags.get(player.getNatImg()));
} else {
holder.logoNationality.setVisibility(View.INVISIBLE);
}
} else {
holder.nationalityLayout.setVisibility(View.GONE);
}
holder.shirt.setBackgroundDrawable(playerShirt);
holder.number.setText(String.valueOf(player.getNumber()));
return convertView;
}
Right now, flags are appearing at the beginning of the list, proving me that the flags map is correctly filled with my images, but while I scroll down they start to disappear randomly and in the end none of them show up anymore.
So important points are :
My flags map is correctly filled with BitmapDrawable (and correct keys)
My playerShirt is also a BitmapDrawable but doesn't disappear as flags do
I already tried to use setBitmapImage instead of setBitmapDrawable to set the flag image (and also set the background as I'm currently doing with the shirt)
I tried with drawable res images and I have the same result
I know that I go through my if condition to show the flag correctly
Any help about this issue would be greatly appreciated.
You are not setting logoNationality visibility back to VISIBLE, as you are doing with nationalityLayout. So I guess once it's gone for the first time, it remains invisible, even if you later reuse the view setting a drawable to it.
Have a look to the fixed code:
if (player.getNationality() != null) {
holder.nationalityLayout.setVisibility(View.VISIBLE); // <- SET VISIBLE, Well done!
holder.nationality.setText(player.getNationality());
holder.logoNationality.setVisibility(View.VISIBLE); // <- Missing line: SET VISIBLE as before.
if (player.getNatImg() != null) {
holder.logoNationality.setImageDrawable(flags.get(player.getNatImg()));
} else {
holder.logoNationality.setVisibility(View.INVISIBLE); // <- OK, no logo, so hide it.
}
} else {
holder.nationalityLayout.setVisibility(View.GONE); // No nationality, hides entire layout.
}

Change view background color into a listview

I'm trying to change background color on a view component, but not success
public View getView(int position, final View convertView, ViewGroup parent) {
View view = convertView;
try {
if (view == null) {
LayoutInflater vi = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.listview_accounts, null); // --CloneChangeRequired(list_item)
}
final Account listItem = (Account) mList.get(position); // --CloneChangeRequired
if (listItem != null) {
int color = listItem.getColor();
View vColor = (View) view
.findViewById(R.id.lv_account_view_color);
vColor.setBackgroundColor(color);
}
}
} catch (Exception e) {
}
return view;
}
I can set some text in textview, but set color not working.
Can anybody helps me how to set the color? Thanks
The example color used is: -16711717
edit
Listview Item layout:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<View
android:id="#+id/lv_account_view_color"
android:layout_width="#dimen/activity_horizontal_margin"
android:layout_height="wrap_content"
android:background="#167117" />
<TextView
android:id="#+id/lv_account_tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/activity_horizontal_margin"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
android:layout_marginTop="#dimen/activity_horizontal_margin"
android:textColor="#color/black" />
</LinearLayout>
background cannot be setted in xml, it's a dynamic color
Try this: vColor.setBackgroundColor(Color.parse("#yourcolorcode"));
You can directly set the background color of the component in the listview_accounts.xml file of your project. For example
<component>
android:background="#color/color_name"
</component>
You have to make a color.xml file in your values folder(maybe already present) and add the color value ex:-16711717.
try this and let me know
<View
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#167117" />
you can find solution on This link
Just you have to change one thing. In delete.onclick method replace list.removeView(customView); with Customview.setbackground(Color.red); etc. This may help you. Best of luck.

ListView items drawn on top of each other when scrolling (Android)

In a fragment, I have a ListView that has a custom ParseQueryAdapter<T>. The problem may not have anything to do with Parse, although I'm not sure.
As I was testing my app, I noticed something very strange. When I would scroll down my ListView, all the visible ListView items would be drawn on top of the next ListView item as seen in the second image below.
The list initialized properly as such:
As you can see, in my list item layout, I have an ImageView (ParseImageView to be specific) and a TextView. The TextView now displays some notes (don't mind the ID user_name_text_view) and the ImageView displays a placeholder blank profile picture.
When I scrolled down, the list looked like:
Here's my list view layout named fragment_post_view_list_view:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/post_list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
Here's my list item layout named list_item_post_view:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.parse.ParseImageView
android:id="#+id/icon"
android:layout_width="75dp"
android:layout_height="75dp"
android:layout_alignParentLeft="true"
android:background="#drawable/com_facebook_profile_picture_blank_square" />
<TextView
android:id="#+id/user_name_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/icon"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#color/link_blue" />
</RelativeLayout>
Here's my adapter named PostViewListViewAdapter:
public class PostViewListViewAdapter extends ParseQueryAdapter<Post> {
// call superclass with a query to populate list view
public PostViewListViewAdapter(Context context, final String[] postsObjectIds) {
super(context, new ParseQueryAdapter.QueryFactory<Post>(){
public ParseQuery<Post> create() {
ParseQuery<Post> query = Post.getQuery();
query.whereContainedIn("objectId", Arrays.asList(postsObjectIds));
return query;
}
});
}
// this is similar to getView method in an adapter
#Override
public View getItemView(Post post, View v, ViewGroup parent) {
if(v == null) {
v = View.inflate(getContext(), R.layout.list_item_post_view, null);
}
super.getItemView(post, v, parent);
TextView usernameTextView = (TextView) v.findViewById(R.id.user_name_text_view);
usernameTextView.setText(post.getNotes()); // some string
return v;
}
}
How can I fix this problem?
Is this an issue with XML or Java?
I was following the two tutorials from Parse and the example from the Parse docs:
MealSpotting
Parse Query Adapter
I set the adapter and ListView here:
View rootView = inflater.inflate(R.layout.fragment_post_view_list_view, container, false);
mPostsObjectIds = SOME_STRING[];
PostViewListViewAdapter adapter = new PostViewListViewAdapter(getActivity(), mPostsObjectIds);
ListView listView = (ListView) rootView.findViewById(R.id.post_list_view);
listView.setAdapter(adapter);
I've tried getting rid of the ParseImageView in my list item layout, but my TextViews still draw on top of each other when I scroll.
Edit:
I forgot to mention that the list items display on top of each other after an orientation change.
I tested this on my Galaxy S5 (Android version 4.4.2 and Parse 1.4.1).
In my Activity, I show the Fragment here (called PostViewListViewFragment):
getSupportFragmentManager().beginTransaction().add(android.R.id.content, new PostViewListViewFragment()).commit();
Try below layout :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/post_list_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="none" >
</ListView>
</RelativeLayout >
Make Sure your adapter like this:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
// reuse views
if (rowView == null) {
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.rowlayout, null);
// configure view holder
ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) rowView.findViewById(R.id.TextView01);
rowView.setTag(viewHolder);
}
// fill data
ViewHolder holder = (ViewHolder) rowView.getTag();
String s = names[position];
holder.text.setText(s);
return rowView;
}
}
PS:You should watch this Google IO video about Listview,and here is the slides.
First create a ViewHolder class
static class ViewHolder {
protected TextView usernameTextView;
}
Then change your getItemView method like below
public View getItemView (Post post, View convertView , ViewGroup parent)
{
ViewHolder viewHolder = null;
if (convertView == null)
{
LayoutInflater inflator = context.getLayoutInflater();
convertView = inflator.inflate(R.layout.list_item_post_view, null);
viewHolder = new ViewHolder();
viewHolder.usernameTextView = (TextView)convertView.findViewById(R.id.user_name_text_view);
convertView.setTag(viewHolder);
convertView.setTag(R.id.user_name_text_view, viewHolder.usernameTextView);
}
else
{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.usernameTextView.setText(post.getNotes()); // some string
return convertView;
}
The problem seems to be in your list item layout -
Change it to this -
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.parse.ParseImageView
android:id="#+id/icon"
android:layout_width="75dp"
android:layout_height="75dp"
android:layout_alignParentLeft="true" />
<TextView
android:id="#+id/user_name_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/icon"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#color/link_blue" />
</RelativeLayout>
Probably you have extra background for each list item set that is causing such effect.
Alter and watch.
Hope this gives you idea!
Try changing your list view layout height to match_parent.
Credit to #VedPrakash for helping me fix this.
In case it helps anyone, I fixed the problem by replacing the fragment not adding it. So I changed this line from:
getSupportFragmentManager().beginTransaction().add(android.R.id.content, new PostViewListViewFragment()).commit();
to:
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, new PostViewListViewFragment()).commit();

Add a new item to a listview

I am not quite sure my question really has something to do with listview.There is an app named Gleeo Time Tracker ,and here has a screenview of it.When you press the symbol "+",a new item will be created,and you can delete one item by pressing the "-".More is that when I click the record button on the left of the item,the background will change.
My question is,what is it in the end,a listview? How can I achieve such thing?Thank you all!
What you want to do, is build a custom ListView.
This is done by providing a layout file, for example
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#android:color/transparent">
<ImageView android:id="#+id/Plus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent" />
<TextView android:id="#+id/Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent" />
</LinearLayout>
This layout is then applied to each row of your ListView by overriding its Adapter's getView() method, for example something like this:
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) MyActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.row, null);
}
ImageView plus = (ImageView) v.findViewById(R.id.plus);
icon.setImageDrawable(BrowseActivity.this.getResources().getDrawable(R.drawable.plus));
TextView title = (TextView) v.findViewById (R.id.Browse_FileName);
// add a listener to your button and you're done
return v;
}
read about list view in developer docs and here is an example

Categories

Resources