How to implement a table layout inside a list view - android

I want to implement a layout which resembles Bank's PassBook. So I thought should I implement table layout inside a list view.
Here is a sample passbook example.
DATE PARTICULARS DEBIT CREDIT BALANCE
12/06/2014 Withdraw 200 10000
11/06/2014 Deposit 200 10200

create xml layout like below
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="horizontal"
android:weightSum="3">
<TextView
android:id="#+id/date"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="#string/hello_world" />
<TextView
android:id="#+id/action_type"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/hello_world"
android:gravity="center"
android:layout_weight="1"/>
<TextView
android:id="#+id/amount"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/hello_world"
android:gravity="center"
android:layout_weight="1"/>
</LinearLayout>
use this layout as list item for your ListView.

Use an ArrayAdapter for your ListView.
In there, you can inflate the Layout for the items of the list, be it a TableLayout, or something other.
private class MyListAdapter extends ArrayAdapter<SomeObject> {
public MyListAdapter(Context context, int resource, List<SomeObject> someObjectList) {
super(context, resource, someObjectList);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
//view recycling
if (convertView == null) {
// inflate the single row with whatever layout you like
view = getLayoutInflater().inflate(R.layout.table_row, parent, false);
} else {
view = convertView;
}
SomeObject item = getItem(position);
//fill the view with data
TextView date = (TextView) view.findViewById(R.id.date);
date.setText(item.getDate());
...
return view;
}
...
}
Here's a little to read about ListViews and ArrayAdapter:
https://github.com/thecodepath/android_guides/wiki/Using-an-ArrayAdapter-with-ListView1

Related

Why is my listview not expanding to accommodate a larger row size?

I have a listview that I want the user to be able to delete items from. If the user holds on a row long enough, the row's checkbox is made visible. However, the listview doesn't grow to accommodate the (now taller) row despite there being plenty of space. I had this issue before when the listview was in a scrollview but that's no longer the case. I understand I can reformat the text as a bandage solution, but I want to understand what is happening.
Here is the listview before and after the first entry is held. You can see the listview's height stays the same and doesn't expand to accommodate the two entries:
Here is the listView:
<ListView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Here is the listView item layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns="https://"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<CheckBox
android:id="#+id/deleteCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone" />
<TextView
android:id="#+id/number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingLeft="5dp"
android:textColor="#android:color/black"
android:textSize="18sp" />
<TextView
android:id="#+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="right"
android:paddingRight="5dp"
android:textColor="#android:color/darker_gray"
android:textSize="18sp" />
</LinearLayout>
Here is how the layout is being inflated in my custom adapter:
public class CustomAdapter extends ArrayAdapter<CustomlistEntry> {
public CustomAdapter(Context context, ArrayList<CustomlistEntry> entries) {
super(context, 0, entries);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.activity_custom_listview, parent, false);
}
CustomlistEntry entry = getItem(position);
TextView tvNumber = convertView.findViewById(R.id.number);
TextView tvDate = convertView.findViewById(R.id.date);
tvNumber.setText(entry.getNumber());
tvDate.setText(entry.getDateString());
return convertView;
}
}
and finally the adapter being set:
CustomAdapter adapter = new CustomAdapter(App.getApp(), arrayListSorted);
final ListView listView = activity.findViewById(R.id.listView);
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
final int pos, long id) {
arg1.findViewById(R.id.deleteCheckBox).setVisibility(View.VISIBLE);
CustomAdapter adapter = (CustomAdapter)listView.getAdapter();
return true;
}
});
listView.setAdapter(adapter);

Android development : Listview with android:onclick attribute on item

I'm beginner in android development and i a have question about Listview and android:onclick attribute.
I try to use attribute android:onclick ="myMethod" on each element of my listview instead of define OnItemClickListener/onItemClick (too much verbose for me)
MyMethod is executed but how can i get clicked element (current context) ?
Thanks in advance
As a beginner, setting an OnItemClickListener might seem a bit scary, but it's really not a big deal at all (and a core concept you should be learning anyway!).
So if you have a simple layout with a ListView in it like this...
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/containerView"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="#+id/myListview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
You can set up an OnItemClickListener with just this code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_listview_layout);
listView = (ListView)findViewById(R.id.myListview);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Every time an item is clicked, you can handle it right here.
}
});
}
So every time an item in your list is clicked, the onItemClick method is fired, and you can figure out which item was clicked by using the int position argument that comes in.
If i am right your question is about implementing on click listener on each listrow item instead of list row.
If that is correct this is how you should implement:
1.In your adapter of getView() method you might be inflating a layout for list row like below:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_row_layout, parent, false);
return convertView;
}
In the above code list_row_layout is the xml file i'm inflating.
Go to that layout and add the following line android:descendantFocusability="blocksDescendants" to the root level of the xml layout like below:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_margin="4dp"
android:descendantFocusability="blocksDescendants"<!--This is the line i'm talking about-->
android:background="#drawable/rounded_border_layout"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="vertical"
android:layout_width="40dp"
android:layout_marginRight="10dp"
android:id="#+id/review_main_user_image_layout"
android:layout_marginLeft="10dp"
android:layout_height="54dp">
<ImageView
android:layout_width="40dp"
android:id="#+id/review_main_user_image"
android:background="#drawable/reviews_x_trail_user_image_border"
android:layout_height="40dp"
android:src="#drawable/ic_help_user" />
<TextView
android:typeface="monospace"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Me"
android:textSize="10sp"
android:layout_gravity="center"
android:singleLine="true"
android:id="#+id/review_main_user_name"
android:layout_below="#+id/review_main_user_image" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/review_main_user_image_layout"
android:layout_toEndOf="#+id/review_main_user_image_layout">
<TextView
android:layout_marginLeft="8dp"
android:layout_width="wrap_content"
android:textColor="#color/black"
android:layout_height="wrap_content"
android:singleLine="true"
android:id="#+id/review_main_title"
android:text="Good Product For The Price"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:orientation="horizontal">
<RatingBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/review_main_rating"
android:progressDrawable="#drawable/apptheme_ratingbar_small_holo_light"
android:numStars="5"
style="?android:attr/ratingBarStyleSmall" />
<TextView
android:layout_marginLeft="8dp"
android:text="12-Jun-1993"
android:id="#+id/review_main_date"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
That't it now in your adapter getView method you can implement on click listener for each widget you have in that layout.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ReviewsXTrailViewHolder reviewsXTrailViewHolder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_row_review_main, parent, false);
TextView title = (TextView)convertView.findViewById(R.id.review_main_user_image);
//title.setOnclickListener()
return convertView;
}
In that above code i have added on click listener for textview.I hope it will work
Comment below if that doesn't work

Custom Spinner with default down arrow in it

I have a custom layout for spinner. Its both selected and dropdown list item's background color will change depending on user demand. So i am changing depending on their values.. so far so good. But the problem is since i am using custom layout or changing background color, there is no arrow to show that it is a spinner. When i add arrow from layout then all even dropdown list have that arrow with them. I can manipulate it by setting arrow's background to null for drop down items but it is not a good way and dont always work. So how can i show spinner default arrow with my custom spinner without using spinner style. Dont forget that i am changing background of every item.
Here is my custom_spinner.xml
<?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:weightSum="6" android:id="#+id/spinnerMainLayout"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal" android:layout_width="match_parent"
android:weightSum="14"
android:layout_height="wrap_content">
<TextView
android:layout_width="0dp" android:layout_marginTop="8dp"
android:layout_height="wrap_content" android:layout_marginLeft="10dp"
android:text="New Text" android:textSize="19sp" android:layout_weight="5"
android:layout_gravity="center" android:layout_marginBottom="8dp"
android:gravity="center" android:layout_marginRight="4dp"
android:id="#+id/type" android:typeface="serif"/>
<View
android:layout_width="1dp" android:layout_marginLeft="8dp" android:layout_marginTop="4dp"
android:layout_height="match_parent" android:layout_marginBottom="4dp"
android:background="#666666" />
<TextView
android:layout_width="0dp" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_weight="9"
android:typeface="serif" android:maxLines="3" android:minLines="2"
android:layout_gravity="center" android:layout_marginBottom="8dp"
android:layout_marginLeft="10dp" android:layout_marginRight="5dp"
android:text="sd" android:textSize="18sp" android:gravity="center_vertical"
android:id="#+id/history" />
</LinearLayout>
</LinearLayout>
and here is my custom spinner class
class CustomSpinner extends ArrayAdapter<String> {
private String[] fixStrs = new String[]{"Definition","Result","Error"};
public CustomSpinner(Context ctx, int txtViewResourceId, String[] objects) {
super(ctx, txtViewResourceId, objects);
//fixStrs = objects;
}
#Override public View getDropDownView(int position, View cnvtView, ViewGroup prnt) {
return getCustomView(position, cnvtView, prnt);
}
#Override public View getView(int pos, View cnvtView, ViewGroup prnt) {
return getCustomView(pos, cnvtView, prnt);
}
public View getCustomView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View mySpinner = inflater.inflate(R.layout.custom_spinner, parent, false);
/*LinearLayout spinnerMain = (LinearLayout) mySpinner.findViewById(R.id.spinnerMainLayout);
spinnerMain.setBackgroundColor(Color.parseColor(colors[0]));*/
TextView fixText = (TextView) mySpinner.findViewById(R.id.type);
fixText.setText(fixStrs[position]);
fixText.setTextColor(Color.parseColor(colors[1]));
TextView historyText = (TextView) mySpinner.findViewById(R.id.history);
historyText.setText(history[position]);
historyText.setTextColor(Color.parseColor(colors[1]));
return mySpinner;
}
}
Create a different layout for the spinner dropdown and pass it to the .setDropDownViewResource method of the ArrayAdapter, then you must specify the id of the textview in this layout in the constructor call of your adapter

Android ListView not detecting selection

I'm stumped. This one IS simple and I'm missing something simple but I'm just not getting anywhere.
I have a ListView that contains pretty simple items - TextView's that contain text of the form "N. name", where N is the position in the list and name is the name of the associated objects. I've created a ListAdapter that presents that information into the ListView.
The presentation stuff seems to work fine. It's the part where when I tap on a row that's not working. I just don't get a notification. If I set a onClickListener on the item (when it's generated in the Adapter) I do get a notification, but it's convoluted to make that work the way I'd like it to. I've tried a bunch of stuff - changing descendent focusability, enabling, disabling, setting itemsCanFocus to false, ... - but no luck on any of them.
I've included relevant code for configuring the view and the elements in the ListView.
In particular, what I'm trying to do is get that OnItemClickLister.onItemClick() to get invoked when I tap on a row. Any thoughts on what I'm doing wrong?
Activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
model = FZMModel.getInstance(this);
setContentView(R.layout.activity_deploy);
TextView viewTitle = (TextView) findViewById(R.id.deploy_header);
if (model.getProfiles().size() == 0) {
viewTitle.setText(R.string.deploy_header_create);
} else {
viewTitle.setText(R.string.deploy_header_choose);
}
profileListView = (ListView) findViewById(R.id.profileListView);
profileListAdapter = new ProfileListAdapter(this, model);
profileListView.setAdapter(profileListAdapter);
profileListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
Log.d(TAG, String.format("Item %d selected (with id=0x%x)", position, id));
}
});
}
Adapter:
... relevant code from getView():
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final Profile profile = model.getProfileAtIndex(position);
final int rowNum = position;
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.profile_list_layout, parent, false);
}
TextView profileIndexView;
TextView profileNameView;
profileIndexView = (TextView) convertView.findViewById(R.id.profileIndexLabel);
profileNameView = (TextView) convertView.findViewById(R.id.profileNameLabel);
profileIndexView.setText(String.format("%d.", position));
profileNameView.setText(profile.getName());
// convertView.setOnClickListener(new View.OnClickListener() {
// #Override
// public void onClick(View view) {
// Toast.makeText(context, String.format("Did select row #%d (index=%d)",rowNum, profile.getPosition()), Toast.LENGTH_SHORT).show();
// }
// });
return convertView;
}
activity layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.nsn.flexizonemobile.FZMConcreteActionDeploy"
tools:ignore="MergeRootFrame" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="#string/deploy_header_choose"
android:id="#+id/deploy_header"
android:layout_margin="10dp"
android:layout_centerHorizontal="true" />
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/profileListView"
android:layout_gravity="left|top"
android:layout_alignParentLeft="true"
android:layout_marginLeft="0dp"
android:choiceMode="none"
android:layout_below="#+id/deploy_header"
android:divider="#android:color/darker_gray"
android:dividerHeight="2dp"
android:clickable="true"
android:descendantFocusability="beforeDescendants" />
</RelativeLayout>
profile_list_layout layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="#dimen/profile_index_width"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="A. "
android:id="#+id/profileIndexLabel"
android:gravity="center_vertical|right"
android:layout_centerVertical="true"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:textSize="24sp"
android:textIsSelectable="true"
android:layout_alignParentStart="false"
android:layout_alignParentTop="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Profile Name"
android:id="#+id/profileNameLabel"
android:layout_alignParentLeft="false"
android:layout_alignParentTop="false"
android:gravity="center_vertical"
android:layout_toRightOf="#+id/profileIndexLabel"
android:layout_marginLeft="10dp"
android:layout_centerVertical="true"
android:textSize="24sp"
android:paddingTop="10dp"
android:paddingBottom="10dp" />
</RelativeLayout>
in the textview of your inflator layout just add:
android:focusable="false"
android:focusableInTouchMode="false"
and in parent layout of your inflator i.e in relative layout of inflator add:
android:descendantFocusability="blocksDescendants"
remove :
android:descendantFocusability="beforeDescendants"
from your listview. and set height of your listview to match_parent will solve your issue.
remove following attributes from your ListView:
android:choiceMode="none"
android:clickable="true"
android:descendantFocusability="beforeDescendants"
also
android:layout_width="wrap_content"
android:layout_height="wrap_content"
makes no sense in this context (especially height)

Making Listeners for buttons within a ListView

Copying other people's code that I only half understand, I have succeeded in making a listview, each element of which contains three TextViews and a CheckBox.
The code involves the following two xml files. First "customrowview.xml":
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="142dp"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView android:id="#+id/text1"
android:layout_width="match_parent"
android:layout_height="fill_parent"/>
<TextView android:id="#+id/text2"
android:layout_width="match_parent"
android:layout_height="fill_parent"/>
<TextView android:id="#+id/text3"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right" >
<CheckBox
android:id="#+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" />
<Button
android:id="#+id/editbut"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Edit" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
Then "customlistview.xml":
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ListView android:id="#id/android:list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#000fff"
android:layout_weight="2"
android:drawSelectorOnTop="false">
</ListView>
<TextView android:id="#id/android:empty"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFff00"
android:text="No data"
/>
</LinearLayout>
I get access to the list via:
listView = (ListView) findViewById(R.id.mylist);
The code also involves:
SimpleAdapter adapter = new SimpleAdapter(
this,
list,
R.layout.custom_row_view,
new String[] {"label","daysordate","time"},
new int[] {R.id.text1,R.id.text3, R.id.text2}
);
listView.setAdapter(adapter);
Now what I want to do is something like listView.setlistenerforbuttonwithinlist() !
But can not work out how to do it. I know there have been related questions on SO before, but I can not understand the answers :-(
EDIT: After seeing azgolfers answer... I made a custom adapter as follows:
public class myadapter extends SimpleAdapter
{
LayoutInflater mLayoutInflater;
public void myadapter(Context context)
{
mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View view = null;
if (convertView != null)
{
view = convertView;
}
else
{
view = mLayoutInflater.inflate(R.layout.custom_row_view, null);
}
Button buttonEdit = (Button) view.findViewById(R.id.editbut);
buttonEdit.setOnClickListener(new OnClickListener()
{
public void onClick(View arg0)
{
Log.i("xx","Button pressed!");
}
});
return super.getView(position, convertView, parent);
}
public myadapter(Context context, List<? extends Map<String, ?>> data,int resource, String[] from, int[] to)
{
super(context, data, resource, from, to);
// TODO Auto-generated constructor stub
}
}
Unfortunatly this crashes at the line
view = mLayoutInflater.inflate(R.layout.custom_row_view, null);
With a null pointer exception... not sure why :-(
First, you need to extend your own Adapter, probably from an ArrayAdapter. ArrayAdapter has a method called getView that you will need to override and provide the UI for a listview row at a certain position. e.g.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView != null) {
view = convertView;
} else {
view = mLayoutInflater.inflate(R.layout.custom_row_view, null);
}
Button buttonEdit = (Button) view.findViewById(R.id.editbut);
buttonEdit.setOnClickListener(...);
}
In getView(), since you are building the UI of the row, you have a chance here to set the click handler on your button.
Also, you also need to add this to your Button's xml tag:
android:focusable="false"
android:focusableInTouchMode="false"
Without that, button inside a listview will not fire OnClick event when pressed.
try to сhange
view = mLayoutInflater.inflate(R.layout.custom_row_view, null);
to
view = mLayoutInflater.inflate(R.layout.custom_row_view, parent, false);
Good luck!

Categories

Resources