Display drawable in Sherlocklistfragment with custom layout - android

Im trying to display drawables from packages installed on the android device example: "com.android.browser" to show an icon for the application.
I have setup an sherlocklistfragment with this layout
XML
<?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="horizontal" >
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="#+id/appName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/numOpen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
Then i use a hashmap to handle the data for the simpleAdapter
Sherlocklistfragment
public class List_fragment extends SherlockListFragment {
private PackageManager pk;
String[] apps = new String[] {
"Browser",
"Email",
"Facebook",
"Clock",
"Map",
"Calendar",
"Settings",
"Media player",
"Google play",
"testapp"
};
String[] period = new String[]{
"54",
"23",
"42",
"23",
"14",
"23",
"23",
"1",
"10",
"12"
};
public final static String TABLE_LOGS = "logs";
public final static String ID_COL = "_id";
public final static String DATE_COL = "date";
public final static String PACKAGE_COL = "package";
public final static String LAT_COL = "lat";
public final static String LNG_COL = "lng";
public final static String DUR_COL = "duration";
View view;
private OnItemClickListener mOnItemClickListener;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
List<HashMap<String,Object>> aList = new ArrayList<HashMap<String,Object>>();
pk = getSherlockActivity().getPackageManager();
Drawable drawable = null;
for(int i=0;i<10;i++){
HashMap<String, Object> hm = new HashMap<String,Object>();
hm.put("app", "" + apps[i]);
hm.put("per", period[i] + " seconds");
try {
drawable = pk.getApplicationIcon("com.android.browser");
//hm.put("image", drawable);
hm.put("image", R.drawable.down_arrow);
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
aList.add(hm);
}
Log.d("DRAWABLE", " "+ drawable);
SimpleAdapter listAdapter = new SimpleAdapter(inflater.getContext(), aList,
R.layout.list_layout, new String[] {"image", "app", "per"}, new int[] {R.id.imageView, R.id.appName, R.id.numOpen});
//listAdapter.setViewBinder(mViewBinder);
setListAdapter(listAdapter);
Log.d("String " , " " + aList);
return super.onCreateView(inflater, container, savedInstanceState);
}
private final SimpleAdapter.ViewBinder mViewBinder = new SimpleAdapter.ViewBinder() {
#Override
public boolean setViewValue(View view, Object data,
String textRepresentation) {
// TODO Auto-generated method stub
if(view instanceof ImageView){
((ImageView) view).setImageDrawable((Drawable) data);
}
return false;
}
};
}
EDIT: code
This shows the text for appName and the arrow icon on imageview, BUT it doenst show the drawable i have inserted in the simple adapter?
See this commented line:
//hm.put("image", drawable);
What am I doing wrong?

There are may ways to do that, but first of all, your fragment layout should have a ListView.
Screen Layout
ListFragment has a default layout that consists of a single list view. However, if you desire, you can customize the fragment layout by returning your own view hierarchy from onCreateView(LayoutInflater, ViewGroup, Bundle). To do this, your view hierarchy must contain a ListView object with the id "#android:id/list" (or list if it's in code)
Optionally, your view hierarchy can contain another view object of any type to display when the list view is empty. This "empty list" notifier must have an id "android:empty". Note that when an empty view is present, the list view will be hidden when there is no data to display. Android Documentation
As you are using a SherlockListFragment your layout must have ListView with a predefined android:id=#android:id/list
Row Layout
You can specify the layout of individual rows in the list. You do this by specifying a layout resource in the ListAdapter object hosted by the fragment (the ListAdapter binds the ListView to the data; more on this later).
A ListAdapter constructor takes a parameter that specifies a layout resource for each row. It also has two additional parameters that let you specify which data field to associate with which object in the row layout resource. These two parameters are typically parallel arrays. Android Documentation
You must define the row layout using a separate xml or build it dynamic for
each row. This first option is more commom.
As #Johannes said for SimpleAdapter you must have only TextView. Here you can se a example with custom layout using only TextView. So you have to use/extends another ListAdapter, for instance a ArrayAdapter or even a BaseAdapter.
The most important thing about it is the method getView, which is the method responsible to
return the view which will be put on each line of your ListView. In this method, you will must inflate you row layout and fill it.
This link show a complex custom layout example using BaseAdapter. You can take a look at this link that show basic custom layout is is better to understand what exactly you have to do.

From http://developer.android.com/reference/android/widget/SimpleAdapter.html#SimpleAdapter
For Parameter to (the last one, your imageView1 and textView1:
The views that should display column in the "from" parameter. These should all be TextViews. The first N views in this list are given the
values of the first N columns in the from parameter.

I have solved my problem now. Thanks for the help.
With the use of http://android-er.blogspot.dk/2012/03/display-video-thumbnail-on-listfragment.html I have created a row.xml layout file and a custom cursor adapter as follows:
Cursor adapter
public class MyCursorAdapter extends SimpleCursorAdapter{
public MyCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to){
super(context, layout, c, from, to);
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
LayoutInflater inflater = getSherlockActivity().getLayoutInflater();
View row = inflater.inflate(R.layout.row, parent, false);
TextView text1 = (TextView)row.findViewById(R.id.text1);
TextView text2 = (TextView)row.findViewById(R.id.text2);
ImageView image1 = (ImageView)row.findViewById(R.id.image1);
Cursor cursor = adapter.getCursor();
cursor.moveToPosition(position);
try {
info = pk.getApplicationInfo(cursor.getString(cursor.getColumnIndex(PACKAGE_COL)), 0);
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String title = (String) pk.getApplicationLabel(info);
text1.setText(title);
String duration = cursor.getString(cursor.getColumnIndex(DUR_COL));
text2.setText("App open for " + duration + " seconds");
BitmapFactory.Options options = new BitmapFactory.Options();
options.inDither = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Drawable d = info.loadIcon(pk);
image1.setImageDrawable(d);
return row;
}
}
Layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/image1"
android:layout_width="75dp"
android:layout_height="75dp"
android:src="#drawable/ic_launcher"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/text1"
android:textSize="22dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/text2"
android:textSize="18dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
<ImageView
android:id="#+id/image2"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="#drawable/arrow"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
/>
</RelativeLayout>

Related

DB results into a ListView, data may vary

Hi a bit new to java/android programming, I am trying to populate a listview from a database. The problem is the database output for each record may have varying results. To give you an idea I have the following layout in my xml for the listview;
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#a28d7a">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/coreHeader"
android:textColor="#ffffff"
android:padding="4dp" />
<LinearLayout
android:id="#+id/coreLinear"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Small Text"
android:id="#+id/coreStatsLeft"
android:textColor="#ffffff" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Small Text"
android:id="#+id/textView"
android:textColor="#ffffff"
android:textAlignment="textEnd"
android:gravity="right" />
</LinearLayout>
</LinearLayout>
The first TextView is the header of sorts, bigger font, etc.. in this area it will hold two fields from the database, the NAME and the LEVEL e.g; SPIDER-MAN (Lvl 5).
The two textfields below it will hold the stats, this area can have more than one for example;
Name Value
------------------------------------
Armor 10%
Speed 5%
... and so on
Each record can be different, some may not have speed, some may not have armor... Maybe this is too difficult to do via ListView, but I need it to be searchable and I do not know what other options I have available for this.
My database fields are as follows:
Id, Name, Level, Stats
an example of the populated db would read;
1, Spider-Man, 5, 3|10%;5|5%;6|3%
I created a example to show how to add variable data to each row in a listview.
This is the Activity implementation:
public class MainActivity extends AppCompatActivity
{
private DynamicAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Simulating variable data per row. Array Adapter instead Cursor Adapter for simplicity
final DataRow[] data =
{
new DataRow("Spider Man", new String[] {"3|10%", "5|25%"}),
new DataRow("Spider Man Brother", new String[] {"3|20%"}),
new DataRow("Other Spider Man", new String[] {"3|22%", "1|12%", "4|7%"})
};
// Assign data to adapter
adapter = new DynamicAdapter(this, data);
// Getting reference to ListView
ListView listViewData = (ListView) findViewById(R.id.listViewData);
// Setting adapter to listView
listViewData.setAdapter(adapter);
}
}
This is how the Adapter will put the data for each row:
public class DynamicAdapter extends ArrayAdapter<DataRow>
{
private final Context context;
private final DataRow[] data;
public DynamicAdapter(Context context, DataRow[] data)
{
super(context, R.layout.row_layout, data);
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.row_layout, parent, false);
// Get a listview reference
LinearLayout linearLayoutRow = (LinearLayout) rowView.findViewById(R.id.coreLinear);
if(position < data.length)
{
// Put text on header
TextView textHeader = (TextView) rowView.findViewById(R.id.coreHeader);
// Set the header for this row
textHeader.setText(data[position].GetHeader());
// Creating a vertical linear layout to put the data row
LinearLayout linearLayoutData = new LinearLayout(context);
linearLayoutData.setOrientation(LinearLayout.VERTICAL);
// Get column amount for this row.
int columnAmount = data[position].GetColumnsSize();
for(int i = 0; i < columnAmount; i++)
{
// Creating dynamically a TextView for this column.
TextView dynamicData = new TextView(context);
dynamicData.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT));
// Adding data to TextView
dynamicData.setText(data[position].GetDataAt(i));
// Adding TextView to linearLayout
linearLayoutData.addView(dynamicData);
}
// Adding LinearLayout to LinearLayout on XML
linearLayoutRow.addView(linearLayoutData);
}
return rowView;
}
}
This is the full demo on Github: https://github.com/deinier/DynamicDataOnListView
I hope this help.

Setting TextView visible(or gone) in ListView

I am tying to set a textview inside my ListView visible depending on another variable. But when I try
TextView sdate;
TextView stime;
sdate= (TextView) findViewById(R.id.date);
stime= (TextView) findViewById(R.id.time);
It seems like it can't find the 2 in the layout?
From what I gather, there needs to be something in front of the findViewbyId() but I'm not sure on what. The items layout in the list is done by list_item.xml. The code that is handling all this is:
ListAdapter adapter;
if(add.equals("Event")){
stime.setVisibility(View.VISIBLE);
sdate.setVisibility(View.VISIBLE);
adapter = new SimpleAdapter(
AllSpotsActivity.this, spotsList,
R.layout.list_item, new String[] { TAG_PID,
TAG_NAME, "sdistance","dateof","timeof" }, new int[] {
R.id.pid, R.id.name, R.id.distance, R.id.date, R.id.time});
}else{
adapter = new SimpleAdapter(
AllSpotsActivity.this, spotsList,
R.layout.list_item, new String[] { TAG_PID,
TAG_NAME, "sdistance" }, new int[] {
R.id.pid, R.id.name, R.id.distance });
}
Thank you in advance,
Tyler
EDIT:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#drawable/gradient_background"
>
<!-- Product id (pid) - will be HIDDEN - used to pass to other activity -->
<TextView
android:id="#+id/pid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone" />
<!-- Name Label -->
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="6dip"
android:paddingLeft="6dip"
android:textSize="17dip"
android:textStyle="bold" />
<!-- Name Label -->
<TextView
android:id="#+id/distance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:paddingRight="6dip"/>
<TextView
android:id="#+id/date"
android:layout_below="#id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="12dip"
android:visibility="gone"/>
<TextView
android:id="#+id/time"
android:layout_below="#id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:paddingRight="6dip"
android:visibility="gone"/>
</RelativeLayout>
EDIT 2:
I've also tried using lv.findViewById() because lv=getListView(); But that did not work either.
I think you should call findViewById() on each row's view. For example, if you are calling that method from the getView() method of your adapter, you should use convertView.findViewById.
If you want to have anything more than a simple TextView as the layout for each item in a ListView, what you'll need to do is create a custom adapter that extends ArrayAdapter. Inside of the getView() method of your custom adapter, you will have access to your custom xml layout (one of the arguments to the constructor of the ArrayAdapter is the resource ID of the layout file you want to have for each item in the list [e.g., R.layout.your_custom_list_item]). From inside of that method, you will have access to either a new or recycled view, which you can inflate your custom layout within.
The LayoutInflater.inflate() method you call from inside the getView() method will return you a view that you can call findViewById() on to get access to all the views in your custom layout that you want to interact with. It's there that you can make your views visible or invisible based on the data you pass into the adapter (the third argument to the adapter's constructor is either a list or an adapter with the data you want to use to populate the views). I strongly recommend you watch the I/O video on ListViews for a more complete explanation. I've also included some sample code for a custom adapter below.
public class BookingSearchResultsAdapter extends ArrayAdapter<SearchResult> {
private static final String TAG = BookingSearchResultsAdapter.class.getName();
private int mLayoutResourceId;
private Context mContext;
private List<SearchResult> mResults = null;
public BookingSearchResultsAdapter(Context context, int resource, List<SearchResult> results) {
super(context, resource, results);
mContext = context;
mLayoutResourceId = resource;
mResults = results;
}
/**
* #return A view to display search result
*/
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
SearchResultVendorViewHolder holder = null;
// if there is no recycled view available
if(row == null) {
Log.d(TAG, "No recyclable custom view found. New view created.");
// get a new search result view
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
row = inflater.inflate(mLayoutResourceId, parent, false);
// store all static view information in a holder
holder = new SearchResultVendorViewHolder();
holder.imgIcon = (ImageView) row.findViewById(R.id.search_result_establishment_icon);
holder.txtTitle = (TextView) row.findViewById(R.id.search_result_establishment_name);
holder.txtDescription = (TextView) row.findViewById(R.id.search_result_establishment_description);
// attach the holder to the view so that it can be recycled
row.setTag(holder);
}
else {
Log.d(TAG, "View recycled");
// get the recycled view (stored in tag)
holder = (SearchResultVendorViewHolder)row.getTag();
}
// initialize data in custom search result view
SearchResult result = (SearchResult) mResults.get(position);
holder.txtTitle.setText(result.getEstablishmentName());
holder.imgIcon.setImageResource(result.getImageId());
holder.txtDescription.setText(result.getDescription());
Log.d(TAG, "Custom search view data initialized");
return row;
}
static class SearchResultVendorViewHolder {
ImageView imgIcon;
TextView txtTitle;
TextView txtDescription;
}
}

Why is my custom SimpleCursorAdapter returning different reults when ListView is scrolling

I'm trying to implement a custom SimpleCursorAdapter in order to switch out layouts in a ListView but I'm getting very random results while scrolling.
My issue here is that when I scroll up and down, the ListView seemingly by random, mix up the layouts. For instance, a row can have the listview_item_row layout at first but when scrolling in and out of the screen it can be replaced by listview_item_reply_row and back again.
I can't say I've really understood how newView works. I have successfully been able to use bindView to determine if I'm to hide an image in the layout or not but new View is veiled in darkness to me about its implementation and why the list scrolling behaves the way it does.
My goal is to have a list with x amount of items. Depending on if the item is a reply or a new message I want to load a specific layout on that row. Depending on if the row has an image or not I want to show/hide the imageview in the row layout.
What I have omitted in the code are the imports and row layouts. I'm trying to implement this by using Fragments and SimpleCursorAdapter in the v4 support package. The row layouts for the ListFragment are visibly different but contain the same widgets.
The ListView layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/text_feed_header_random"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:padding="4dp"
android:text="Allmänt"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#FFF" />
<!--
The frame layout is here since we will be showing either
the empty view or the list view.
-->
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#id/text_feed_header_random"
android:layout_above="#+id/footer" >
<!--
Here is the list. Since we are using a ListActivity, we
have to call it "#android:id/list" so ListActivity will
find it
-->
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:drawSelectorOnTop="false" />
<!-- Here is the view to show if the list is emtpy -->
<TextView
android:id="#android:id/empty"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="No items."
android:textAppearance="?android:attr/textAppearanceMedium" />
</FrameLayout>
<LinearLayout
android:id="#+id/footer"
style="#android:style/ButtonBar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal" >
<Button
android:id="#+id/button_random_post"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Gör ett inlägg!" />
<Button
android:id="#+id/button_random_refresh"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Refresh list!" />
</LinearLayout>
</RelativeLayout>
A condensed Fragment using the layout above:
public class RandomFragment extends ListFragment implements LOG {
private DatabaseHelper mDbHelper;
private KarenfeedCursorAdapter mAdapter;
private Cursor mCursor;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "RANDOMFRAGMENT START!");
mDbHelper = new DatabaseHelper(getActivity());
mDbHelper.open();
mDbHelper.setTable(Posts.TABLE_RANDOM_POSTS);
//TODO: Replace SimpleCursorAdapter with a FragmentList instead...
mCursor = mDbHelper.getAllPostsSortedCursor();
String[] columns = { Posts.COLUMN_ID, Posts.COLUMN_CREATED, Posts.COLUMN_USER, Posts.COLUMN_COMMENT };
int[] to = { R.id.imageItemPhoto, R.id.textItemDate, R.id.textItemUser, R.id.textItemComment };
int flags = 0;
mAdapter = new FeedCursorAdapter(getActivity(), R.layout.listview_item_row, mCursor, columns, to, flags);
this.setListAdapter(mAdapter);
initFeedList(); // This call in the end executes mCursor = mDbHelper.getAllPostsSorted(); mAdapter.changeCursor(mCursor); mAdapter.notifyDataSetChanged();
}
}
The SimpleCursorAdapter that the ListFragment connects to:
public class FeedCursorAdapter extends SimpleCursorAdapter implements LOG {
private Context mContext;
private int mLayout;
public FeedCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
super(context, layout, c, from, to, flags);
// TODO Auto-generated constructor stub
mContext = context;
mLayout = layout;
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(context);
View view;
int id = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_ID));
int parentId = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_PARENT_ID));
Log.d(TAG, "id: " +id+ " parentId: " +parentId);
int hasImage = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_IMAGE));
if(id == parentId) {
view = inflater.inflate(R.layout.listview_item_row, parent, false);
} else {
view = inflater.inflate(R.layout.listview_item_reply_row, parent, false);
}
return view;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
Log.d(TAG, "bindView()");
int id = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_ID));
int parentId = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_PARENT_ID));
int hasImage = cursor.getInt(cursor.getColumnIndex(Posts.COLUMN_IMAGE));
String date = cursor.getString(cursor.getColumnIndex(Posts.COLUMN_CREATED));
String user = cursor.getString(cursor.getColumnIndex(Posts.COLUMN_USER));
String comment = cursor.getString(cursor.getColumnIndex(Posts.COLUMN_COMMENT));
TextView dateView = (TextView) view.findViewById(R.id.textItemDate);
TextView userView = (TextView) view.findViewById(R.id.textItemUser);
TextView commentView = (TextView) view.findViewById(R.id.textItemComment);
ImageView imageView = (ImageView) view.findViewById(R.id.imageItemPhoto);
dateView.setText(date);
userView.setText(user);
commentView.setText(comment);
if(hasImage == 0) {
imageView.setVisibility(ImageView.GONE);
} else {
String bitmapPath = Environment.getExternalStorageDirectory().getPath() + "/feed/" + id + "_thumb.jpg";
Bitmap bitmap = BitmapFactory.decodeFile(bitmapPath);
BitmapDrawable bitmapDrawable = new BitmapDrawable(bitmap);
imageView.setImageDrawable(bitmapDrawable);
imageView.setVisibility(ImageView.VISIBLE);
}
}
}
after reading your question and the code i think you should know that whenever you scroll a listview up or down it communicates with the adapter to populate the new items that came in to focus and for the case of different row for different data you should make a arraylist that will contain the name or id of the items whose backgrounds are different and then you start making there background according to your need on every call to adapter.

Android set color to a listview item

I'm using a list view in my application which I'm populating from database. The things that I want to do is depending on some calculations to set the single list view item's text color to red for example. Is there any way to do that?
Here is how I'm populating the listview :
Cursor cursor = dbHelper.executeSQLQuery(sql);
if(cursor.getCount()==0){
Log.i("Cursor Null","CURSOR IS NULL");
nocards.setVisibility(View.VISIBLE);
} else if(cursor.getCount()>0){
nocards.setVisibility(View.GONE);
for(cursor.move(0); cursor.moveToNext(); cursor.isAfterLast()) {
text = cursor.getString(cursor.getColumnIndex("Title"));
Log.i("Show Title","Show Title : "+text);
collId = Integer.parseInt(cursor.getString(cursor.getColumnIndex("CollID")));
Log.i("CollId","Collection ID : "+collId);
if (isLoggedIn) {
for(int k=0; k<ObjectID.size(); k++){
if (ObjectID.get(k) == collId){
cardsCount = OwnedCardsCount.get(k);
}
}
} else {
cardsCount = cursor.getString(cursor.getColumnIndex("TotalCards"));
}
String sqlite2 = "SELECT media_id FROM collection_media WHERE collection_id="+collId+" AND media_type_id="+fronImage;
Cursor bg = dbHelper.executeSQLQuery(sqlite2);
if (bg.getCount() == 0) {
bg.close();
} else if (bg.getCount() > 0) {
for (bg.move(0); bg.moveToNext(); bg.isAfterLast()) {
int mediId = Integer.parseInt(bg.getString(bg.getColumnIndex("media_id")));
Log.i("","mediId : " + mediId);
//if(storageID==1){
path = rpc.getPublicPathsInternal(servername, fronImage, mediId, Recommended.this);
/*} else if(storageID==2){
path = rpc.getPublicPathsExternal(servername, fronImage, mediId);
}*/
Log.v("","path: "+path);
}
}
array.add(collId);
hm = new HashMap<String, Object>();
hm.put(IMAGE, path);
hm.put(TITLE, text);
hm.put(CARDS_COUNT, cardsCount +" Stampii");
items.add(hm);
}
}
final SimpleAdapter adapter = new SimpleAdapter(this, items, R.layout.main_listview,
new String[]{TITLE, CARDS_COUNT, IMAGE}, new int[]{ R.id.main_name, R.id.main_info, R.id.main_img});
lv1.setAdapter(adapter);
lv1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> a, View v, int position, long id)
{
Intent previewMessage = new Intent(Recommended.this, MyCollectionId.class);
TabGroupActivity parentActivity = (TabGroupActivity)getParent();
previewMessage.putExtra("collection_id", array.get(position));
previewMessage.putExtra("opentype", 1);
parentActivity.startChildActivity("MyCollectionId", previewMessage);
}
});
and my main_listview.xml's code :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:orientation="horizontal"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="fill_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/main_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_margin="4dp"/>
<TextView
android:id="#+id/main_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="14dp"
android:textColor="#000000"
android:textStyle="bold"
android:layout_toRightOf="#+id/main_img"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"/>
<TextView
android:id="#+id/main_info"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/main_name"
android:layout_toRightOf="#+id/main_img"
android:textSize="12dp"
android:textColor="#666666"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"/>
<ImageView
android:id="#+id/arrow"
android:src="#drawable/ic_arrow_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:layout_centerVertical="true" />
</RelativeLayout>
</LinearLayout>
So I want to set the textColor of main_name to red. Any suggestions?
You need class like this:
public class StillSimpleAdapter extends SimpleAdapter {
public StillSimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) {
super(context, data, resource, from, to);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
if (timeForRed(position)) ((TextView) view.findViewById(R.id.main_name)).setTextColor(0xffff0000);
return view;
}
}
Use it instead of SimpleAdapter in your code and implement timeForRed() method somewhere and will be happy.
Create an XML for a single list item. Then create your own adapter which overrides getView() function. In this function inflate the list item layout, populate controls from the data and set your textview color as you wish.
Use Custom List Adapter
Custom Android ListAdapter
OR
Android Lists: ListActivity and ListView CustomAdapter
May this help you...Enjoy
You can make a class which extends the BaseAdapter class. The BaseAdapter class provides you some override method; the getView() is one of them — in this method you can customize your views as you want.
Below is the sample project from this; you can get the idea:
https://ujjwal.opendrive.com/files?51477570_t4x6y

Not able to get the clicked row number in list view of android

I am trying to build a simple sms app for which edit page lists all the saved smses. I gave 2 buttons in my layout for Edit and Delete but when I am clicking on them I am unable to get the rowid (row number from top) to retrieve the sms corresponding to that particular row.. Somebody please help me..my sms adapter is not not extending anything..Here's my class and xml files..
public class SMSEdit extends ListActivity{
private SMSDbAdapter mDbHelper;
//private Button editsmsbtn, deletesmsbtn;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.editsmslist);
mDbHelper = new SMSDbAdapter(this);
mDbHelper.open();
fillData();
}
public void fillData() {
Cursor smsCursor = mDbHelper.fetchAllNotes();
startManagingCursor(smsCursor);
// Create an array to specify the fields we want to display in the list (only TITLE)
String[] from = new String[]{SMSDbAdapter.KEY_TITLE,
SMSDbAdapter.KEY_BODY,
SMSDbAdapter.KEY_DATE,
SMSDbAdapter.KEY_TIME};
// and an array of the fields we want to bind those fields to (in this case just text1)
int[] to = new int[]{R.id.smseditlistTO,
R.id.smseditlistMessage,
R.id.smseditlistDay,
R.id.smseditlistTime};
// Now create a simple cursor adapter and set it to display
SimpleCursorAdapter smsadap =
new SimpleCursorAdapter(this, R.layout.smsrow, smsCursor, from, to);
setListAdapter(smsadap);
}
public void myEditClickHandler(View v)
{
//get the row the clicked button is in
LinearLayout vwParentRow = (LinearLayout)v.getParent();
Button btnChild = (Button)vwParentRow.getChildAt(4);
btnChild.setText("I've been clicked!");
ListAdapter pos = getListAdapter();
Intent intent = new Intent();
intent.setClass(SMSEdit.this, SMS.class);
// intent.putExtra(SMSDbAdapter.KEY_ROWID, id);
startActivity(intent);
finish();
}
public void myDeleteClickHandler(View v)
{
//get the row the clicked button is in
LinearLayout vwParentRow = (LinearLayout)v.getParent();
//TextView child = (TextView)vwParentRow.getChildAt(0);
Button btnChild = (Button)vwParentRow.getChildAt(5);
//btnChild.setText(child.getText());
btnChild.setText("I've been clicked!");
int c = Color.CYAN;
vwParentRow.setBackgroundColor(c);
vwParentRow.refreshDrawableState();
}
}
editsmslist.xml -- >>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ListView android:id="#+id/android:list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView android:id="#+id/android:empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No Future SMS Yet" android:textSize="35px"/>
</LinearLayout>
smsrow.xml -- >>
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
android:id="#+id/ScrollView01"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:id="#+id/LinearLayout02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout android:id="#+id/LinearLayout03" android:layout_width="wrap_content" android:layout_height="wrap_content">
<TextView android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="#string/smsdetailseditlist" android:id="#+id/smseditlistTO" android:paddingLeft="5px">
</TextView>
<TextView android:layout_height="wrap_content" android:text="#string/smsdetailseditlist" android:id="#+id/smseditlistMessage" android:paddingLeft="20px" android:maxLines="1" android:layout_width="wrap_content">
</TextView>
</LinearLayout>
<LinearLayout android:id="#+id/LinearLayout01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" android:paddingLeft="5px">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Date: "></TextView><TextView android:text="#string/smsdetailseditlist" android:id="#+id/smseditlistDay" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Time: " android:paddingLeft="5px"> </TextView><TextView android:text="#string/smsdetailseditlist" android:id="#+id/smseditlistTime" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingRight="10px"></TextView>
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="#+id/EditSMSButton" android:text="#string/editsms" android:onClick="#string/myEditClickHandler"></Button>
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="#+id/DeleteSMSButton" android:text="#string/deletesms" android:onClick="#string/myDeleteClickHandler"></Button>
</LinearLayout>
</LinearLayout>
</ScrollView>
Also Please suggest if there'a yn better way to implement this or make the layout look better...
You can extend a cursorAdapter like this...
public class exampleAdapter extends CursorAdapter
{
LayoutInflater inflater;
public exampleAdapter (Context context, Cursor c) {
super(context, c);
inflater = LayoutInflater.from(context);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
// TODO Auto-generated method stub
Button btn_del = (Button)view.findViewById(R.id.button1);
btn_del.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
SMSDbAdapter vb = new SMSDbAdapter(context);
vb.open();
String xyz = cursor.getString(0); //Persumably your ID
vb.Delete(Integer.parseInt(cursor.getString(0)));
Toast.makeText(context, xyz + " Deleted!", Toast.LENGTH_SHORT).show();
vb.close();
}
});
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return inflater.inflate(R.layout.smsrow, parent, false);
}
}
I had a similar problem with my ListView.
Assume you are filling a ListView dynamically. You have 5 rows (for example). The id of first row is 1 second is 2 and so on.
When you scroll whatever rows are visible to you, the id of the 1st row (that you currently see on screen) will always be 1. You need to control that by using mabye some another class (XYZ).
I simply used ArrayList<XYZ> and that worked.
You can override this method in your SMSAdapter:
public View getView(int position, View convertView, ViewGroup parent)
and then call the get(position) method that returns an ArrayList<XYZ>.
You should use ListView to display your messages.
Store the data retrieved from database in a Array of Strings say s1.
Then
private ArrayList<String> arr_sort = new ArrayList<String>();
And copy whole s1 into arr_sort by using add() method.
While setting adapter
lv.setAdapter(new ArrayAdapter<String>(DataAttach.this,
android.R.layout.simple_list_item_1, arr_sort));
where lv is the ListView refernce.
Then use this method for onClick
lv.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String item = (String) lv.getItemAtPosition(position);
Toast.makeText(*.this,
"You selected - " + item + " ,Please wait...",
Toast.LENGTH_LONG).show();
Intent intent = new Intent(*.this, *.class);
*.this.startActivity(intent);
}
});
Hope this helps..

Categories

Resources