I have an activity that draws some icons on the view.
It sets a list and listAdapter in onCreate().
I have extracted to public method the code that assign the list to my adapter.
So that external code, can call the UI thread and assign new list to the adapter and make it notify the change via notifyDataSetChange()
However the new icons are not drawn, but only after leaving and getting back to the Activity.
How can I fix this?
I have tried adapter.clear()
and doubled checked the UI thread runs this code.
what else?
public class CategoriesActivity extends ActivityBase {
private Category[] categories;
SettingValueAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_values);
((TitleBar)findViewById(R.id.theTitleBar)).init(this,DisplayStrings.DS_CATEGORIES);
adapter = new SettingValueAdapter(this);
DriveToNativeManager nativeManager = DriveToNativeManager.getInstance();
nativeManager.getCategories(new CategoriesListener() {
#Override
public void onComplete(Category[] aCategories) {
categories = aCategories;
refreshListIcons();
}
});
final ListView list = (ListView)findViewById(R.id.settingsValueList);
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
..
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
..
}
public void refreshListIcons() {
NativeManager nativeManager = AppService.getNativeManager();
SettingsValue[] values = new SettingsValue[categories.length];
for (int i = 0; i < categories.length; i++) {
values[i] = new SettingsValue(categories[i].value, nativeManager.getLanguageString(categories[i].displayString), false);
values[i].icon = ResManager.GetSkinDrawable(categories[i].iconName + ".bin");
}
adapter.setValues(values);
}
}
public class SettingValueAdapter extends BaseAdapter {
private SettingsValue[] values;
private LayoutInflater inflater;
public SettingValueAdapter(Context context) {
inflater = LayoutInflater.from(context);
}
...
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.settings_item, null);
}
SettingsValue item = values[position];
CheckedTextView name = (CheckedTextView) convertView.findViewById(R.id.itemText);
ImageView iconView = (ImageView) convertView.findViewById(R.id.itemIcon);
if (iconView != null && (item != null) && (item.icon != null)) {
iconView.setImageDrawable(item.icon);
iconView.setVisibility(View.VISIBLE);
} else {
iconView.setVisibility(View.GONE);
}
name.setText(item.display);
name.setChecked(item.isSelected);
View container = convertView.findViewById(R.id.itemContainer);
if (position == 0) {
..
return convertView;
}
public void setValues(SettingsValue[] values) {
this.values = values;
notifyDataSetChanged();
}
}
You should extend ArrayAdapter instead of BaseAdapter:
http://developer.android.com/reference/android/widget/ArrayAdapter.html
This class is suitable for Arrays and Collections and it handles correctly all concerns regarding internal state.
In this case use clear followed by addAll at Adapter object itself before call notifyDataSetChanged. Another aproach is to change the Array or Collection bound to your Adapter.
I've found a very well done tutorial here:
http://www.vogella.com/articles/AndroidListView/article.html
Hope it helps !! Best regards !!
A dirty hack to do this, in case you are having too much problems getting the new notification and in case you dont have a significant amount of data in the adapter, you can always create a new adapter and assign it to the list list.setAdapter(adapter); forcing the list to render it over again from scratch...
Regards!
I don't think you can update the memory location of the list powering your adapter during runtime. This isn't allowed:
this.values = values;
If you know that the number of items won't change, use this piece of code:
public void setValues(SettingsValue[] values) {
for (int i = 0; i < values.length; i++) {
this.values[i] = values[i];
}
notifyDataSetChanged();
}
Otherwise you will need to create a new adapter every time you call setValues and update your listview by pointing to the new adapter. I'll try to link to the article where I read this when I find it. Hope this works.
Related
I made an GridView to organize TextView and Edit views, like a table , programatically, using an CustomAdapter. In getView() override method i create the views, add it to a arrayList and let the abstraction do its job. The problem arises when i try to acess the views outside the adapter class, in this case, in OnCreate of the activity. I was trying to get the array through getItems() method which returns the arrayList of views. But it returns am empty array (i check with a log that prints 0). And i'm wondering why is that happening? maybe the getView() methods runs only after i try to get the array in onCreate, somehow the onCreate finishes before the adapter is fully ready?
and if that's the case, where/when should i get the views?
Here's my activity and adapter class:
public class MatrizMultiplicationActivity extends AppCompatActivity {
MatrizGridAdapter gridAdapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_matriz_mult);
GridView gridView = (GridView) findViewById(R.id.grid_view);
gridView.setNumColumns(5);
gridAdapter = new MatrizGridAdapter(this,5,5);
gridView.setAdapter(gridAdapter);
ArrayList<EditText> matrix = gridAdapter.getItems();
Log.d("mSize", String.valueOf(matrix.size()));
}
public class MatrizGridAdapter extends BaseAdapter {
Context ctx;
int rows;
int coluns;
int size;
ArrayList<EditText> views;
public MatrizGridAdapter(Context ctx, int rows, int coluns)
{
this.ctx = ctx;
this.rows= rows;
this.coluns = coluns;
this.size = rows*coluns;
this.views = new ArrayList<EditText>();
}
// .. some methods
public ArrayList<EditText> getItems()
{
return views;
}
#Override
public int getCount() {
return size;
}
#Override
public EditText getItem(int position) {
if((views.size()<position))
{
return views.get(position);
}
return null;
}
#SuppressLint("ResourceAsColor")
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView==null)
{
CardView cardview = new CardView(ctx);
//code for setting CardView attributes
//...
//..
//layout logic, doesn't really matter
if(position==0)
{
TextView textView = new TextView(ctx);
//code for setting textView attributes
cardview.addView(textView);
cardview.setBackgroundColor(R.color.cinzarrom);
}
//layout logic, doesn't really matter
//it is the first row, so put the numbers of coluns above
else if(position<coluns)
{
//code for setting textView attributes
//...
//..
cardview.addView(textView);
cardview.setBackgroundColor(R.color.cinzarrom);
setMarginLeft(textView, MyMath.convertDpToPixels(20,ctx));
}
//it is the first colun in any row, so put the number of rows on the left
else if(position%coluns==0)
{
//code for setting textView attributes
cardview.addView(textView);
cardview.setBackgroundColor(R.color.cinzarrom);
setMarginLeft(textView, MyMath.convertDpToPixels(20,ctx));
}
//ARE THE VIEWS BEING ADDED BEFORE THE CALL TO ARRAY.SIZE?()
else {
EditText editText = new EditText(ctx);
//add it to the array who stores the text views
views.add(editText);
//code for setting textView attributes
cardview.setBackgroundColor(Color.BLUE);
cardview.addView(editText);
}
return cardview;
}
return convertView;
}
}
I have a RecyclerView that contains expandable items. clicking on an item expands it. The problem is it also expand some other cards, unexpectedly. I checked everything and I couldn't find why is this happening, but I did manage to find out that the clicked item always somehow has the same id as the other expanded item. The error occurs only when the list is big enough, so I think it has something to do with the RecyclerViews functionality. Also using notifyDataSetChanged() works, but it eliminates the animations, and I want the layout to be animated...
this question looks to discuss the same problem I'm facing... but yet I don't know how to solve it.
I couldn't understand why is this happening or how to fix this... below are some images and code to help you understand better, and maybe see if the problem is in the code...
this is the RecyclerView:
An expanded card item looks like this:
Here's my Adapters class:
public class ActiveGoalsAdapter extends RecyclerView.Adapter<ActiveGoalsAdapter.ActiveGoalsViewHolder> {
private Context context;
private Cursor cursor;
private ArrayList<Goal> activeGoals;
private static boolean[] openedFromParent = new boolean[]{false, true}, editing = new boolean[]{false};
public ActiveGoalsAdapter(Context context, ArrayList<Goal> activeGoals, Cursor cursor) {
this.context = context;
this.activeGoals = activeGoals;
this.cursor = cursor;
}
public class ActiveGoalsViewHolder extends RecyclerView.ViewHolder {
public LinearLayout shrunkContainer, subGoalsTitleContainer;
public RelativeLayout expandedContainer, subGoalsRecyclerViewContainer, btnDelete, btnCancel, btnSave;
public ConstraintLayout editPanel;
public CustomProgressBar shrunkProgressBar, expandedProgressBar;
public ImageButton btnExpandShrink, btnEdit, btnBackToParent;
public TextView title, description;
public RecyclerView subGoalsRecyclerView;
public ExtendedEditText nameET, descriptionET;
public ActiveGoalsViewHolder(#NonNull View itemView) {
super(itemView);
shrunkContainer = itemView.findViewById(R.id.shrunk_active_goal_container);
expandedContainer = itemView.findViewById(R.id.expanded_active_goal_container);
editPanel = itemView.findViewById(R.id.edit_panel);
btnExpandShrink = itemView.findViewById(R.id.active_goal_expand_shrink_btn);
btnEdit = itemView.findViewById(R.id.active_goal_edit_btn);
btnBackToParent = itemView.findViewById(R.id.active_goal_back_to_parent_btn);
shrunkProgressBar = itemView.findViewById(R.id.shrunk_active_goal_progress_bar);
shrunkProgressBar.enableDefaultGradient(true);
title = itemView.findViewById(R.id.expanded_active_goal_title);
expandedProgressBar = itemView.findViewById(R.id.expanded_active_goal_progress_bar);
expandedProgressBar.enableDefaultGradient(true);
description = itemView.findViewById(R.id.expanded_active_goal_description);
subGoalsTitleContainer = itemView.findViewById(R.id.expanded_active_goal_sub_goals_title_container);
subGoalsRecyclerViewContainer = itemView.findViewById(R.id.expanded_active_goal_sub_goals_container);
subGoalsRecyclerView = itemView.findViewById(R.id.expanded_active_goal_sub_goals_recyclerview);
nameET = itemView.findViewById(R.id.expanded_active_goal_edit_name_edit_text);
descriptionET = itemView.findViewById(R.id.expanded_active_goal_edit_description_edit_text);
btnDelete = itemView.findViewById(R.id.edit_delete_button);
btnCancel = itemView.findViewById(R.id.edit_cancel_button);
btnSave = itemView.findViewById(R.id.edit_save_button);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (expandedContainer.getVisibility() == View.VISIBLE) {
shrink();
} else {
expand();
}
}
});
}
private void expand(){
TransitionManager.beginDelayedTransition((ViewGroup) itemView.getRootView(), new AutoTransition());
expandedContainer.setVisibility(View.VISIBLE);
shrunkProgressBar.setVisibility(View.INVISIBLE);
}
private void shrink(){
TransitionManager.beginDelayedTransition((ViewGroup) itemView.getRootView(), new AutoTransition());
expandedContainer.setVisibility(View.GONE);
shrunkProgressBar.setVisibility(View.VISIBLE);
}
}
#NonNull
#Override
public ActiveGoalsViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.active_goal_card, parent, false);
return new ActiveGoalsViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ActiveGoalsViewHolder holder, int position) {
if (activeGoals.get(position) == null) {
return;
}
GoalDBHelper db = new GoalDBHelper(context);
Goal currentGoal = activeGoals.get(position);
Cursor subGoalsCursor = db.getSubGoalsCursorOf(currentGoal);
ArrayList<Goal> subGoalsArrayList = db.getSubGoalsArrayListOf(currentGoal);
String name = currentGoal.getName(),
description = currentGoal.getDescription(),
parent = currentGoal.getParentGoal();
int timeCounted = currentGoal.getTimeCounted(),
timeEstimated = currentGoal.getTimeEstimated();
for (Goal subGoal : activeGoals) {
if (subGoal.getParentGoal().equals(name)) {
subGoalsArrayList.add(subGoal);
}
}
holder.shrunkProgressBar.setText(name);
holder.shrunkProgressBar.setProgress((timeCounted * 100 / timeEstimated));
holder.shrunkProgressBar.setRadius(300.0f);
holder.expandedProgressBar.setText("");
holder.expandedProgressBar.setProgress((timeCounted * 100 / timeEstimated));
holder.expandedProgressBar.setRadius(300.0f);
holder.title.setText(name);
holder.description.setText(description);
if (subGoalsArrayList.size() <= 0) {
holder.subGoalsTitleContainer.setVisibility(View.GONE);
holder.subGoalsRecyclerViewContainer.setVisibility(View.GONE);
} else {
holder.subGoalsTitleContainer.setVisibility(View.VISIBLE);
holder.subGoalsRecyclerViewContainer.setVisibility(View.VISIBLE);
initSubGoalsAdapter(holder.subGoalsRecyclerView, subGoalsArrayList, subGoalsCursor);
}
if (openedFromParent[0]) {
holder.btnBackToParent.setVisibility(View.VISIBLE);
} else {
holder.btnBackToParent.setVisibility(View.GONE);
}
}
public void initSubGoalsAdapter(RecyclerView subGoalsRecyclerView, ArrayList<Goal> subGoals, Cursor subGoalsCursor) {
GoalsAdapter adapter = new GoalsAdapter(context, subGoals, subGoalsCursor);
final CarouselLayoutManager layoutManager = new CarouselLayoutManager(CarouselLayoutManager.VERTICAL, false);
layoutManager.setPostLayoutListener((CarouselLayoutManager.PostLayoutListener) new CarouselZoomPostLayoutListener());
subGoalsRecyclerView.setLayoutManager(layoutManager);
subGoalsRecyclerView.setHasFixedSize(true);
subGoalsRecyclerView.setAdapter(adapter);
}
#Override
public int getItemCount() {
return activeGoals.size();
}
public void swapCursor(Cursor newCursor) {
if (cursor != null) {
cursor.close();
}
cursor = newCursor;
if (newCursor != null) {
notifyDataSetChanged();
}
}
}
Where is the problem? and how should I fix it?
Help would be highly appreciated
The problem is that RecyclerView reuses ViewHolders during scrolling. For example on position 10 it can uses ViewHolder from position 2 (let's imagine this item was expanded) and if you don't bind expanded / collapsed state for ViewHolder on position 10 it will have expanded state. So to solve the problem you have to track ViewHolder state and update ViewHolder every onBindViewHolder method calling.
Here is a good answer related to selection in RecyclerView and you will have almost the same logic for expanded / collapsed states.
https://stackoverflow.com/a/28838834/9169701
I'm not familiar with the utilities you're using for animation. But, you can do something like this to track and update the visibility of your views:
private ArrayList<MyData> dataList;
private ArrayList<boolean> itemStates; // Create a list to store the item states
public MyAdapter(ArrayList<MyData> myData){
dataList = myData;
itemStates = new ArrayList<>();
// Build the default state values for each position
for(MyData data: dataList){
itemStates.add(false);
}
}
#Override
public void onBindViewHolder(MyHolder holder, int position){
// Whatever you need to do on each item position ...
final boolean visible = itemStates.get(position);
// Set the visibility of whichever view you want
if(visible){
holder.myView.setVisibility(View.VISIBLE);
}else{
holder.myView.setVisibility(View.GONE);
}
// Change the visibility after clicked
holder.itemView.setOnClickListener(new View.OnClickListener(){
// Use the ViewHolder's getAdapterPosition()
// to retrieve a reliable position inside the click callback
int pos = holder.getAdapterPosition();
if(visible){
// Play the hide view animation for this position ...
}else{
// Play the show view animation for this position ...
}
// Set the new item state
itemStates.set(pos, !visible);
// Refresh the Adapter after a delay to give your animation time to play
// (I've used 500 milliseconds here)
new Handler().postDelayed(new Runnable(){
#Override
public void run(){
notifyDataSetChanged();
}
}, 500);
});
}
You can refer to my code for the solution, maybe it'll help.
final boolean isExpanded = position == currentPosition;
holder.childLayout.setVisibility(isExpanded ? View.VISIBLE : View.GONE);
holder.itemView.setActivated(isExpanded);
Animation slideDown = AnimationUtils.loadAnimation(context, R.anim.slide_down_animation);
holder.childLayout.startAnimation(slideDown);
if (isExpanded)
currentPosition = position;
holder.parentLayout.setOnClickListener(v -> {
currentPosition = isExpanded ? -1 : position;
notifyItemChanged(currentPosition);
notifyItemChanged(position);
});
Hope this solves your problem.
Edit:
currentPosition is a variable which is assigned to -1 and it stores the current position of the item in the recyclerview.
position is the variable of the BindViewHolder
setActivated() is a method defined for view. You can check it here.
childLayout is the layout of the view that is shown after the expansion.
parentLayout is the layout on which you click to expand.
I apologize if this is similar to other threads, but I have yet to find a good solution on how to update the ListView in my custom ArrayAdapter.
I'm extending FragmentActivity in order to create a custom Dialog popup for adding / updating new List entries (which works fine), but I can't seem to get the ListView in ServerActivityArrayAdapter to update after a change is made.
Obviously, adapter.notifyDataSetChanged(); in the ServersActivity class isn't enough, but I'm stumped as to how to get my ListView to update after the Save button is clicked in the ServerDialog popup. Any help would be greatly appreciated!
public class ServersActivity extends FragmentActivity {
private List<Server> server;
private ListView lv;
private ServerActivityArrayAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.server_list);
server = getServers();
lv = (ListView) findViewById(android.R.id.list);
adapter = new ServerActivityArrayAdapter(this, R.layout.server_list_item, server);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
showServerDialog(position);
}
});
}
...
private void showServerDialog(int position) {
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
ServerDialog serverDialog = new ServerDialog(position);
ServerDialog.newInstance();
serverDialog.show(fragmentManager, "server_dialog");
}
ServerDialog class for adding new List entries
public class ServerDialog extends DialogFragment {
...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.settings_fragment, container);
context = getActivity().getApplicationContext();
dbh = new DbHandler(context);
etName = (EditText) view.findViewById(R.id.etName);
etAddress = (EditText) view.findViewById(R.id.etAddress);
etPort = (EditText) view.findViewById(R.id.etPort);
swtchNumDoors = (Switch) view.findViewById(R.id.swtchNumDoors);
Button btnSave = (Button) view.findViewById(R.id.btnSave);
loadData();
String title = (!newServer) ? "Edit Server" : "Add A New Server " + ID;
getDialog().setTitle(title);
btnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
server[ID] = String.valueOf(ID);
server[SERVER_NAME] = etName.getText().toString();
server[ADDRESS] = etAddress.getText().toString();
server[PORT] = etPort.getText().toString();
if (server[ADDRESS].isEmpty() || server[PORT].isEmpty()) {
Toast.makeText(context, "Invalid Entry", Toast.LENGTH_LONG).show();
} else {
saveData();
// TODO - notify ServersActivity of change
}
}
});
return view;
}
public class ServerActivityArrayAdapter extends ArrayAdapter<Server> {
private int layout;
private String[][] values;
private int defServer;
private static LayoutInflater inflater;
ServerActivityArrayAdapter class for displaying ListView
public ServerActivityArrayAdapter(Context context, int layout, List<Server> servers) {
super(context, layout, servers);
this.layout = layout;
int i = 0;
values = new String[servers.size()][5];
for (Server server : servers) {
values[i][0] = Integer.toString(server.id);
values[i][1] = server.name;
values[i][2] = server.address;
values[i][3] = Integer.toString(server.port);
values[i][4] = Integer.toString(server.num_doors);
defServer = (server.default_server) ? i : 0;
i++;
}
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
private static class ViewHolder {
private TextView tvServerName;
private CheckBox cbDefault;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View v = convertView;
try {
if(v == null) {
v = inflater.inflate(layout, parent, false);
holder = new ViewHolder();
holder.tvServerName = (TextView) v.findViewById(R.id.tvServerName);
holder.cbDefault = (CheckBox) v.findViewById(R.id.cbDefault);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
holder.tvServerName.setText(values[position][1]);
holder.cbDefault.setChecked(defServer==position);
} catch (Exception e){
System.out.println(e);
}
return v;
}
You could use an interface and have a method in it maybe named updateListView().
Implement this interface in your FragmentActivity. In the implemented method, add code to update the listView.
And in the button code of your dialog, call ((Interfacename) getActivity).updateListView()
Your problem is in the implementation of the adapter. You are instantiating the ArrayAdapter with a List<Server> object (The super call) but then creating your own two dimensional array values to contain the data. You use the values array for the getView() method yet make no mention or show through code how you actually modify that data to update the adapter.
You should be calling back into the adapter to update it. EG, calling add(), remove(), etc. You only mention updating the DB which has nothing to do with updating your adapter. It's not linked in anyway to the DB. Even if you were to call into the previously mentioned mutate methods on the adapter, they wouldn't work unless you specifically override them. The default ArrayAdapter implementation will modify the List<Server> data and not the values two-dim array you created.
But if you find yourself override those mutate methods to support your values two-dim array...there's no point in subclassing the ArrayAdapter. Part of the point of the ArrayAdapter is handling all the data management for you. In such a situation you should be instead subclassing BaseAdapter.
I'm trying to inflate a list using baseadapter within an activity. The list just doesn't inflate. From the logs implemented within the class, the getView() function doesn't even execute. Here's the code. -
public class CallLog extends Activity {
ListView logList;
List mList;
Context mCtx;
ArrayList<String> logName;
ArrayList<String> logNumber;
ArrayList<String> logTime;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.reject_call_log);
mCtx = getApplicationContext();
ListView logList = (ListView) findViewById(R.id.log_list);
mList = new List(mCtx, R.layout.log_row);
logList.setAdapter(mList);
SharedPreferences savedLogName = PreferenceManager.getDefaultSharedPreferences(mCtx);
SharedPreferences savedLogNumber = PreferenceManager.getDefaultSharedPreferences(mCtx);
SharedPreferences savedLogTime = PreferenceManager.getDefaultSharedPreferences(mCtx);
try{
logName = new ArrayList(Arrays.asList(TextUtils.split(savedLogName.getString("logName", null), ",")));
logNumber = new ArrayList(Arrays.asList(TextUtils.split(savedLogNumber.getString("logNumber", null), ",")));
logTime = new ArrayList(Arrays.asList(TextUtils.split(savedLogTime.getString("logTime", null), ",")));
Collections.reverse(logName);
Collections.reverse(logNumber);
Collections.reverse(logTime);
}catch(NullPointerException e){
e.printStackTrace();
//TextView noLog = (TextView)findViewById(R.id.no_log);
}
}
public class List extends BaseAdapter {
LayoutInflater mInflater;
TextView nameText;
TextView numberText;
TextView timeText;
int timePos = 1;
public List(Context context, int resource) {
}
#Override
public int getCount() {
return 0;
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (convertView == null) {
v = mInflater.inflate(R.layout.row, null);
}
nameText = (TextView) v.findViewById(R.id.log_name);
numberText = (TextView) v.findViewById(R.id.log_number);
timeText = (TextView) v.findViewById(R.id.log_time);
nameText.setText(logName.get(position));
numberText.setText(logNumber.get(position));
timeText.setText(logTime.get(timePos) + logTime.get(timePos+1));
Log.d("RejectCall", "ListView");
timePos+=2;
return v;
}
}
}
Where is it all going wrong? Also, is there a better way to do what I'm trying to do?
Please replace the following code :
#Override
public int getCount() {
return 0;
}
with
#Override
public int getCount() {
return logName.size();
}
As list view only show the numbers of rows that is returned by this method and right now you are returning 0;
And after fetching the data in arraylist please use adapter.notifyDataSetChanged() to notify the list view.
You have to call notifyDataSetChanged() as you are filling data in array list after setting the adapter. so to notify the list view that data has been changed you have to call notify method(as above)
Your getItem() and getCount() haven't been implemented. If you want any kind of adapter to work for the list, these need to be implemented. Your list is also not holding any actual data, so getItem() has nothing to set.
Don't forget to call notifiyDataSetChanged() in your adapter after you set appropriate implementations for the above two functions.
I'm new to android and I have following problem
I have a ListView. The ListView is filled with data from an ArrayList. I added a CheckBox to every row.
After clicking on a "Resume-Button" I want to write the selected items to a SQLliteDB (the db works fine - I tested it with static data).
My question is now:
How can I get the checked items from the list?
Thx everyone for help!
Best regards
kyp
You can use this ListView method getCheckedItemPositions() to get all the checked positions. Make sure that the child view in your ListView actually implements the Checkable interface otherwise the checkmark information will not be passed along to the ListView.
You can go through the list, using a for loop and getItemAtPosition(int).
For each row you just check if the item is checked, isChecked() for a checkbox. Without seeing the code that is as specific as I can get. If this is not clear enough then post some code about how/what items are stored in the listView
Hope this helps!
But i figured it out myself.
I only wanted to select the row by clicking on the checkBox view.
I modified my custom Array Adapter
Here is my code:
public class ContactAdapter extends ArrayAdapter<Contact> implements OnClickListener{
private static HashMap<Integer, Boolean> teamItems = new HashMap<Integer, Boolean>();
int count = 0;
private List<Contact> items;
private int mode;
CheckBox add_to_team;
static int counter = 3;
public ContactAdapter(Context context, int textViewResourceId, List<Contact> objects, int mode) {
super(context, textViewResourceId, objects);
// TODO Auto-generated constructor stub
this.context = context;
this.mode = mode;
this.items = objects;
}
#Override
public View getView(int position, View convertView, final ViewGroup parent) {
View v = convertView;
if(v == null) {
//get a reference to the LayoutInflator
LayoutInflater li = (LayoutInflater)getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//and inflate our XML into the View
v = li.inflate(R.layout.list_contacts_item, null);
}
String race = items.get(position).race;
String nick = items.get(position).nick;
String name = items.get(position).name;
final int pos = position;
if(v!= null) {
// Do the work for the other views
// MODE 1 = SELECTION-MODE
if(mode == 1) {
add_to_team.setVisibility(0);
try {
if(count!=0) {
boolean b = teamItems.get(pos);
if(b==false) {
add_to_team.setChecked(false);
}
else {
add_to_team.setChecked(true);
}
}
} catch (NullPointerException e) {
}
add_to_team.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
teamItems.put(pos, arg1);
count++;
}
});
} else {
add_to_team.setVisibility(8);
}
}
return v;
}
}
I added a HashMap in which I save the selected items. I can call the select state from my activity, by calling the HashMap... And it works great!