I am a new android developer and I need your help. I created a simple listview. User can add some item in listview (type in EditText and click on Button "OK"). When user made onItemClick , the app will strike out text and set background green.
But then , when I add one more item,I see that it applies that strike out and background option from previously item.
Can you advise me what I need to do in this situation? How to improve it?
package com.example.boytsov.foodbasketapp;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Boytsov on 23.07.2015.
*/
public class ProductList extends Activity implements View.OnClickListener,AdapterView.OnItemClickListener,AdapterView.OnItemLongClickListener,TextView.OnEditorActionListener {
EditText myText;
ListView lvMain;
ArrayList<String> catnames;
ArrayAdapter<String> adapter;
Button button;
DataBase db;
final String LOG_TAG = "myLogs";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.productlist);
db = new DataBase(this);
myText = (EditText)findViewById(R.id.editText);
lvMain = (ListView) findViewById(R.id.lvMain);
button=(Button)findViewById(R.id.button);
catnames= new ArrayList<String>();
// создаем адаптер
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, catnames);
// присваиваем адаптер списку
lvMain.setAdapter(adapter);
lvMain.setOnItemClickListener(this);
lvMain.setOnItemLongClickListener(this);
// Прослушиваем нажатия клавиш
button.setOnClickListener(this);
//слушаем edittext
myText.setOnEditorActionListener(this);
}
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.button : {
//TextView myText = (TextView) view;
catnames.add(0, myText.getText().toString());
adapter.notifyDataSetChanged();
//myText.setBackgroundColor(Color.TRANSPARENT);
//myText.setPaintFlags(0);
Log.d("Insert: ", "Inserting ..");
db.addProduct(new Product(myText.getText().toString()));
myText.setText("");
Log.d("Reading: ", "Reading all contacts..");
List<Product> products = db.getAllProducts();
for (Product cn : products) {
String log = "Id: "+cn.getID_product()+" ,Name: " + cn.getName_product();
// Writing Contacts to log
Log.d("Name: ", log);
}
}
break;
}
}
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
TextView textview= (TextView) view;
if (textview.getPaintFlags() != 16){
textview.setPaintFlags(16);
textview.setBackgroundColor(Color.parseColor("#77dd77"));
Toast.makeText(this, "Куплено", Toast.LENGTH_SHORT).show();
adapter.notifyDataSetChanged();
Log.d(LOG_TAG, "itemClick: position = " + i + ", id = "
+ l);
} else {
textview.setPaintFlags(0);
textview.setBackgroundColor(Color.TRANSPARENT);
Toast.makeText(this, "Не куплено", Toast.LENGTH_SHORT).show();
}
}
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
catnames.remove(position);
adapter.notifyDataSetChanged();
Toast.makeText(this, "Удалено", Toast.LENGTH_SHORT).show();
Log.d(LOG_TAG, "onItemClick: position = " + position + ", id = "
+ id);
return true;
}
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
boolean handled = false;
if (actionId == EditorInfo.IME_ACTION_SEND) {
Log.d(LOG_TAG, "onItemClick: position = " + actionId + ", id = "
+ event);
handled = true;
}
return handled;
}
}
You apply your changes on the view at position 0.
When you add your item you also add it to position 0, hence the entire list is pushed down by 1 and the new item get the already changed view.
Edited Answer
Sorry, I was short on time, but now I can address it more thoroughly.
One important thing you must understand is that the view which shows your data in the list view DOES NOT NECESSARILY correspond with your data.
If you click on an item in your list and change it's views attributes, it doesn't change the state for the item or object which represents the data, but the view itself.
For example if you click on item at position 0 it will change the view's background at position 0. Then, in your example, you add an item at the top of the list, which puts the newly created object at position 0 (with the already modified view) and pushes THE REST OF THE ALREADY CREATED DATA by one, And you end up with an already changed view at position 0 with new data at position 0.
What you should do is as follows:
1)Make sure your object has a boolean member which states if item is "strike out" or not. like for example mIsStrikeOut.
2)create a custom adapter from any android adapter, like from ArrayAdapter.
3)Override it's getView method, for example:
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View view = convertView;
if (view == null)
{
view = (LinearLayout) inflater.inflate(R.layout. simple_list_item_1, parent, false);
}
TextView textview = (TextView) view.findViewById(R.id.text1);
if (catnames.get(position).isStrikeOut())
{
textview.setPaintFlags(16);
textview.setBackgroundColor(Color.parseColor("#77dd77"));
Toast.makeText(this, "Куплено", Toast.LENGTH_SHORT).show();
Log.d(LOG_TAG, "itemClick: position = " + i + ", id = "
+ l);
}
else
{
textview.setPaintFlags(0);
textview.setBackgroundColor(Color.TRANSPARENT);
Toast.makeText(this, "Не куплено", Toast.LENGTH_SHORT).show();
}
return view;
}
Side note:
When you query your data from your DB make sure the order is correct, I would suggest ORDER BY id dec or something like that.
I do not really know if this is the right answer but it is a suggestion :
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.button : {
//TextView myText = (TextView) view;
catnames.add(0, myText.getText().toString());
View view = listView.getChildAt(0);
TextView textview= (TextView) view;
textview.setBackgroundColor(Color.TRANSPARENT);
adapter.notifyDataSetChanged();
//myText.setBackgroundColor(Color.TRANSPARENT);
//myText.setPaintFlags(0);
Log.d("Insert: ", "Inserting ..");
db.addProduct(new Product(myText.getText().toString()));
myText.setText("");
Log.d("Reading: ", "Reading all contacts..");
List<Product> products = db.getAllProducts();
for (Product cn : products) {
String log = "Id: "+cn.getID_product()+" ,Name: " + cn.getName_product();
// Writing Contacts to log
Log.d("Name: ", log);
}
}
break;
}
}
Related
I have a big problem deleting a group from an ExpandableListView. Even after google a lot and trying a lot of tutorials and examples I was not able to solve it.
Though I have a lot of programming experiences I am relative knew to Android programming. So I am sure there are many things in the source which are not yet well done. But as of now I wanted to focus on the problem with a wrong view after deleting a group from the list.
To give a good overview to the problem here are some screenshots
Start of the App
List after click to the button List All Budgets
All Groups Expandet
Before delete the last child of the last group
Remaining group show children twice
Last group this time with two children
Before deleting the last children of the last group
Correct result after deleting last child of last group
I hope the problem becomes clear. If the last group has only one child and this was deleted the whole group will be deleted by the app - but than the children of the first group show up twice.
During a debugging session I checked all the ressources behind the data and they are all ok. If I go back to MainActivity and start the list again the view ist totally correct. So it must be a problem of an incorrect population after deleting a whole group.
As you can see if I only delete the last child from a last group with two childs the populating of the whole list is correct.
Here are some more information about the app:
I use a room database with two tables holding the data.
One tabel contains the categories with name and id and the other tabel is for single budget records with the category id as an foreign key
In onCreate of the BudgetListActivity I created two DAO's budgetDAO and categoryDAO to get the data and fill the lists allBudgetsList and all CatList.
With this informations I create a new array List allGroups with the structure I need for the view
- Categories as header
- budgets as children due to the foreign key
(just one remark here:
meanwhile I tried already using a hashmap for the data given to the ExpandableListAdapter - but the result was the same wrong view population!)
There is a contentView "budget_expandable_list" which is set to the ExpandableListAdapter. The adapter should populate the groups and childs for this list using the data from the ArrayList "allGroups"
This is the structure of the app
It could be that there are some ressources which are not used actually.
I will give now the soure code for the importand classes
BudgetListActivity:
package com.wbapps.WBEasyBudgetManagement;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.CoordinatorLayout;
import android.support.v7.app.AppCompatActivity;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ExpandableListView;
import android.widget.Toast;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class BudgetListActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
CoordinatorLayout coordinatorLayout;
private SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
//wb, 23Oct2018: now using an array list for the expandable list adapter
ArrayList<Group> allGroups = new ArrayList();
private ArrayAdapter adapter;
private final int REQUEST_CODE_EDIT = 1;
private BudgetDAO budgetDAO;
private CategoryDAO categoryDAO;
List<Budget> allBudgetsList;
List<Category> allCatsList;
ExpandableListView expListView;
List<String> expListViewTitle;
ExpandableListAdapter expAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.budget_expandable_list);
if (allGroups.size() > 0 ) {allGroups.clear();}
//get instances for DAO's of db from MainActivity
budgetDAO = MainActivity.getBudgetDAO();
categoryDAO = MainActivity.getCategoryDAO();
//the list for budgets and categories
allBudgetsList = budgetDAO.getBudgets();
allCatsList = categoryDAO.getCategories();
//temporary Group-Object for the ArrayList allGroups
Group tmpGroup;
double sumExpenses = 0;
//Start with reading all categories
for (int i=0;i<allCatsList.size(); i++) {
String tmpCat = allCatsList.get(i).getCategory();
tmpGroup = new Group(tmpCat);
sumExpenses = 0.0;
//now read all budgets for the current category and fill the rest of the temporary Group-Object
for (int j=0;j<allBudgetsList.size();j++){
if (allBudgetsList.get(j).getCategoryId() == allCatsList.get(i).getId()){
//tmpGroup.budgetId = allBudgetsList.get(j).getId();
tmpGroup.catId = allBudgetsList.get(j).getCategoryId();
tmpGroup.children.add(Arrays.asList
(
" Date: " + sdf.format(allBudgetsList.get(j).getDateTime())
+ " - Expenses: " + Double.toString(allBudgetsList.get(j).getExpenses()),
Long.toString(allBudgetsList.get(j).getId())
)
);
sumExpenses = sumExpenses + allBudgetsList.get(j).getExpenses();
tmpGroup.sumExpenses = sumExpenses;
}
}
//if at least one children for the current category was found
// =>> write all the group information the the array list
if (tmpGroup.children.size() > 0 ) {allGroups.add(tmpGroup);}
}
expListView = (ExpandableListView) findViewById(R.id.expandableList);
expAdapter = new ExpandableListAdapter(this, allGroups);
expListView.setAdapter(expAdapter);
expListView.setOnItemClickListener(this);
registerForContextMenu(expListView);
}
#Override
public void onCreateContextMenu(ContextMenu contMenu, View v,
ContextMenu.ContextMenuInfo contextMenuInfo) {
super.onCreateContextMenu(contMenu, v, contextMenuInfo);
ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) contextMenuInfo;
int type = ExpandableListView.getPackedPositionType(info.packedPosition);
int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
int childPosition = ExpandableListView.getPackedPositionChild(info.packedPosition);
// Show context menu for groups
if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
contMenu.setHeaderTitle("Budget");
contMenu.add(R.string.context_editBudget);
contMenu.add(R.string.context_delBudget);
// Show context menu for children
} else if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
contMenu.setHeaderTitle("Child");
contMenu.add(R.string.context_editChild);
contMenu.add(R.string.context_delChild);
}
}
#Override
public boolean onContextItemSelected(MenuItem item) {
Integer tmpInt = item.getItemId();
ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) item
.getMenuInfo();
int type = ExpandableListView.getPackedPositionType(info.packedPosition);
int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
int childPosition = ExpandableListView.getPackedPositionChild(info.packedPosition);
//TextView vItem = info.targetView.findViewById(R.id.context_editBudget);
if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
//Toast.makeText(this, "Click auf Group: " + Integer.toString(item.getGroupId()), Toast.LENGTH_SHORT).show();
if (item.getTitle().toString().equals(getString(R.string.context_editBudget))){
Toast.makeText(this, "Edit Budget clicked in Budget Context Menu", Toast.LENGTH_SHORT).show();
}
if (item.getTitle().toString().equals(getString(R.string.context_delBudget))){
int size = allGroups.get(groupPosition).children.size();
for (int i = 0; i<size; i++) {
budgetDAO.delAllBudgetsForCategory(allGroups.get(groupPosition).catId);
}
allGroups.remove(groupPosition);
//expAdapter.notifyDataSetChanged();
if (allGroups.size() == 0){
Intent intent = new Intent(BudgetListActivity.this, MainActivity.class);
startActivity(intent);
}
}
}
if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
if (item.getTitle().toString().equals(getString(R.string.context_editChild))){
Toast.makeText(this, "Edit Child clicked in Child Context Menu", Toast.LENGTH_SHORT).show();
}
if (item.getTitle().toString().equals(getString(R.string.context_delChild))){
//wb, 27Oct2018: Delete the selected child for a budget with given category
budgetDAO.delBudgetChildForCategory(Integer.parseInt(allGroups.get(groupPosition).children.get(childPosition).get(1)));
allGroups.get(groupPosition).children.remove(childPosition);
//expAdapter.notifyDataSetChanged();
//wb, 28Oct2018: If no more budget rows available delete the whole budget for category
if (allGroups.get(groupPosition).children.size() == 0) {
allGroups.remove(groupPosition);
//expAdapter.notifyDataSetChanged();
//expAdapter.notifyDataSetChanged();
if (allGroups.size() ==0){
Intent intent = new Intent(BudgetListActivity.this, MainActivity.class);
startActivity(intent);
}
}
/*
else {
//allGroups.get(groupPosition).sumExpenses = 0.0;
//allGroups.get(groupPosition) = expAdapter.getSum(groupPosition)
for (int i = 0; i < allBudgetsList.size(); i++) {
if (allBudgetsList.get(i).getCategoryId() == allGroups.get(groupPosition).catId) {
allGroups.get(groupPosition).sumExpenses =
allGroups.get(groupPosition).sumExpenses + allBudgetsList.get(i).getExpenses();
}
}
}*/
}
}
expAdapter.notifyDataSetChanged();
//return super.onContextItemSelected(item);
return true;
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Budget budget = (Budget)adapter.getItem(position);
editEntry(budget, position);
}
private void editEntry(Budget budget, int position) {
Intent intent = new Intent(this, EditBudgetActivity.class);
intent.putExtra("position", position);
startActivityForResult(intent, REQUEST_CODE_EDIT);
}
}
As you can see I use a context menu for editing and deleting groups and/or childs. Some features are not yet fully implemented. Please understand that I will first focus on my main problem with the correct population of the ExpandableView.
Also other things - like the incorrect update of the summery of the expences after deleting a child - are not yet very important and will be done later.
Here the class for a Group Object:
package com.wbapps.WBEasyBudgetManagement;
import java.util.ArrayList;
import java.util.List;
public class Group {
public long budgetId;
public long catId;
public String category;
public final List<List<String>> children = new ArrayList<List<String>>();
public final List<Long> BudIds = new ArrayList<Long>();
public double sumExpenses;
public Group(String pcategory) {
category = pcategory;
}
}
Here is the ExpandableListAdapter source:
package com.wbapps.WBEasyBudgetManagement;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.CheckedTextView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Currency;
import java.util.Locale;
public class ExpandableListAdapter extends BaseExpandableListAdapter{
Context context;
Locale locale;
Currency curr;
//array list to take the data for the list from the activity
private final ArrayList<Group> allGroups;
public LayoutInflater inflater;
public AppCompatActivity activity;
public int times = 0;
//Constructor for ExpandableListAdapter
//public ExpandableListAdapter(AppCompatActivity act, SparseArray<Group> groups) {
public ExpandableListAdapter(AppCompatActivity act, ArrayList<Group> allGroups) {
this.activity = act;
this.allGroups = allGroups;
inflater = act.getLayoutInflater();
}
#Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
times = times + 1;
Log.d("Info getGroupView","In getGroupView " + Integer.toString(times) + " times");
for (Locale wbLocale : Locale.getAvailableLocales()) {
//Log.d("LOCALES", wbLocale.getLanguage() + "_" + wbLocale.getCountry() + " [" + wbLocale.getDisplayName() + "]");
if (wbLocale.getCountry().equals("PH")) {
curr = Currency.getInstance(wbLocale);
curr.getSymbol(wbLocale);
break;
}
}
if (convertView == null || convertView.findViewById(R.id.tvCatGroup)==null){
convertView = inflater.inflate(R.layout.list_row_group, null);
}
convertView = inflater.inflate(R.layout.list_row_group, null);
String tmpCat = allGroups.get(groupPosition).category;
Group tmpGroup = new Group(tmpCat);
sortList();
Group group = (Group) getGroup(groupPosition);
//((CheckedTextView) convertView).setText(group.category + "\nTotal Expenses: " + group.sumExpenses + " " + curr.getSymbol());
((CheckedTextView) convertView).setText(group.category + "\nTotal Expenses: " + getSum(groupPosition) + " " + curr.getSymbol());
((CheckedTextView) convertView).setChecked(isExpanded);
return convertView;
}
/* wb, 18Sep2017: sort the list_selectedShoppingItems list */
public void sortList() {
Collections.sort(allGroups, new Comparator<Group>() {
#Override
public int compare(Group content1, Group content2) {
/* ignore case sensitivity */
return content1.category.compareToIgnoreCase(content2.category);
}
});
}
#Override
public View getChildView(int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent)
{
if(childPosition < getChildrenCount(groupPosition)-1) {
//holds the detail string for one child
final String children = (String) getChild(groupPosition, childPosition);
if (convertView == null || convertView.findViewById(R.id.tvChildRow)==null)
convertView = inflater.inflate(R.layout.list_row_details, null);
convertView = inflater.inflate(R.layout.list_row_details, null);
TextView txtChildRow = (TextView)convertView.findViewById(R.id.tvChildRow);
txtChildRow.setText(children + " " + curr.getSymbol());
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(activity, children + " " + curr.getSymbol(),
Toast.LENGTH_SHORT).show();
}
});
}
//children is the last one
if(childPosition == getChildrenCount(groupPosition)-1)
{
if (convertView == null || convertView.findViewById(R.id.tvSum)==null)
convertView = inflater.inflate(R.layout.listview_footer,null);
TextView txtFooter = (TextView)convertView.findViewById(R.id.tvSum);
//txtFooter.setText("Total expenses: " + allGroups.get(groupPosition).sumExpenses + " " + curr.getSymbol() );
txtFooter.setText("Total expenses: " + getSum(groupPosition) + " " + curr.getSymbol() );
//Log.e(TAG, "getChildView - sumExpenses: "+txtFooter.getText().toString());
}
convertView.setLongClickable( true);
return convertView;
}
#Override
public Object getChild(int groupPosition, int childPosition) {
return allGroups.get(groupPosition).children.get(childPosition).get(0);
}
public Object getSum(int groupPosition) {
return allGroups.get(groupPosition).sumExpenses;
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return 0;
}
//Add 1 to childCount. The last row is used as footer to childView
#Override
public int getChildrenCount(int groupPosition) {
return allGroups.get(groupPosition).children.size() +1;
}
#Override
public Object getGroup(int groupPosition) {
return allGroups.get(groupPosition);
}
#Override
public int getGroupCount() {
return allGroups.size();
}
#Override
public void onGroupCollapsed(int groupPosition) {
super.onGroupCollapsed(groupPosition);
}
#Override
public void onGroupExpanded(int groupPosition) {
super.onGroupExpanded(groupPosition);
}
#Override
public long getGroupId(int groupPosition) {
return 0;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
}
Some remarks might be helpful:
- in getChildrenCount I added 1 to the number of size because I use one last children as a footer to show the summary of expenses
for a better understanding here is a picture of the list "allGroups"
I hope I could support you with all the neccessary informations. Please let me know if some is missing. I will add it soon.
Hopefully there is someone out there with a solution for me.
Have a nice day
Andreas
meanwhile I found the reason for that behaviour. There is a method "getGroupID" at the end of the source code of the adapter. The return value here was set to 0 which caused the trouble. It has to be set to the groupPosition and then it works!
#Override
public long getGroupId(int groupPosition) {
/* wb, 10Nov2018: this statement was due to the error of deleting a last child of a group
With "return 0" the children of the remaining group was shown twice !!!
return 0;
*/
return groupPosition;
}
This is hopefully helpful to all who also run into this problem.
Have a nice time
Andreas
Using list view in Android application that uses a ToggleButton to record number of times it has been pressed and display the number on each click. I can't get the View object in order to set the text using setText() to the new number each time. I can get the position using tags, but it seems to give a null pointer exception each time I use that to get the View object that I want. Maybe I am going about this completely wrong, but I can't seem to figure it out.
package com.eventappucsd.activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.v4.app.FragmentManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import com.eventappucsd.backend.Event;
import java.util.List;
public class EventsCustomAdapter extends ArrayAdapter<Event> {
private LayoutInflater mLayoutInflater;
private static FragmentManager sFragmentManager;
private ContentResolver mContentResolver;
private Context mContext;
private final String LOG_TAG = EventsCustomAdapter.class.getSimpleName();
public EventsCustomAdapter(Context context, FragmentManager fragmentManager){
super(context, android.R.layout.simple_list_item_2);
mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
sFragmentManager = fragmentManager;
}
#Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
View view;
if(convertView == null) {
//custom event layout
view = mLayoutInflater.inflate(R.layout.custom_event, parent, false);
} else {
view = convertView;
}
final Event event = getItem(position);
final int _id = event.getId();
final String name = event.getEventName();
final String date = event.getDate();
final String time = event.getTime();
final String location = event.getLocation();
final String description = event.getDescription();
final int numVotes = event.getNumVotes();
((TextView) view.findViewById(R.id.event_name)).setText(name);
((TextView) view.findViewById(R.id.event_date)).setText(date);
((TextView) view.findViewById(R.id.event_location)).setText(location);
((TextView) view.findViewById(R.id.event_numVotes)).setText(numVotes + " Votes");
//get the context so that the object called is not null for db updates
mContentResolver = getContext().getContentResolver();
/*
make the event clickable and transition into the ViewActivity
*/
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//setting up the data needed to be made available by the ViewEventActivity.class
Intent eventView = new Intent(getContext(), ViewEventActivity.class);
eventView.putExtra(EventsContract.EventsColumns.EVENTS_ID, String.valueOf(_id));
eventView.putExtra(EventsContract.EventsColumns.EVENTS_NAME, name);
eventView.putExtra(EventsContract.EventsColumns.EVENTS_DATE, date);
eventView.putExtra(EventsContract.EventsColumns.EVENTS_TIME, time);
eventView.putExtra(EventsContract.EventsColumns.EVENTS_LOCATION, location);
eventView.putExtra(EventsContract.EventsColumns.EVENTS_DESCRIPTION,description);
getContext().startActivity(eventView);
}
});
final ToggleButton upvoteButton = (ToggleButton) view.findViewById(R.id.upbtn);
// Needed in order to have both the button and the list item clickable
upvoteButton.setFocusable(false);
upvoteButton.setFocusableInTouchMode(false);
upvoteButton.setClickable(true);
upvoteButton.setTag(position);
upvoteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final int position = (Integer)view.getTag();
Log.d(LOG_TAG, "position of view: " + position + "\n");
//get the view that was clicked
view = view.findViewWithTag(view.getTag());
ContentValues values = new ContentValues();
int recordsUpdated = 0;
if(upvoteButton.isChecked()) {
Toast.makeText(getContext(), "Thank you for voting ", Toast.LENGTH_SHORT).show();
int newVotes = numVotes;
++newVotes;
values.put(EventsContract.EventsColumns.EVENTS_NUM_VOTES, String.valueOf(newVotes));
Uri uri = EventsContract.Events.buildEventUri(String.valueOf(event.getId()));
recordsUpdated = mContentResolver.update(uri, values, null, null);
//TODO: display the new vote;
((TextView) view.findViewById(R.id.event_numVotes)).setText(newVotes + " Votes");
Log.d(LOG_TAG, "number of records updated = " + recordsUpdated + " newVotes: " + newVotes);
} else {
//TODO: decrease vote
((TextView) view.findViewById(R.id.event_numVotes)).setText(numVotes + " Votes");
values.put(EventsContract.EventsColumns.EVENTS_NUM_VOTES, String.valueOf(numVotes));
Uri uri = EventsContract.Events.buildEventUri(String.valueOf(event.getId()));
recordsUpdated = mContentResolver.update(uri, values, null, null);
Log.d(LOG_TAG, "number of records updated = " + recordsUpdated + "newVotes: " + numVotes);
}
}
});
return view;
}
public void setData(List<Event> events){
clear();
if(events != null){
for(Event event : events){
add(event);
}
}
}
}
The error thrown by the compiler shows that the null pointer exception happens at:
11-28 15:29:51.881 9724-9724/com.eventappucsd.mikesapplication E/AndroidRuntime: FATAL EXCEPTION: main
11-28 15:29:51.881 9724-9724/com.eventappucsd.mikesapplication E/AndroidRuntime: Process: com.eventappucsd.mikesapplication, PID: 9724
11-28 15:29:51.881 9724-9724/com.eventappucsd.mikesapplication E/AndroidRuntime: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
Fixed it with this code. The problem seemed to be my old parameter
public void onClick(View view)
This was confusing syntax-wise, because it is meant to represent a different value than the View view that is outside of the OnClick method. The view in the getView method is what I needed in order to set the text in the TextView.
final ToggleButton upvoteButton = (ToggleButton) view.findViewById(R.id.upbtn);
upvoteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.upbtn:
ContentValues values = new ContentValues();
int recordsUpdated = 0;
if(upvoteButton.isChecked()) {
Toast.makeText(getContext(), "Thank you for voting ", Toast.LENGTH_SHORT).show();
int newVotes = numVotes;
++newVotes;
//display the new vote count
((TextView) view.findViewById(R.id.event_numVotes)).setText(newVotes + " Votes");
//update
values.put(EventsContract.EventsColumns.EVENTS_NUM_VOTES, String.valueOf(newVotes));
Uri uri = EventsContract.Events.buildEventUri(String.valueOf(event.getId()));
recordsUpdated = mContentResolver.update(uri, values, null, null);
Log.d(LOG_TAG, "number of records updated = " + recordsUpdated + " newVotes: " + newVotes);
}else {
//revert view for vote count
((TextView) view.findViewById(R.id.event_numVotes)).setText(numVotes + " Votes");
values.put(EventsContract.EventsColumns.EVENTS_NUM_VOTES, String.valueOf(numVotes));
Uri uri = EventsContract.Events.buildEventUri(String.valueOf(event.getId()));
recordsUpdated = mContentResolver.update(uri, values, null, null);
Log.d(LOG_TAG, "number of records updated = " + recordsUpdated + " newVotes: " + numVotes);
}
break;
default:
}
}
});
I am a new android developer and I need your help.
I created a simple listview. I add items in this listview through the keyboard.
Moreover I add action on item. When user click "OK" the app will be strike out text and set background green.
But when I add the next item,I see that it applies that strike out and background option from previously item.
Can you advise me what I need to do in this situation? How to improve it?
My Code:
package com.example.boytsov.foodbasketapp;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
/**
* Created by Boytsov on 23.07.2015.
*/
public class ProductList extends Activity implements View.OnClickListener,AdapterView.OnItemClickListener,AdapterView.OnItemLongClickListener {
EditText myText;
ListView lvMain;
ArrayList<String> catnames;
ArrayAdapter<String> adapter;
Button button;
final String LOG_TAG = "myLogs";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.productlist);
lvMain = (ListView) findViewById(R.id.lvMain);
myText = (EditText) findViewById(R.id.editText);
button=(Button)findViewById(R.id.button);
catnames= new ArrayList<String>();
// создаем адаптер
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, catnames);
// присваиваем адаптер списку
lvMain.setAdapter(adapter);
lvMain.setOnItemClickListener(this);
lvMain.setOnItemLongClickListener(this);
// Прослушиваем нажатия клавиш
button.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.button :
catnames.add(0, myText.getText().toString());
adapter.notifyDataSetChanged();
myText.setText("");
myText.setBackgroundColor(Color.TRANSPARENT);
myText.setPaintFlags(0);
break;
}
}
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Log.d(LOG_TAG, "itemClick: position = " + i + ", id = "
+ l);
TextView textview= (TextView) view;
if (textview.getPaintFlags() != 16){
textview.setPaintFlags(16);
textview.setBackgroundColor(Color.parseColor("#77dd77"));
Toast.makeText(this, "Куплено", Toast.LENGTH_SHORT).show();
} else {
textview.setPaintFlags(0);
textview.setBackgroundColor(Color.TRANSPARENT);
}
}
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
catnames.remove(position);
adapter.notifyDataSetChanged();
Toast.makeText(this, "Удалено", Toast.LENGTH_SHORT).show();
Log.d(LOG_TAG, "onItemClick: position = " + position + ", id = "
+ id);
return true;
}
}
every listview item has its own R.id.editText so having one global myText = (EditText) findViewById(R.id.editText); does not work.
Instead you have to find the edit in the onClick handler
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.button : {
// EditText myText = (EditText) view.findViewById(R.id.editText);
TextView myText = (TextView) view;
catnames.add(0, myText.getText().toString());
adapter.notifyDataSetChanged();
myText.setText("");
myText.setBackgroundColor(Color.TRANSPARENT);
myText.setPaintFlags(0);
}
break;
}
}
[Update 28.7.2015]
Your adapter is using android.R.layout.simple_list_item_1 :
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, catnames);
wich does not have an EditText with id R.id.editText. therefore you get an exception.
simple_list_item_1 is a textview. using
TextView myText = (TextView) view;
might work
I am developing an application in which i am having a custom list view with custom adapter. The adapter contains image view, text view and other view. I want to swipe the list item to delete it from list. The link i refereed are as :
Ans having High vote
One row is looks like.
1 = Image view.
2 = Text view
The swipe is working but it is not smooth. When i swipe at bottom that time row deleted else the swipe is not properly working.
Please suggest me what i am missing or what changes i need to do or add or apply.
package com.example.android.swipedismiss;
import android.app.ListActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Arrays;
public class MainActivity extends ListActivity {
ArrayAdapter<String> mAdapter;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set up ListView example
String[] items = new String[20];
for (int i = 0; i < items.length; i++) {
items[i] = "Item " + (i + 1);
}
mAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
android.R.id.text1,
new ArrayList<String>(Arrays.asList(items)));
setListAdapter(mAdapter);
ListView listView = getListView();
// Create a ListView-specific touch listener. ListViews are given special treatment because
// by default they handle touches for their list items... i.e. they're in charge of drawing
// the pressed state (the list selector), handling list item clicks, etc.
SwipeDismissListViewTouchListener touchListener =
new SwipeDismissListViewTouchListener(
listView,
new SwipeDismissListViewTouchListener.DismissCallbacks() {
#Override
public boolean canDismiss(int position) {
return true;
}
#Override
public void onDismiss(ListView listView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions) {
mAdapter.remove(mAdapter.getItem(position));
}
mAdapter.notifyDataSetChanged();
}
});
listView.setOnTouchListener(touchListener);
// Setting this scroll listener is required to ensure that during ListView scrolling,
// we don't look for swipes.
listView.setOnScrollListener(touchListener.makeScrollListener());
// Set up normal ViewGroup example
final ViewGroup dismissableContainer = (ViewGroup) findViewById(R.id.dismissable_container);
for (int i = 0; i < items.length; i++) {
final Button dismissableButton = new Button(this);
dismissableButton.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
dismissableButton.setText("Button " + (i + 1));
dismissableButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,
"Clicked " + ((Button) view).getText(),
Toast.LENGTH_SHORT).show();
}
});
// Create a generic swipe-to-dismiss touch listener.
dismissableButton.setOnTouchListener(new SwipeDismissTouchListener(
dismissableButton,
null,
new SwipeDismissTouchListener.DismissCallbacks() {
#Override
public boolean canDismiss(Object token) {
return true;
}
#Override
public void onDismiss(View view, Object token) {
dismissableContainer.removeView(dismissableButton);
}
}));
dismissableContainer.addView(dismissableButton);
}
}
#Override
protected void onListItemClick(ListView listView, View view, int position, long id) {
Toast.makeText(this,
"Clicked " + getListAdapter().getItem(position).toString(),
Toast.LENGTH_SHORT).show();
}
}
full source code on githib and also tested
This is my code for click on a customlistview. When I click on the header, it works but after header its not working. CustomAdapter is another class in my App where I have defined header and all variables of listview. Please help me to resolve this problem.
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.Html;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
public class ProbabilityConditional extends Activity {
String htmlcodefor_root = "√", htmlcodefor_multiply = "×",
htmlcodefor_divide = "÷", htmlcodefor_underroot = "�B3";
ListView listView1;
String htmlcodefor_space = " ", htmlcodefor_pi = "Π",
htmlcodefor_largespace = " ";
String htmlcodefor_implies = "⇒";
String htmlcodefor_i = "ᵢ";
String htmlcodefor_angle = "θ";
String htmlcodefor_overline = "‾", htmlcodefor_plusminus = "±";
// TextView txtv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// txtv = (TextView)findViewById(R.id.txtTitle);
// txtv.setText(Html.fromHtml("1.(constant)<sup><small>0</></> = 1"));
listView1 = (ListView) findViewById(R.id.listView1);
CustomAdapter.formula_one_custom_adapter_class_var = Html.fromHtml("1 ");
CustomAdapter.formula_two_custom_adapter_class_var = Html.fromHtml("2 ");
CustomItemCall formula_data[] = new CustomItemCall[] {
new CustomItemCall(CustomAdapter.formula_one_custom_adapter_class_var),
new CustomItemCall(CustomAdapter.formula_two_custom_adapter_class_var),
};
CustomAdapter adapter = new CustomAdapter(this,R.layout.listview_item_row, formula_data);
View header = (View) getLayoutInflater().inflate(R.layout.listview_header_row, null);
listView1.addHeaderView(header);
listView1.setAdapter(adapter);
listView1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
System.out.println(position);
Toast.makeText(ProbabilityConditional.this,position + " " , Toast.LENGTH_LONG).show();
// When clicked, show a toast with the TextView text
if (position == 1) {
startActivity(new Intent(ProbabilityConditional.this,ProbabilityConditionalDiscrete.class));
} if (position == 2) {
startActivity(new Intent(ProbabilityConditional.this,ProbabilityConditionalContinuous.class));
}
}
});
}
}
make your listview focusable true add these line in your xml android:focusable="true"
and make other item of list make false android:focusable="false "
listView1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
System.out.println(position);
Toast.makeText(ProbabilityConditional.this,position + " " , Toast.LENGTH_LONG).show();
// When clicked, show a toast with the TextView text
if (position == 1) {
startActivity(new Intent(ProbabilityConditional.this,ProbabilityConditionalDiscrete.class));
} if (position == 2) {
startActivity(new Intent(ProbabilityConditional.this,ProbabilityConditionalContinuous.class));
}
}
});
write code like this, simple way:-
ListView list;
list.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView parent, View view,
int position, long id)
{
//if in future you need to start a new activity
//then add below line also in your activity
Intent in = new Intent(MainActivity.this, SecondActivity.class);
startActivity(in);
}
});