So I have a listview with one textview and I want to add a second textview to it. But I cannot figure out how to modify the adapter and then call it in my main activity, even after looking through many similiar questions on stackoverflow.
Heres how my CustomAdapter.java is now
class CustomAdapter extends ArrayAdapter<CharSequence>{
public CustomAdapter(Context context, CharSequence[] routes) {
super(context, R.layout.custom_row ,routes);
}
#NonNull
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater routeInflater = LayoutInflater.from(getContext());
View customView = convertView;
if(customView == null){customView = routeInflater.inflate(R.layout.custom_row, parent, false);}
CharSequence singleRoute = getItem(position);
TextView routeText = (TextView) customView.findViewById(R.id.routeText);
routeText.setText(singleRoute);
///// Textview I want to add
CharSequence routeNum = getItem(position);
TextView routeNumText = (TextView) customView.findViewById(R.id.numbersTextView);
routeNumText.setText(routeNum);
/////
return customView;
and heres my MainActivity.java
///// fill listview numbers I want to add
final String[] routeListviewNumbers = getResources().getStringArray(R.array.routeNumbers);
//fill list view with xml array of routes
final String[] routeListViewItems = getResources().getStringArray(R.array.routeList);
//custom adapter for list view
ListAdapter routeAdapter = new CustomAdapter(this, routeListViewItems);
final ListView routeListView = (ListView) findViewById(R.id.routeListView);
routeListView.setAdapter(routeAdapter);
any help in how to modify the adapter and then call it in the main activity would be really appreciated. Thank you!
I would recommend creating a custom Route class since this adapter is meant to handle one array. Create some member variables for the route number and route items in the new class with getter and setter methods. Then you should be able to create a new array list of Route objects in your main activity and iterate through the existing string arrays while appending them (as new Route objects) to the new array.
You will have to change the adapter to accept a Route object instead of CharSequence. Hope this points you in the right direction.
I would recommend a custom adapter for you.
Exm..
Create Route Class
class Route{
public int number;
public String text;
}
Base Adapter...
public class myBaseAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private List<Route> mRouteList;
public BilgiAdapter(Activity activity,List<Route> routeList){
mInflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mRouteList = routeList;
}
#Override
public int getCount() {
return mRouteList.size();
}
#Override
public Object getItem(int position) {
return mRouteList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View myView;
myView = mInflater.inflate(R.layout.line_layout,null);
Route r = mRouteList.get(position);
TextView txtRouteNumber = (TextView)myView.findViewById(R.id.textRouteNumber);
TextView txtRouteText = (TextView)myView.findViewById(R.id.textRouteText);
txtRouteNumber.setText(String.ValueOf(r.number));
txtRouteText.setText(String.ValueOf(r.text));
return myView;
}
}
MainActivity vs..
ListView lstRoute;
myBaseAdapter adapter;
List<Route> list;
...
..
..
..
..
OnCreate(..)
..
list = new ArrayList<Route>();
//add routes in list
myBaseAdapter = new myBaseAdapter(MainActivity.this,list);
lstRoute = (ListView)findViewById(R.id.listViewRoute);
lstRoute.setAdapter(myBaseAdapter);
...
..
..
line_layout.xml(Layout file)
<?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">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/textRouteNumber"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/textRouteText"/>
</LinearLayout>
Related
I'm trying to implement button on each row in ListView, but I saw many topics and I don't succeeded to add code to mine. Here is my MainActivity :
public class MainActivity extends AppCompatActivity {
private ArrayAdapter<String> itemsAdapter;
private ArrayList<String> items;
private ImageButton formButton;
private ListView lvMain;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
commonFunction();
}
public void commonFunction() {
lvMain = (ListView) findViewById(R.id.lvMain);
items = new ArrayList<String>();
readItems();
itemsAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
items);
lvMain.setAdapter(itemsAdapter);
formButton = (ImageButton) findViewById(R.id.btnPlus);
formButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setLayoutActivity();
}
});
}
}
Here is my activity_main.xml :
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/lvMain"
android:layout_above="#+id/btnPlus" />
<ImageButton
android:layout_width="match_parent"
android:layout_height="65dp"
android:id="#+id/btnPlus"
android:layout_alignParentBottom="true"
app:srcCompat="#mipmap/ic_plus_foreground" />
Does someone any idea how to do ?
Create custom adapter with custom row layout file and add button on that row file and bind it to List/Recycler view. So it will inflate in all row.
Add below code in row_list.xml file.
<ImageButton
android:layout_width="match_parent"
android:layout_height="65dp"
android:id="#+id/btnPlus"
android:layout_alignParentBottom="true"
app:srcCompat="#mipmap/ic_plus_foreground" />
CustomAdapter.java
public class CustomAdapter extends BaseAdapter {
private ArrayList data;
private static LayoutInflater inflater = null;
/************* CustomAdapter Constructor *****************/
public CustomAdapter(ArrayList d) {
/********** Take passed values **********/
data = d;
/*********** Layout inflater to call external xml layout () ***********/
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
/******** What is the size of Passed Arraylist Size ************/
public int getCount() {
if (data.size() <= 0)
return 1;
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
/********* Create a holder Class to contain inflated xml file elements *********/
public static class ViewHolder {
public ImageButton button;
}
/****** Depends upon data size called for each row , Create each ListView row *****/
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
ViewHolder holder;
if (convertView == null) {
/****** Inflate tabitem.xml file for each row ( Defined below ) *******/
vi = inflater.inflate(R.layout.row_list, null);
/****** View Holder Object to contain tabitem.xml file elements ******/
holder = new ViewHolder();
holder.button = (ImageView) vi.findViewById(R.id.btnPlus);
/************ Set holder with LayoutInflater ************/
vi.setTag(holder);
} else
holder = (ViewHolder) vi.getTag();
holder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Button click
}
});
return vi;
}}
Hope it will solve problem.
Happy coding!!
Crate custom adapter and bind it with the ListView.
Inflate custom layout for each row in the adapter.
You can put your button in the custom layout file.
public class CustomAdapter extends ArrayAdapter<String> {
private Context context;
private int singleRowLayoutId;
public CustomAdapter(Context context, int singleRowLayoutId, String []titles, String []desc, int []images ) {
super(context, singleRowLayoutId,titles);
this.context=context;
this.singleRowLayoutId=singleRowLayoutId; //custom row layout for list view item
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View row=convertView;
CustomViewHolder holder=null;
if(row==null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//view object of single row of list view
row = inflater.inflate(singleRowLayoutId, parent, false);
//by using holder, we make sure that findViewById() is not called every time.
holder=new CustomViewHolder(row);
row.setTag(holder);
}
else
{
holder=(CustomViewHolder)row.getTag();
}
return row;
}
private class CustomViewHolder {
private ImageButton mbtn;
CustomViewHolder(View view)
{
mbtn=(ImageButton)view.findViewById(R.id.btn);
mbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//handle button click here
}
});
}
}
I think that this is what you need - create a separate layout for the rows in the list view. Then create a custom adapter, where you are adding this layout as row layout and then set this adapter to your list view. Here are the details with examples:
Android custom Row Item for ListView
I have a list of a POJO in an Android app and I am currently displaying one of the fields in a listview/listitem like so:
List<NotificationItem> notifItems;
// snip, populate
ArrayAdapter adapter = new ArrayAdapter<>(this, R.layout.notification_item, notifItems);
ListView listView = (ListView) findViewById(R.id.notification_listview);
listView.setAdapter(adapter);
And it is my understanding that the listivew or adapter uses the toString of the POJO, which is
public String toString() {
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd hh:mm");
return _notificationTitle + " | " + dateFormatter.format(_notificationReceivedDate);
}
R.id.notificationitem is
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/label"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dip"
android:textSize="16sp"
android:textStyle="bold"></TextView>
So far so good, but what I want to do is add elements to the notificationitem layout file and then update the Java code to populate the new fields.
How is this done? I don't really understand how the adapter knows/puts the toString value into the one field in the notificationitem.
public class NotificationItem {
//your fields here
}
//-----------------------
public class NotifAdapter extends BaseAdapter {
Context context;
List<NotificationItem> data;
public NotifAdapter(Context context, List<NotificationItem> data) {
this.context = context;
this.data = data;
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.your_row_layout,parent, null);
TextView tx = convertView.findViewById(R.id.your_widget_inside_row_layout);
tx.setText(data.yourDataPropery);
return convertView;
}
}
// In your activity
NotifAdapter adapter = new NotifAdapter(this, ArrayList<NotificationItem>);
listView.setAdapter(adapter);
Here's the code with the problem:
//declarations:
private ArrayAdapter<String> listAdapter;
private ArrayAdapter<String> listAdapter2;
String [] nomi=null;
String[] famiglia=null;
private ListView mainListView;
// other code bla bla bla...
mainListView = (ListView) findViewById(R.id.listView);
// other code bla bla bla...
nomi = new String[res.size()];
for (int i = 0; i < res.size(); i++) {
nomi[i] = res.get(i).getNomignolo();
}
famiglia= new String[res.size()];
for(int i=0; i<res.size();i++){
famiglia[i] = res.get(i).getFamiglia();
}
ArrayList<String> listaNomi = new ArrayList<String>();
listaNomi.addAll(Arrays.asList(nomi));
ArrayList<String> listaFamiglie = new ArrayList<String>();
listaFamiglie.addAll(Arrays.asList(famiglia));
listAdapter = new ArrayAdapter<String>(HomeActivity.this, R.layout.row, R.id.button3, listaNomi);
listAdapter2 = new ArrayAdapter<String>(HomeActivity.this, R.layout.row, R.id.button6, listaFamiglie);
mainListView.setAdapter(listAdapter);
mainListView.setAdapter(listAdapter2);
It works, but only in part, because when i start the app i can find only the result of the second setAdapter method. How can i achieve also the result of all the setAdapter methods? Thanks.
try to add objects of second list in first on
nomi = new String[res.size()];
for (int i = 0; i < res.size(); i++) {
nomi[i] = res.get(i).getNomignolo() + " " +res.get(i).getFamiglia();
}
//list of object with name and family
create adapter
listAdapter = new ArrayAdapter<String>(HomeActivity.this, R.layout.row, R.id.button3, listaNomi);
mainListView.setAdapter(listAdapter);
you cannot set multiple adapter for one listview.
How to create custom array adapter:
public class CustomAdapter extends ArrayAdapter<Person>{
private final Activity context;
private ArrayList<Person> Items;
public CustomAdapter (Activity context, int layout,ArrayList<Person> persons) {
super(context, layout, carriers);
// TODO Auto-generated constructor stub
this.context = context;
this.Items = persons;
}
static class ViewHolder {
public Button name;
public Button family;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
// Recycle existing view if passed as parameter
// This will save memory and time on Android
// This only works if the base layout for all classes are the same
View rowView = convertView;
if (rowView == null) {
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.item, null, true);
holder = new ViewHolder();
holder.name= (TextView) rowView.findViewById(R.id.name);
holder.family= (TextView) rowView.findViewById(R.id.family);
rowView.setTag(holder);
} else {
holder = (ViewHolder) rowView.getTag();
}
holder.name.setText(Items.get(position).getName());
holder.family.setText(Items.get(position).getFamily());
return rowView;
}
}
and create PErson Object:
public class PErson{ public String name; public String family;
public Person();
public String getName(){ return name;}
public String getFamily(){return family;}
}
and this is item xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<Button
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="wkjdhk"
android:textColor="#color/green"
android:textSize="12sp" />
<Button
android:id="#+id/family"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="wkjdhk"
android:textColor="#color/green"
android:textSize="12sp" />
</RelativeLayout>
this is how to call from activity:
adapter = new MyCustomAdapter(CarrierSummaryActivity.this,nomi,R.layout.item);
mainListView.setAdapter(adapter);
Can you please do like this way ?
First List:
ArrayList<String> a = new ArrayList<String>();
a.add("a");
a.add("b");
a.add("c");
Second List:
ArrayList<String> b = new ArrayList<String>();
b.add("d");
b.add("e");
b.add("f");
Add a to b:
b.addAll(a);
Merge both list:
ArrayList<String> union = new ArrayList<String>(a);
union.addAll(b);
Set Adapter on ListView:
listAdapter = new ArrayAdapter<String>(HomeActivity.this, R.layout.row, R.id.button3, union);
mainListView.setAdapter(listAdapter);
Hope this will help you.
This is not possible, whenever you are setting second adapter to listview, your first adapters data get replaced with second.
LISTVIEW CAN DISPLAY SINGLE ADAPTER DATA AT SINGLE TIME.
If you want to display data from multiple sources to ListView then first merge all all data and then use single adapter. Do something like below
dataList1 (From source A)
datalist2 (From source B)
datalist3 = dataList1 + dataList2;
setDapter(dataList3)
You should implement your custom adapter so it can draw the list just like you want.
class MyAdapter extends BaseAdapter
{
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//Here you can return a View with any data in any way
}
}
Hope this helps.
I've searched a lot this but I really did not find what I need exactly.
What I want is :
I have a listview and load it on my main class. I load it like this:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(Main.this,
R.layout.myrow,R.id.text );
if (friends != null) {
for (ParseObject friend : friends) {
adapter.add((String) friend.get("name"));
}
}
setListAdapter(adapter);
and myrow layout xml is here:
< RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center" >
<ProgressBar
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/my_prog"
></ProgressBar>
<TextView
android:id="#+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="25sp" >
</TextView>
</RelativeLayout >
You can see I have progress bar on textview so I need to reach it and set it's visible. I mean sometimes I set it invisible sometimes visible
What I did is:
On my MainActivity on create method the code is here :
ProgressBar my_prog;
my_prog=(ProgressBar)findViewById(R.id.my_prog);
my_prog.setVisibility(View.INVISIBLE);
The error is:
07-16 13:35:39.219: E/AndroidRuntime(29096): java.lang.RuntimeException: Unable to start activity ComponentInfo{....MainActivity}: java.lang.NullPointerException
I think I cant reach my_prog on my main activity but I need it.
How can I do that.
thanks in adnvace...
You need to implement a custom Adapter to do this. I have written this ExampleAdapter to show you how it works, I commented all the important parts:
public class ExampleAdapter extends BaseAdapter {
private final LayoutInflater inflater;
private final List<ParseObject> objects;
private final boolean[] activated;
public ExampleAdapter(Context context, List<ParseObject> objects) {
this.inflater = LayoutInflater.from(context);
this.objects = objects;
this.activated = new boolean[objects.size()];
}
public void showProgressBar(int position, boolean visible) {
this.activated[position] = visible;
notifyDataSetChanged();
}
#Override
public int getCount() {
return this.objects.size();
}
#Override
public ParseObject getItem(int position) {
return this.objects.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// If the convertView is null, we need to inflate a new one
if(convertView == null) {
// We inflate the view with your layout
convertView = inflater.inflate(R.layout.myrow, parent, false);
// Here we create a view holder object which keeps a
// reference to the Views in this row so we have to
// perform the expensive findViewById() only once
ViewHolder holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.my_prog = (ProgressBar) convertView.findViewById(R.id.my_prog);
// The view holder is set as tag to the view so we can access it later
convertView.setTag(holder);
}
// We retrieve the ParseObject for the current position
ParseObject parseObject = getItem(position);
// And get the view holder from the View
ViewHolder holder = (ViewHolder) convertView.getTag();
// We read the data we need from the ParseObject
String name = parseObject.get("name");
// And here is the visibility logic
int progressBarVisibility = this.activated[position] ? View.VISIBLE : View.GONE;
int textViewVisibility = this.activated[position] ? View.GONE : View.VISIBLE;
// Now we set the data to the Views through the view holder
holder.text.setText(name);
holder.text.setVisibility(textViewVisibility);
holder.my_prog.setVisibility(progressBarVisibility);
return convertView;
}
// This is our view holder class. It keeps a reference to the Views
// inside each row so we have to perform the expensive
// findViewById() only once
private class ViewHolder {
public TextView text;
public ProgressBar my_prog;
}
}
You can use the ExampleAdapter like this:
if(friends != null) {
ExampleAdapter adapter = new ExampleAdapter(Main.this, friends);
setListAdapter(adapter);
}
If you want to show a ProgressBar at a specific position you just do this:
// Shows the ProgressBar in the first row
adapter.showProgressBar(0, true)
I am using GridView for displaying the categories , i have used ImageButton and a Text View in Grid View but I am not able to setOnItemClickListener on those items( Imean nothings Happening on Clicking it)
My code is
this is My Adapter for GridView
public class MyAdapter extends BaseAdapter{
private ArrayList<String> listJewel_name;
private ArrayList<Integer> listJewellery;
private Activity activity;
//private LayoutInflater inflater;
public MyAdapter(Activity activity,ArrayList<String> listJewel_name, ArrayList<Integer> listJewellery) {
super();
this.listJewel_name = listJewel_name;
this.listJewellery = listJewellery;
this.activity = activity;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return listJewel_name.size();
}
#Override
public String getItem(int position) {
// TODO Auto-generated method stub
return listJewel_name.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
public static class ViewHolder
{
public ImageButton imgViewJewel;
public TextView txtViewTitle;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder view;
LayoutInflater inflator = activity.getLayoutInflater();
if(convertView==null)
{
view = new ViewHolder();
convertView = inflator.inflate(R.layout.gridview, null);
view.txtViewTitle = (TextView) convertView.findViewById(R.id.tvtext);
view.imgViewJewel = (ImageButton) convertView.findViewById(R.id.picture);
convertView.setTag(view);
}
else
{
view = (ViewHolder) convertView.getTag();
}
view.txtViewTitle.setText(listJewel_name.get(position));
view.imgViewJewel.setImageResource(listJewellery.get(position));
return convertView;
}
}
My activity.class is
GridView gridView;
Button add;
private MyAdapter mAdapter;
private ArrayList<String> listJewel_name;
private ArrayList<Integer> listJewellery;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select_jewellery_option);
prepareList();
// prepared arraylist and passed it to the Adapter class
mAdapter = new MyAdapter(this,listJewel_name, listJewellery);
// Set custom adapter to gridview
gridView = (GridView) findViewById(R.id.gridview);
gridView.setAdapter(mAdapter);
// Implement On Item click listener
gridView.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View v, int position,
long id) {
String shri=mAdapter.getItem(position);
Toast.makeText(SelectJewelleryOption.this, shri , Toast.LENGTH_SHORT).show();
}
});
}
My XML file is
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.myjewelbox.SquareImageButtonView
android:id="#+id/picture"
android:layout_width="match_parent"
android:layout_height="130dp"
android:scaleType="fitCenter"
android:clickable="true" />
<TextView
android:id="#+id/tvtext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="1dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:layout_gravity="bottom"
android:textColor="#color/Golden"
android:background="#55000000"
android:focusable="false"
/>
</FrameLayout>
And I have set this XMl file to my Main XML file's GridView
Set ItemClickListener for items of GridView in it's adapter,instead of set an ItemClickListener directly for GridView.
view.imgViewJewel.setItemClickListener(activity);
In your adapter class, setOnClickListener on your convertView before return line.
convertView.setOnClickListener(new onClickListener(){
//In this method you can get the items same as you are getting in your
//adapter, as follow:-
String name=listJewel_name.get(position);
//or you can do whatever you want as now you have the whole view that is
//clicked, so you can event get its children or start a new activity or
//whatever you want
}
return converView;
Make Sure android:focusable="false" in your First Child of GridView Layout
and
GridViews can't handle clickable items. Button for example won't work. And also if you have any other non-clickable item, you have to make sure that you didn't set the property: clikable="true".
Refer below link - It is same as what you expect
http://www.androidhub4you.com/2013/07/custom-grid-view-example-in-android.html