NullPointerException using getView in BaseAdapter - java

I'm trying to populate a listView and am getting a nullPointerException. When I debug the program, I see that the TextView's are all null, ie. the findViewById is not working for some reason. Any advice?
The favouritesActivity populates the activity_favourites listView, using favourite_list_layout as the format for each element in the list.
activity to populate lists
public class favouritesActivity extends AppCompatActivity {
String[] titles, authors, publishers, ISBN;
DBConnection dbConnection;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_favourites);
ListView favouritesListView = (ListView) findViewById(R.id.favouritesListView);
//Below populates title and author string lists
//connecting to DB
dbConnection = new DBConnection(this);
//populating list with
List<Book> favouriteBookList = dbConnection.getAllFavBooks();
//below i am populating lists with book data (title and author)
titles = new String[favouriteBookList.size()];
for (int i=0; i<favouriteBookList.size(); i++){
titles[i] = favouriteBookList.get(i).title;
}
authors = new String[favouriteBookList.size()];
for (int i=0; i<favouriteBookList.size(); i++){
authors[i] = favouriteBookList.get(i).authorsString;
}
publishers = new String[favouriteBookList.size()];
for (int i=0; i<favouriteBookList.size(); i++){
publishers[i] = favouriteBookList.get(i).publisher;
}
ISBN = new String[favouriteBookList.size()];
for (int i=0; i<favouriteBookList.size(); i++){
ISBN[i] = favouriteBookList.get(i).isbn;
}
CustomAdapter customAdapter = new CustomAdapter();
favouritesListView.setAdapter(customAdapter);
}
class CustomAdapter extends BaseAdapter{
#Override
public int getCount() {
return titles.length;
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
view = getLayoutInflater().inflate(R.layout.favourite_list_layout, null);
final int index = i;
TextView titleTV = (TextView) findViewById(R.id.favouriteTitle);
TextView authorTV = (TextView) findViewById(R.id.favouriteAuthor);
TextView publisherTV = (TextView) findViewById(R.id.favouritePublisher);
Button deleteFavButton = (Button) findViewById(R.id.deleteFavButton);
titleTV.setText(titles[index]);
authorTV.setText(authors[index]);
publisherTV.setText(publishers[index]);
deleteFavButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dbConnection.removeFavBook(ISBN[index]);
}
});
return view;
}
}
}
favourite_list_layout - the layout of each element of the list
<?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">
<TextView
android:id="#+id/favouriteTitle"
android:textSize="20sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="32dp"
android:layout_marginStart="32dp"
android:layout_marginTop="16dp"
android:text="TextView" />
<TextView
android:id="#+id/favouriteAuthor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/favouriteTitle"
android:layout_alignStart="#+id/favouriteTitle"
android:layout_below="#+id/favouriteTitle"
android:text="TextView" />
<TextView
android:id="#+id/favouritePublisher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/favouriteAuthor"
android:layout_alignStart="#+id/favouriteAuthor"
android:layout_below="#+id/favouriteAuthor"
android:text="TextView" />
<Button
android:id="#+id/deleteFavButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/favouriteAuthor"
android:layout_alignBottom="#+id/favouriteAuthor"
android:layout_marginLeft="38dp"
android:layout_marginStart="38dp"
android:layout_toEndOf="#+id/favouriteTitle"
android:layout_toRightOf="#+id/favouriteTitle"
android:text="Delete" />
</RelativeLayout>

You need to be calling findViewById() on the layout you inflated and not on your activity. That is, replace
TextView titleTV = (TextView) findViewById(R.id.favouriteTitle);
with
TextView titleTV = (TextView) view.findViewById(R.id.favouriteTitle);
and similarly for your other views.

Related

How to change TextView in Activity by delete button in RecyclerView?

When I add an item by button Scan Now, the public double sumCost value incrementes by the cost value in the AddItem method and then TextView(android:id="#+id/SumText") assigns this value. And How to decrease sumCost by the number that is in cost and set new text in TextView when pressing the Delete button? Thanks for any help
enter image description here
My full code:
MainActivity:
package com.example.testfirst;
...
public class MainActivity extends AppCompatActivity {
TextView sumText;
Button buttonAdd;
List<Contact> contacts = new LinkedList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_users);
buttonAdd = (Button) findViewById(R.id.scanBtn);
sumText = (TextView) findViewById(R.id.SumText);
buttonAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
AddItem("Tom", 2.45);
sumText.setText(Double.toString(sumCost));
}
});
}
public void AddItem(String name, double cost){
sumCost += cost;
RecyclerView rvContacts = (RecyclerView) findViewById(R.id.recyclerView);
ContactsAdapter adapter = new ContactsAdapter(contacts);
rvContacts.setAdapter(adapter);
rvContacts.setLayoutManager(new LinearLayoutManager(this));
contacts.add(new Contact(name,Double.toString(cost)));
}
public double sumCost = 0;
}
Contact(Model class):
...
public class Contact {
private String mName;
private String mCost;
public Contact(String name, String cost) {
mName = name;
mCost = cost;
}
public String getName() {
return mName;
}
public String getCost() {
return mCost;
}
}
ContactsAdapter:
...
public class ContactsAdapter extends RecyclerView.Adapter<ViewHolder>{
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View contactView = inflater.inflate(R.layout.item_contact, parent, false);
return new ViewHolder(contactView).linkAdapter(this);
}
///////////////
#NonNull
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
Contact contact = mContacts.get(position);
TextView textViewId = holder.nameId;
textViewId.setText(contact.getName());
TextView textViewCost = holder.nameCost;
textViewCost.setText(contact.getCost());
}
#Override
public int getItemCount() {
return mContacts.size();
}
List<Contact> mContacts;
public ContactsAdapter(List<Contact> contacts) {
mContacts = contacts;
}
}
class ViewHolder extends RecyclerView.ViewHolder {
private ContactsAdapter adapter;
public TextView nameId;
public TextView nameCost;
public ViewHolder(#NonNull View itemView) {
super(itemView);
nameId = (TextView) itemView.findViewById(R.id.text);
nameCost = (TextView) itemView.findViewById(R.id.textCost);
itemView.findViewById(R.id.delete).setOnClickListener(view -> {
adapter.mContacts.remove(getAdapterPosition());
adapter.notifyItemRemoved(getAdapterPosition());
});
}
public ViewHolder linkAdapter(ContactsAdapter adapter){
this.adapter = adapter;
return this;
}
}
item_contact.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="10dp"
app:cardCornerRadius="10dp"
app:cardElevation="5dp"
app:contentPadding="5dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:text="#string/app_name"
android:textSize="20sp" />
<TextView
android:id="#+id/textCost"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/text"
android:text="#string/app_name"
android:textSize="20sp" />
<Button
android:id="#+id/delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginTop="3dp"
android:layout_marginEnd="3dp"
android:text="Delete" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
activity_users.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="#+id/SumText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="0.00"
android:textSize="30sp"/>
<Button
android:id="#+id/scanBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Scan now"
android:textSize="30sp"
android:layout_gravity="center_horizontal"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
One easy way to do that would be do add a "Decrementer" interface in the adapter that it can call to decrement the total cost, like this:
// Define the interface
public interface Decrementer {
void onDelete(double cost);
}
// Define an instance of the interface to hold
private final Decrementer mDecrementer;
// Pass in a decrementer at construction
public ContactsAdapter(List<Contact> contacts, Decrementer decr) {
mContacts = contacts;
mDecrementer = decr;
}
#NonNull
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
// get views and such ...
// Call the decrementer method when the button is clicked
// Could set this in onBindViewHolder, or pass the decrementer
// into the ViewHolder itself and use it there.
deleteButton.setOnClickListener(view -> {
int pos = holder.getAdapterPosition();
Contact c = mContacts.get(pos);
// add getCostAmount to return a double, or better yet, just
// store it as a Double instead of a string in Contact
mDecrementer.onDelete(c.getCostAmount());
mContacts.remove(pos);
notifyItemRemoved(pos);
});
}
and you would define the Decrementer when you create the adapter so it can access the Activity class members, like this:
ContactsAdapter adapter = new ContactsAdapter(contacts, new ContactsAdapter.Decrementer() {
#Override
public void onDelete(double cost) {
sumCost -= cost;
// change activity TextViews and such here too
sumText.setText(Double.toString(sumCost));
}
});
Side note: you don't need to create a whole new adapter every time you add an item, just add it to the contacts array and call an appropriate notifyDataSetChanged method on the existing adapter.
private ContactsAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_users);
//...
RecyclerView rvContacts = (RecyclerView) findViewById(R.id.recyclerView);
ContactsAdapter adapter = new ContactsAdapter(contacts);
rvContacts.setAdapter(adapter);
rvContacts.setLayoutManager(new LinearLayoutManager(this));
}
public void AddItem(String name, double cost){
sumCost += cost;
contacts.add(new Contact(name,Double.toString(cost)));
adapter.notifyDataSetChanged(); // or a less expensive notify call
}

Android Custom ListView with Images and Text in horizantally

first of all sorry for poor communication, i have using custom array adapter and list of images and names are displaying gridview control in my app.The images and names are come from sql server database now showing all images bind and display to gridview, i want to images displaying slide type i.e. first column display 3 images after click the image slide to the next 3 images display.. anybody help me please.
My Code is:
enquiryfrm.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:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Select Name"/>
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ScrollView
android:id="#+id/questionListSV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:fillViewport="true">
<GridView
android:id="#+id/gridviewimg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:numColumns="3"
android:horizontalSpacing="10dp"
android:scrollbars="horizontal"
android:scrollbarAlwaysDrawHorizontalTrack="true"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:stretchMode="none"
android:columnWidth="100dp"
android:paddingBottom="60dp"/>
</ScrollView>
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content">
</Spinner>
</LinearLayout>
2.enquiryaimagetemplate.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="wrap_content"
android:padding="1dp"
android:orientation="vertical">
<ImageView
android:id="#+id/imageview2"
android:layout_width="120dp"
android:layout_height="120dp"
android:scaleType="fitXY"
android:layout_marginRight="10dp"
android:src="#drawable/not_available" />
<TextView
android:id="#+id/txtitem_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textSize="15sp" >
</TextView>
<TextView
android:id="#+id/txtregidno"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textSize="15sp" >
</TextView>
</LinearLayout>
3.enquiryitems.java
public class enquiryItems {
String itemname;
int Reg_id;
Bitmap itemimg;
public enquiryItems(String itemname,Bitmap itemimg,int Reg_id){
this.itemname=itemname;
this.itemimg=itemimg;
this.Reg_id=Reg_id;
}
public String getItemname(){
return itemname;
}
public Bitmap getItemimg(){return itemimg;}
public int getReg_id(){return Reg_id;}
}
4.enquiryarrayadapter
public class EnquiryArrayadapter extends ArrayAdapter<enquiryItems> {
ArrayList<enquiryItems> itemlist = new ArrayList<>();
private Context context;
ConnectionClass connectionClass;
public EnquiryArrayadapter(ArrayList<enquiryItems> objects,Context context) {
super(context,R.layout.enquiryaimagetemplate,objects);
this.itemlist=objects;
this.context=context;
//visitorlist=objects;
}
#Override
public int getCount() {
return super.getCount();
}
#Override
public View getView(final int position, View convertview, ViewGroup parent){
if (convertview == null) { // This a new view we inflate the new layout
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertview = inflater.inflate(R.layout.enquiryaimagetemplate, parent, false);
}
connectionClass = new ConnectionClass();
final TextView txtitem_name=(TextView)convertview.findViewById(R.id.txtitem_name);
final TextView txtregidno = (TextView) convertview.findViewById(R.id.txtregidno);
final ImageView imageview2 = (ImageView) convertview.findViewById(R.id.imageview2);
final enquiryItems objitem=itemlist.get(position);
imageview2.setImageBitmap(objitem.getItemimg());
txtitem_name.setText(objitem.getItemname());
txtregidno.setText(String.valueOf(objitem.getReg_id()));
// txtregidno.setVisibility(View.GONE);
imageview2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//ImageView imageview2 = (ImageView) v;
String idval = txtregidno.getText().toString();
/* int id=Integer.parseInt(String.valueOf(idval));
zoomImageFromThumb(imageview2, id);*/
}
});
return convertview;
}
5.enquiry.java
public class Enquiry extends Fragment {
ProgressDialog pbd;
GridView gridviewimg;
ConnectionClass connectionClass;
int RegIdNo;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.enquiryfrm, container, false);
connectionClass=new ConnectionClass();
gridviewimg=(GridView)rootView.findViewById(R.id.gridviewimg);
Fetch fe=new Fetch();
fe.execute("");
return rootView;
}
public class Fetch extends AsyncTask<String, String, String> {
String z = "";
String ownid;
ArrayList<enquiryItems> visitorList=new ArrayList<>();
#Override
protected void onPreExecute() {
pbd=new ProgressDialog(getActivity());
pbd.setMessage("Please Wait...");
pbd.setCancelable(false);
pbd.show();
}
#Override
protected void onPostExecute(String r) {
// pbbar.setVisibility(View.GONE);
if (pbd.isShowing())
pbd.dismiss();
if(r!="empty"){
Toast.makeText(getActivity(), r, Toast.LENGTH_SHORT).show();
}
EnquiryArrayadapter myAdapter=new EnquiryArrayadapter(visitorList,getActivity());
myAdapter.notifyDataSetChanged();
gridviewimg.setAdapter(myAdapter);
// Toast.makeText(getActivity(), r, Toast.LENGTH_SHORT).show();
}
#Override
protected String doInBackground(String... params) {
try {
Connection con = connectionClass.CONN();
if (con == null) {
z = "Error in connection with SQL server";
} else {//
String query="";
query = "select * from FB_Feedback";
PreparedStatement ps2 = con.prepareStatement(query);
ResultSet rs2 = ps2.executeQuery();
ArrayList data1 = new ArrayList();
while (rs2.next()) {
//Reg_Id=rs.getInt("Id");
RegIdNo = rs2.getInt("id");
String r = rs2.getString("Photo");
//Convertong Images string to bitmap
byte[] decodeString = Base64.decode(r, Base64.DEFAULT);
Bitmap decodebitmap = BitmapFactory.decodeByteArray(decodeString, 0, decodeString.length);
visitorList.add(new enquiryItems("Item Name : "+rs2.getString("Feedback"),decodebitmap,RegIdNo));
// }
// z="Success";
}
if (RegIdNo==0){
z="No Visitor data";
}else {
z="empty";
}
}
} catch (Exception ex) {
z = ex.toString();
}
return z;
}
}
like the below format need enter image description here
Your question is not understandable. As far as I understood, try using horizontal listview.

Android - Selecting a Radio Button in a group causes another Radio Button in another group to be selected

I am using a fragment layout to display a row in a ListView and I'm using a ListAdapter to populate the ListView. Each row contains a TextView and a RadioGroup, each radio group contains 2 RadioButtons for yes and no.
The problem is that when I run the application, when I select a RadioButton (like yes) on the first group it causes another RadioButton (also yes) to be selected in another group in another row of the ListView.
Here is the layout code for the row fragment:
<?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:id="#+id/questionTextView">
<TextView
android:text="Dis one na question wey go need yes or no answer?"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/questionView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="19dp"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:textSize="20sp" />
<RadioGroup
android:layout_width="120dp"
android:layout_height="wrap_content"
android:id="#+id/customRadioGroup"
android:layout_marginTop="16dp"
android:layout_below="#+id/questionView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true">
<RadioButton
android:text="Yes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/yesRadioBtn"
android:layout_alignBaseline="#+id/noRadioBtn"
android:layout_alignBottom="#+id/noRadioBtn"
android:layout_toLeftOf="#+id/noRadioBtn"
android:layout_toStartOf="#+id/noRadioBtn"
android:layout_marginRight="15dp"
android:layout_marginEnd="15dp" />
<RadioButton
android:text="No"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/noRadioBtn"
android:layout_below="#+id/questionsTitle"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp" />
</RadioGroup>
And my ListAdapter class:
public class MyCustomAdapter extends BaseAdapter implements ListAdapter {
private ArrayList<String> list = new ArrayList<String>();
private Context context;
private String[] answers;
public MyCustomAdapter(ArrayList<String> list, Context context) {
this.list = list;
this.context = context;
this.answers = new String[list.size()];
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int pos) {
return list.get(pos);
}
#Override
public long getItemId(int pos) {
//return list.get(pos).getId();
//just return 0 if your list items do not have an Id variable.
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.question_row, null);
}
//Handle TextView and display string from your list
TextView listItemText = (TextView)view.findViewById(R.id.questionView);
listItemText.setText(list.get(position));
//Handle buttons and add onClickListeners
RadioGroup radioGroup = (RadioGroup)view.findViewById(R.id.customRadioGroup);
//radioGroup.setId(position);
View vYes = radioGroup.getChildAt(0);
View vNo = radioGroup.getChildAt(1);
RadioButton yesRadioBtn = (RadioButton)vYes;//(RadioButton)view.findViewById(R.id.yesRadioBtn);
RadioButton noRadioBtn = (RadioButton)vNo;//(RadioButton)view.findViewById(R.id.noRadioBtn);
yesRadioBtn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
answers[position] = "yes";
notifyDataSetChanged();
}
});
noRadioBtn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
answers[position] = "no";
notifyDataSetChanged();
}
});
return view;
}
public String[] getAnswers()
{
return this.answers;
}
}
You need to reset the RadioGroup if you are reusing a View (convertView != null). The following change will reset the RadioGroup to "no selection", but you will need to set it to the value that is reflected in your internal data structure answers.
RadioGroup radioGroup = (RadioGroup)view.findViewById(R.id.customRadioGroup);
if (convertView != null) {
radioGroup.clearCheck();
}

How to Change Text Color, Size and Font in a Dynamically Created ListView

I am trying to make a to-do list using an EditText and a ListView. How can I change the text font, color and size? I have seen a couple answers using array adapters, but don't know how to apply them to dynamically created ListView items.
Here is what I have so far:
ActivityMain.xml
<RelativeLayout
android:id="#+id/AgendaRL"
android:orientation="vertical"
android:background="#3E2723"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/agenda"
android:layout_width="370sp"
android:layout_height="wrap_content"
android:text="#string/agenda"
android:textSize="40sp"
android:textColor="#b7950b"
android:layout_marginTop="12sp"
android:layout_marginLeft="12sp"
android:layout_marginStart="12sp"
android:layout_marginBottom="0sp" />
<View
android:background="#b7950b"
android:layout_below="#+id/agenda"
android:layout_width="28sp"
android:layout_height="36sp"/>
<EditText
android:id="#+id/aTask"
android:layout_below="#+id/agenda"
android:background="#drawable/ribbon"
android:inputType="text"
android:text="#string/Add_Task"
android:textColor="#3E2723"
android:maxLength="22"
android:maxLines="1"
android:layout_width="330sp"
android:layout_height="36sp"
android:textSize="28sp"
android:layout_marginLeft="28sp"
android:layout_marginStart="28sp"/>
<Button
android:id="#+id/Done"
style="?android:attr/borderlessButtonStyle"
android:layout_marginLeft="250sp"
android:layout_marginStart="250sp"
android:background="#b7950b"
android:text="#string/Done"
android:textColor="#3E2723"
android:textSize="18sp"
android:layout_below="#+id/agenda"
android:layout_width="48sp"
android:layout_height="36sp"
android:onClick="DoneClick"/>
<ListView
android:id="#+id/LVAgenda"
android:layout_below="#+id/aTask"
android:divider="#android:color/transparent"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
MainActivity.Java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView LVAgenda = (ListView) findViewById(R.id.LVAgenda);
arrayListAgenda = new ArrayList<String>();
arrayAdapterAgenda = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, arrayListAgenda);
LVAgenda.setAdapter(arrayAdapterAgenda);
}
public void DoneClick(View v){
EditText aTask = (EditText)findViewById(R.id.aTask);
String agenda = aTask.getText().toString().trim();
if(agenda.isEmpty()){
return;
}
arrayAdapterAgenda.add(agenda);
aTask.setText("Add task");
}
As commonsware said you can use getView() of ArrayAdapter to do this.
I have implemented Facebook friend selector with ListAdapter. I will share the code. May be it helps. Please try.
First make a XML file in layout that defines the layout of each item of your 'to do list'.
In my case it is a facebook profile image and a checked textbox. (There is also a spacer for alignment)
Facebook.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="wrap_content"
android:orientation="vertical">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/img"
android:layout_width="50dp"
android:layout_height="50dp"
android:paddingLeft="10dp"/>
<CheckedTextView
android:id="#+id/name"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical|right"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:textColor="#android:color/black"
android:textStyle="bold" />
</LinearLayout>
<View
android:id="#+id/spacer"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#android:color/white"/>
</LinearLayout>
Now prepare your data array. In my case it is custom class array where each element contains a facebook name, profilepic, and a boolean.
public class Item{
public final String text;
public final Drawable icon;
public boolean isChecked;
public Item(String text, Drawable icon, boolean ischeck) {
this.text = text;
this.icon = icon;
this.isChecked = ischeck;
}
#Override
public String toString() {
return text;
}
}
I call the below code by passing friendsArray from another activity.
final Item[] items = new Item[friendsArray.length];
try {
int a = 1;
for (int i = 0; i < friendsArray.length; i++) {
tsk = new DownloadImageTask();
Bitmap bmp = (Bitmap) tsk.execute(new RaceActivity.FriendInfo[]{friendsArray[i]}).get();
Resources res = getActivity().getResources();
drawable = new BitmapDrawable(res, bmp);
items[i] = new Item(friendsArray[i].name, drawable,false);
}
}
catch(Exception ex)
{
}
Now your data array is prepared. You can pass this to ListAdapter(items in my case).
Its nice to understand the working of a List adapter. I created a scrollable List. What this logic does is it reuses the Views while scrolling.
ListAdapter adapter = new ArrayAdapter<Item>(
getActivity(),
android.R.layout.select_dialog_item,
android.R.id.text1,
items){
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
FaceBookHolder fb = new FaceBookHolder();
if(convertView == null)
{
LayoutInflater inflater = (LayoutInflater) getActivity().getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.facebook,null);
fb.Name = (CheckedTextView) v.findViewById(R.id.name);
fb.img = (ImageView) v.findViewById(R.id.img);
fb.spacer = (View) v.findViewById(R.id.spacer);
fb.Name.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
CheckedTextView cv = (CheckedTextView)v;
if(cv.isChecked())
cv.setChecked(false);
else
cv.setChecked(true);
for(int i =0;i< items.length; i++)
{
if(items[i].text == cv.getText())
{
items[i].isChecked = cv.isChecked();
}
}
}
});
v.setTag(fb);
}
else
fb = (FaceBookHolder) v.getTag();
Item itm = items[position];
fb.Name.setText(itm.text);
fb.img.setImageDrawable(itm.icon);
fb.Name.setChecked(itm.isChecked);
return v;
}
};
you get the view in getView(), so you can modify it however you want.(change color , font etc)
Hope it helps! cheers!

Android ListView based in custom BaseAdapter is not shown in my code

I've working on ListView with a custom BaseAdapter which I've watched on the Slidenerd tutorial series here:(It's not important to watch to understand my question)
http://www.youtube.com/watch?v=_l9e2t4fcfM&list=PLonJJ3BVjZW6hYgvtkaWvwAVvOFB7fkLa&index=91
After running the code on the virtual device there is no error but not ListView too.
Is it possible to tell me what's the problem of my code?
public class List extends Activity {
ListView lv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
lv = (ListView) findViewById(R.id.listView);
lv.setAdapter(new EhsanAdapter(this));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.list, menu);
return true;
}
}
class SingleRow{
String title;
String description;
int image;
public SingleRow(String title,String description,int image) {
this.title = title;
this.description=description;
this.image=image;
}
}
class EhsanAdapter extends BaseAdapter{
ArrayList<SingleRow> list;
Context context;
public EhsanAdapter(Context c) {
list = new ArrayList<SingleRow>();
context = c;
Resources res = c.getResources();
String[] titles = res.getStringArray(R.array.titles);
String[] descriptions = res.getStringArray(R.array.descriptions);
int[] images = {R.drawable.image1,R.drawable.image2,R.drawable.image3,R.drawable.image4,R.drawable.image5};
for(int i=0;i<10;i++){
list.add(new SingleRow(titles[i], descriptions[i], images[i]));
}
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int i) {
return list.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.single_row, viewGroup,false);
TextView title = (TextView) row.findViewById(R.id.txtTitle);
TextView description = (TextView) row.findViewById(R.id.txtDescription);
ImageView image = (ImageView) row.findViewById(R.id.imgPic);
SingleRow temp = list.get(i);
title.setText(temp.title);
description.setText(temp.description);
image.setImageResource(temp.image);
return row;
}
}
The layout of activity:
<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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".List" >
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/listView"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</RelativeLayout>
The layout of single row:
<?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" >
<ImageView
android:layout_margin="10dp"
android:id="#+id/imgPic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:src="#drawable/image1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Title"
android:id="#+id/txtTitle"
android:layout_alignTop="#+id/imgPic"
android:layout_toRightOf="#+id/imgPic"
android:layout_alignParentRight="true">
</TextView>
<TextView
android:id="#+id/txtDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/imgPic"
android:layout_marginLeft="25dp"
android:layout_toRightOf="#+id/imgPic"
android:layout_marginTop="20dp"
android:text="Description"
android:ems="10">
</TextView>
</RelativeLayout>
Remove the line LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); from getView() method and instead add it in the constructor of EhsanAdapter class.
I see different issues:
The layout of single row contains a relative layout which the android:layout_height="match_parent" should be android:layout_height="wrap_content"
Then inside the Adapter you are neither recycling the views nor using the ViewHolder pattern:
http://developer.android.com/training/improving-layouts/smooth-scrolling.html
About ViewHolder pattern implementation optimisation in ListView
http://www.jmanzano.es/blog/?p=166
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
if (view == null){ //The row view is not created, let's do it:
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.single_row, viewGroup,false);
TextView title = (TextView) row.findViewById(R.id.txtTitle);
TextView description = (TextView) row.findViewById(R.id.txtDescription);
ImageView image = (ImageView) row.findViewById(R.id.imgPic);
// Here we add the title, description and image inside the ViewHolder
....
}else{
//With the View holder pattern we get the views inside the row view to fill it later
....
}
// Now we get the SingleRow and we fill it using the ViewHolder pattern
SingleRow temp = list.get(i);
....
return row;
}
You only have 5 images and you wrote i<10 you should've wrote i<5 the amount of "titles" and "descriptions" and "images" must be the same.
for(int i=0;i<5;i++){
list.add(new SingleRow(titles[i], descriptions[i], images[i]));
}

Categories

Resources