I am trying to use the ListFragment and assign an adapter to it.
I tried many different methods, but still the app crashes and won't start.
Here is what I have done:
fragment_five.xml:
<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=".MainActivity"
android:background="#drawable/bg11">
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</RelativeLayout>
FiveFragment.java:
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class FiveFragment extends ListFragment {
public FiveFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_five, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String items[] = getResources().getStringArray(R.array.list5);
CustomListAdapter adapter = new CustomListAdapter(getActivity().getBaseContext(), items);
//ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, items);
setListAdapter(adapter);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
}
}
and here is the CustomListAdapter that I am using... I am sure it works cause I have tested elsewhere
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class CustomListAdapter extends BaseAdapter {
private Context context;
private String texts[];
public CustomListAdapter(Context context, String[] texts) {
this.context = context;
this.texts = texts;
}
#Override
public int getCount() {
return texts.length;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
static class ViewHolder {
private TextView details;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View rowView = convertView;
if (rowView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.list_item, parent, false);
ViewHolder viewHolder = new ViewHolder();
viewHolder.details = (TextView) rowView.findViewById(R.id.details);
rowView.setTag(viewHolder);
}
ViewHolder holder = (ViewHolder) rowView.getTag();
holder.details.setText(texts[position]);
return rowView;
}
}
When I use the simple ArrayAdapter everything is ok but when I use the Custom Adapter the app crashes... it doesn't matter that which adapter I use either the CustomArrayAdapter or the CustomBaseAdapter it just doesn't work.
If you know any way around this please help!
I finally found the solution for this problem...
FiveFragment.java should be like this:
public class FiveFragment extends Fragment {
private ListView listView;
private String items[];
public FiveFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
items = getResources().getStringArray(R.array.list5);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_five, container, false);
listView = (ListView) rootView.findViewById(android.R.id.list);
CustomListAdapter adapter = new CustomListAdapter(getActivity(), items);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
Toast.makeText(getContext(), "You Clicked on: " + arg2, Toast.LENGTH_SHORT).show();
}
});
return rootView;
}
}
and the CustomListAdapter:
private LayoutInflater myInflater;
private String shopList[];
public ShopListAdapter(Context context, String shopList[]) {
myInflater = LayoutInflater.from(context);
this.shopList = shopList;
}
static class ViewHolder {
TextView tvTitle;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = myInflater.inflate(R.layout.list_item, null);
holder = new ViewHolder();
holder.tvTitle = (TextView) convertView.findViewById(R.id.rowText);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tvTitle.setText(shopList[position]);
return convertView;
}
This code solved the problem completely...
Related
when I open app it does not work why?
Why this RecyclerView does not work but I don not why
package com.example.dell.iwantto;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
public class NameAdapter extends RecyclerView.Adapter<NameAdapter.NameViewHolder> {
private ArrayList<String> mData;
public static class NameViewHolder extends RecyclerView.ViewHolder {
public TextView mNameTextView;
public NameViewHolder(TextView v) {
super(v);
mNameTextView = v;
}
}
public NameAdapter(ArrayList<String> mData) {
this.mData = mData;
}
#Override
public NameAdapter.NameViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
TextView v = (TextView) LayoutInflater.from(parent.getContext())
.inflate(R.layout.layout,parent, false).findViewById(R.id.xs);
NameViewHolder vh = new NameViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(NameViewHolder holder, int position) {
holder.mNameTextView.setText(mData.get(position));
}
#Override
public int getItemCount() {
return mData.size();
}
}
How I can solve it ? And what is the error? Why app is stop when I tried to open it in phone?
Your RecyclerView can't work because you're incorrectly giving a child view as a parent view which is needed by ViewHolder in your following code:
#Override
public NameAdapter.NameViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// This is incorrect because the method need a parent view not a child view
TextView v = (TextView) LayoutInflater.from(parent.getContext())
.inflate(R.layout.layout,parent, false).findViewById(R.id.xs);
NameViewHolder vh = new NameViewHolder(v);
return vh;
}
It should be something like this:
#Override
public NameAdapter.NameViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
// inflate your layout.
View view = inflater.inflate(R.layout.layout, parent, false);
NameViewHolder viewHolder = new NameViewHolder(view);
return viewHolder;
}
I got some problem when trying to refresh the list view content on call back. Inside my onCreate():
private ListAdapter mAdapter;
private ListView listview;
mAdapter = new ListAdapter(getActivity());
listview.setAdapter(mAdapter);
Then, inside my callback which is working as I managed to print out the data:
public void callback(ArrayList<Transaction> list)
{
expenseslist.clear();
Log.d("SIZE", String.valueOf(list.size()));
for(int i = 0; i < list.size(); i++){
expenseslist.add(list.get(i));
}
mAdapter.notifyDataSetChanged();
listview.invalidateViews();
}
private class ListAdapter extends BaseAdapter {
LayoutInflater inflater;
ViewHolder viewHolder;
public ListAdapter(Context context) {
inflater = LayoutInflater.from(context);
}
public int getCount() {
return expenseslist.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.transactioncat_listview_row,
null);
viewHolder = new ViewHolder();
viewHolder.txt_dcatTitle = (TextView) convertView
.findViewById(R.id.txtCatTitle);
viewHolder.txt_dcatTotal = (TextView) convertView
.findViewById(R.id.txtCatTotal);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.txt_dcatTitle.setText(expenseslist.get(position)
.getCategory().getCategoryName().trim());
viewHolder.txt_dcatTotal.setText(Extra.formatCurrency(expenseslist.get(position)
.getTransactionAmt()));
return convertView;
}
}
I called the notifyDataSetChanged() and invalidateViews() but it is not refreshing. I am not adding new rows to the list view but rather, updating the content in each row.
How can I do this correctly?
public class ExpenseActivity extends Fragment implements TransactionListCallBack{
private ArrayList<Transaction> transactionlist = new ArrayList<Transaction>();
private ArrayList<Transaction> expenseslist = new ArrayList<Transaction>();
private ListAdapter mAdapter;
private ListView listview;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.activity_expense,container,false);
expenseslist.clear();
transactionlist = (ArrayList<Transaction>)getArguments().getSerializable("transactionlist");
for(int j = 0; j < transactionlist.size(); j++){
expenseslist.add(transactionlist.get(j));
}
listview = (ListView) v.findViewById(R.id.transactionCatListview);
// Binding the list into list view
mAdapter = new ListAdapter(getActivity());
listview.setAdapter(mAdapter);
return v;
}
#Override
public void callback(ArrayList<Transaction> list)
{
total = 0;
expenseslist.clear();
for(int i = 0; i < list.size(); i++){
expenseslist.add(list.get(i));
}
}
mAdapter.notifyDataSetChanged();
listview.invalidateViews();
}
private class ListAdapter extends BaseAdapter {
LayoutInflater inflater;
ViewHolder viewHolder;
public ListAdapter(Context context) {
inflater = LayoutInflater.from(context);
}
public int getCount() {
return expenseslist.size();
}
public Object getItem(int position) {
return expenseslist.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.transactioncat_listview_row,
null);
viewHolder = new ViewHolder();
viewHolder.txt_dcatTitle = (TextView) convertView
.findViewById(R.id.txtCatTitle);
viewHolder.txt_dcatTotal = (TextView) convertView
.findViewById(R.id.txtCatTotal);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.txt_dcatTitle.setText(expenseslist.get(position)
.getCategory().getCategoryName().trim());
viewHolder.txt_dcatTotal.setText(Extra.formatCurrency(expenseslist.get(position)
.getTransactionAmt()));
return convertView;
}
}
private class ViewHolder {
CircularProgressBar progressBar;
ImageView background_catview;
ImageView icon_catview;
TextView txt_dcatTitle;
TextView txt_dcatTotal;
}
// override menu item to add new transaction
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.menu_main_addtransaction, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_openNewTransaction) {
new GetAllCategoriesAsyncTask(
new GetAllCategoriesAsyncTask.OnRoutineFinished() {
public void onFinish() {
AddTransactionActivity addFragment = new AddTransactionActivity();
FragmentTransaction tt = getFragmentManager().beginTransaction();
addFragment.setTransactionListCallBack(ExpenseActivity.this);
tt.replace(R.id.frame,addFragment);
tt.addToBackStack("tag");
tt.commit();
}
}).execute();
}
return super.onOptionsItemSelected(item);
}
}
Make this change
public Object getItem(int position) {
return expenseslist.get(position);
}
You need to keep a list of your data in adapter for notifyDataSetChanged to work:
Change
mAdapter = new ListAdapter(getActivity(), expenseslist);
And inside your adapter:
list<Transaction> expenseslist;
public ListAdapter(Context context, list<Transaction> expenseslist) {
inflater = LayoutInflater.from(context);
this.expenseslist = expenseslist;
}
EDIT:
Also change these methods:
public Transaction getItem(int position) {
return expenseslist.get(position);
}
public long getItemId(int position) {
return expenseslist.get(position).getId();
}
Hi Denise in your adapter create a new function called updateTransactions(). This is the code for function where expenseslist is the list your passing to adapter.
public void updateTransactions(List<Transaction> list) {
expenseslist.clear();
expenseslist.addAll(list);
notifyDataSetChanged();
Log.d("SIZE", String.valueOf(expensesList.size()));
}
Then in your callback function call updateTransactions() using instance of adapter like this
public void callback(ArrayList<Transaction> list)
{
mAdapter.updateTransactions(list);
}
Edit: Demo run code
package ********;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collections;
/**
* Created by Rishabh Bhatia on 18/5/17.
*/
public class TestActivity extends Activity {
private ListView list;
private ListAdapter adapter;
private ArrayList<String> dataList;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
list = (ListView) findViewById(R.id.list);
dataList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
String string = "abc";
dataList.add(string);
}
adapter = new ListAdapter(this, dataList);
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d("rishabh", "something is selected");
String transaction = dataList.get(0);
transaction = "xyz";
dataList.remove(0);
dataList.add(0, transaction);
adapter.updateExpenses(dataList);
}
});
}
private class ListAdapter extends BaseAdapter {
private ArrayList<String> expenseslist;
LayoutInflater inflater;
ViewHolder viewHolder;
public ListAdapter(Context context, ArrayList<String> list) {
inflater = LayoutInflater.from(context);
this.expenseslist = (ArrayList<String>) list.clone();
}
public int getCount() {
return expenseslist.size();
}
public Object getItem(int position) {
return expenseslist.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.row,
null);
viewHolder = new ViewHolder();
viewHolder.text = (TextView) convertView
.findViewById(R.id.tvRow);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.text.setText(expenseslist.get(position));
return convertView;
}
public void updateExpenses(ArrayList<String> list) {
Log.d("rishabh", "updating the expenses "+list.size());
expenseslist.clear();
for(int i =0; i<list.size(); i++) {
Log.d("rishabh", "inside for loop");
expenseslist.add(list.get(i));
Log.d("rishabh", "updating item to list "+list.get(i));
}
notifyDataSetChanged();
Log.d("rishabh", "updating the expenses "+expenseslist.size());
}
}
static class ViewHolder {
private TextView text;
}
}
Hopefully it helps.
Are you are coding within a fragment? Could i ask where/when you call this method
public void callback(ArrayList list);
As I guess you call this method from an activity on a lifecycle method right after you add the fragment. Or maybe you call this method not in a UI thread with a try - catch block.
I want to show my custom ArrayAdapter in a ListFragment with a SlidingTabLayout. Previously I tested the adapter in a normal activity and worked fine, also the SlidingTabLayout worked correctly, but yet the ListFragment show nothing. I get the data from a meteor server and logcat show me the data has been downloaded...
Does anybody have some tips?
This is my Fragment Java Code:
public class MorningFragment extends ListFragment {
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_morning,container,false);
return v;
}
#Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
MedicationTimeAdapter timeAdapter;
timeAdapter = new MedicationTimeAdapter(getActivity(), R.layout.item_time);
setListAdapter(timeAdapter);
}
}
And my Fragment XML Code:
<?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">
<ListView
android:id="#android:id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
My adapter
public class MedicationTimeAdapter extends ArrayAdapter<MedicationTime> implements DataManager.MedicationCallback {
private static final String LOG_TAG = MedicationTimeAdapter.class.getName();
private final int resourceId;
private final Activity activity;
// private List<MedicationEntry> medications = new ArrayList<MedicationEntry>();
public MedicationTimeAdapter(Activity context, int resource) {
super(context, resource);
resourceId = resource;
activity = context;
}
#Override
public void handleMedicationPlan(List<MedicationEntry> medication) {
// ignore
}
#Override
public void handleMedicationTimes(final List<MedicationTime> medicationTimes) {
// TODO Activity möglicherweise nicht mehr aktiv
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
setItems(medicationTimes);
}
});
}
public void setItems(List<MedicationTime> itemList) {
clear();
for (MedicationTime item : itemList) {
add(item);
}
notifyDataSetChanged();
}
#Override
public int getCount() {
return super.getCount();
}
#Override
public View getView(int index, View convertView, ViewGroup parent) {
//data from your adapter
MedicationTime itemData = getItem(index);
if (convertView == null) {
// final LayoutInflater inflater = MHApplication.getLayoutInflater();
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
// TODO mit Referenz Parent-Group erzeugen?! (war für ColorFinder notwendig, um die LayoutParams beim Laden zu erhalten)
// convertView = inflater.inflate(resourceId, parent, false);
convertView = inflater.inflate(resourceId, null);
// prepareInflatedView(convertView);
}
setViewContent(index, convertView, itemData);
return convertView;
}
protected void setViewContent(int index, View itemView, MedicationTime itemData) {
final TextView nameView = (TextView) itemView.findViewById(R.id.time_name);
final TextView medicationView = (TextView) itemView.findViewById(R.id.medication);
int nameId = activity.getResources().getIdentifier("time_name." + itemData.getTimeName(), "string", activity.getPackageName());
nameView.setText(activity.getResources().getString(nameId));
nameView.setText(nameId);
StringBuilder medText = new StringBuilder();
List<MedicationTime.Entry> medications = itemData.getMedications();
for (MedicationTime.Entry medication : medications) {
medText.append(medication.getCount());
medText.append(" * ");
medText.append(medication.getMedicationEntry().getSubstance());
medText.append(" (");
medText.append(medication.getMedicationEntry().getTradingName());
medText.append(")\n");
}
medicationView.setText(medText.toString());
}
Edit:
I solved the Problem , i have a Method in my mainActivity to fill the adapter with Data. The problem was i create a new Adapter in my Fragment. So i add a konstruktor in my Fragment class and submitter the Adapter from my mainActivity.
public MorningFragment(MedicationTimeAdapter timeAdapter) {
medicationTimeAdapter = timeAdapter;
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_morning,container,false);
setListAdapter(medicationTimeAdapter);
return v;
}
Call handleMedicationTimes(final List<MedicationTime> medicationTimes) with some data, Your code seems is not inflating any data.
I have list of title-CheckBox, and i want to have control which one will be checked on default. So I'm trying to get the right view and check it, but for some reason it doesn't work. any idea why?
form_checkbox_item.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"
android:gravity="center"
android:orientation="horizontal" >
<CheckBox
android:id="#+id/checkBox1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp"
android:textColor="#color/background_red"
android:padding="12dp"
/>
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="TextView"
android:textColor="#color/background_red"
android:textSize="18sp" />
</LinearLayout>
CheckboxAdapter.java
package com.rgis.datacollection.ui.adapters;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.TextView;
import com.rgis.datacollection.R;
import java.util.List;
public class CheckboxAdapter extends ArrayAdapter
{
Context context;
List<String> checkboxItems;
public CheckboxAdapter(Context context, List<String> resource)
{
super(context, R.layout.form_checkbox_item ,resource);
this.context = context;
this.checkboxItems = resource;
}
public View getView(int position, View convertView, ViewGroup parent)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
convertView = inflater.inflate(R.layout.form_checkbox_item, parent, false);
TextView textView = (TextView) convertView.findViewById(R.id.textView1);
CheckBox cb = (CheckBox) convertView.findViewById(R.id.checkBox1);
textView.setText(checkboxItems.get(position));
return convertView;
}
}
part of formCheckBox.java
formItem = (LinearLayout) linflater.inflate(R.layout.checkbox_layout, null);
listView = (ListView) formItem.findViewById(R.id.checkboxList);
stringList = dbUtils.getServiceConfigForFixedOptions(attribute.getListValues());
CheckboxAdapter checkboxAdapter = new CheckboxAdapter(context, stringList);
listView.setAdapter(checkboxAdapter);
CheckBox cb = (CheckBox) checkboxAdapter.getView(0, null, listView).findViewById(R.id.checkBox1);
cb.setChecked(true);
I recomend you to implement this way:
Pass a boolean array in the constructor to initialize states.
Register a listener for checkbox state changes to update the states array.
Implement "isChecked" to check if an item is checked at determinated position.
Using "getCount" and "isChecked" you can traverse the list from outside the adapter.
Here is the code:
public class CheckboxAdapter extends ArrayAdapter<String> {
List<String> subcategories;
boolean[] checked;
public SubcategoriesAdapter(Context context, List<String> subcategories, boolean[] checked) {
super(context, android.R.layout.simple_list_item_1);
this.subcategories = subcategories;
this.checked = checked;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
convertView = inflater.inflate(R.layout.form_checkbox_item, parent, false);
TextView textView = (TextView) convertView.findViewById(R.id.textView1);
CheckBox cb = (CheckBox) convertView.findViewById(R.id.checkBox1);
textView.setText(checkboxItems.get(position));
// Set state
cb.setChecked(checked[position]);
// Register listener
cb.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
checked[position] = cb.isChecked();
}
});
return convertView;
}
#Override
public int getCount() {
return subcategories.size();
}
#Override
public DTOSubcategoria getItem(int position) {
return subcategories.get(position);
}
public void selectAll() {
selectAll(true);
notifyDataSetChanged();
}
public void selectNone() {
selectAll(false);
notifyDataSetChanged();
}
void selectAll(boolean selected) {
for (int i = 0; i < checked.length; i++) {
checked[i] = selected;
}
}
public boolean isChecked(int index) {
return checked[index];
}
}
NOTE: Once you fix your adapter, consider modifying it to use the ViewHolder pattern and so improve performance.
One way is having a list of booleans in your adapter which represents the state of every checkbox. You need to init that to false and then with a setCheckbox method change the state of a specific checkbox
public class CheckboxAdapter extends ArrayAdapter
{
Context context;
List<Boolean> checkboxState;
List<String> checkboxItems;
public CheckboxAdapter(Context context, List<String> resource)
{
super(context, R.layout.form_checkbox_item ,resource);
this.context = context;
this.checkboxItems = resource;
this.checkboxState = new ArrayList<Boolean>(Collections.nCopies(resource.size(), true));
}
public View getView(int position, View convertView, ViewGroup parent){
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
convertView = inflater.inflate(R.layout.form_checkbox_item, parent, false);
TextView textView = (TextView) convertView.findViewById(R.id.textView1);
CheckBox cb = (CheckBox) convertView.findViewById(R.id.checkBox1);
textView.setText(checkboxItems.get(position));
cb.setChecked(checkboxState.get(position));
return convertView;
}
This method let you control which checkboxes are actived
void setChecked(boolean state, int position)
{
checkboxState.set(position, state);
}
I want to use custom ListView in extends from ListFragment class. After create new subClass extends from BaseAdapter into current class and set layout to that I get ... has stopped error.
list_fragment.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"
android:orientation="vertical"
>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/txt1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"/>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/txt2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"/>
</LinearLayout>
ResivedSMS.java :
public class ResivedSMS extends ListFragment {
private String testArray1[];
private String testArray2[];
private ListView listFragment;
public ResivedSMS() {
testArray1 = new String[] {
"1111111111",
"2222222222",
"3333333333",
"4444444444",
"5555555555",
"6666666666",
};
testArray1 = new String[] {
"AAAAA",
"BBBBB",
"CCCCC",
"DDDDD",
"FFFFF",
"GGGGG",
};
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
listFragment = (ListView) inflater.inflate(
R.layout.list_fragment, container, false);
ViewResivedSMSDetailes customListView = new ViewResivedSMSDetailes(getActivity(),testArray1,testArray2);
listFragment.
setAdapter( customListView );
return listFragment;
}
#Override
public void onListItemClick(ListView list, View v, int position, long id) {
Toast.makeText(getActivity(), getListView().getItemAtPosition(position).toString(), Toast.LENGTH_LONG).show();
}
class ViewResivedSMSDetailes extends BaseAdapter
{
private LayoutInflater inflater;
private String[] values1;
private String[] values2;
private class ViewHolder {
TextView txt1;
TextView txt2;
}
public ViewResivedSMSDetailes(Context context,String[] values1,String[] values2)
{
this.values1=values1;
this.values2=values2;
inflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return values1.length;
}
#Override
public Object getItem(int index) {
return values1[index];
}
#Override
public long getItemId(int arg0) {
return arg0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
if(convertView ==null){
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.list_fragment, null);
holder.txt1 = (TextView)convertView.findViewById(R.id.txt1);
holder.txt2 = (TextView)convertView.findViewById(R.id.txt2);
convertView.setTag(holder);
}
holder = (ViewHolder) convertView.getTag();
holder.txt1.setText(values1[position]);
holder.txt2.setText(values2[position]);
return convertView;
}
}
}
logcat Result:
08-24 10:33:34.675 349-349/ir.tsms E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.ClassCastException: android.widget.LinearLayout
at ir.tsms.ResivedSMS.onCreateView(ResivedSMS.java:50)
ResivedSMS.java:50 is:
listFragment = (ListView) inflater.inflate(
R.layout.list_fragment, container, false);
Whats my code problem and how to resolved Thanks?
problem:
inflater.inflate(R.layout.list_fragment, container, false);
You are inflating a LinearLayout not a ListView thus giving you ClassCastException
solution:
Since you are using ListFragment you can directly set the adapter, since ListFragment has its own default ListView. Set the adapter in the onCreate Method.
sample:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewResivedSMSDetailes customListView = new ViewResivedSMSDetailes(getActivity(),testArray1,testArray2);
setListAdapter( customListView ); //call the method if listFragment
}