I'm working on an app (part of a project in school), and I have an activity, that consists of an ImageView, a SearchView, a ListView, and a Button.
I'm trying to put the button in front of the ListView, which was working gucci until I got to the actual making the button do something part.
After setting the onClick method, I noticed that the button didn't do anything. I tried just printing something using the button, but nothing worked. Also tried creating a new button, outside the ListView, but that also failed (also didn't cause the onClick event).
I am kinda clueless, and cannot think of anything that could've caused this problem...
xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/main_color"
android:orientation="vertical"
android:divider="#android:color/transparent"
android:dividerHeight="10.0sp"
android:layout_gravity="center"
tools:context=".SetupActivity">
<ImageView
android:layout_width="300dp"
android:layout_gravity="center"
android:layout_height="130dp"
android:layout_marginTop="13dp"
android:background="#drawable/setup_text"
android:id="#+id/setupText"
></ImageView>
<androidx.appcompat.widget.SearchView
android:layout_width="match_parent"
android:layout_height="65dp"
android:id="#+id/searchViewSetup"
android:theme="#style/AppTheme.Toolbar"
app:iconifiedByDefault="false"
></androidx.appcompat.widget.SearchView>
<RelativeLayout
android:layout_width="wrap_content"
android:paddingHorizontal="8dp"
android:layout_height="wrap_content">
<ListView
android:id="#+id/list_item"
android:layout_gravity="center"
android:layout_width="395dp"
android:divider="#android:color/transparent"
android:dividerHeight="10.0sp"
android:layout_height="wrap_content"
tools:listitem="#layout/activity_ingredients_layout"
android:paddingBottom="10.0sp"
android:clipToPadding="false"
android:scrollbars="none"
android:paddingTop="10.0sp">
</ListView>
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#drawable/setup_btn_shadow"
android:layout_marginLeft="287dp"
android:layout_marginTop="450dp"
android:alpha="0.5"
></ImageView>
<android.widget.Button
android:layout_width="73dp"
android:id="#+id/setup_floating_btn"
android:layout_height="73dp"
android:layout_marginLeft="300dp"
android:layout_marginTop="460dp"
android:foregroundGravity="bottom"
android:src="#drawable/ic_baseline_arrow_forward_ios_24"
android:background="#drawable/setup_btn"
></android.widget.Button>
</RelativeLayout>
</LinearLayout>
java:
package com.example.yummilyproject;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import com.example.yummilyproject.databinding.ActivitySetupFridgeBinding;
import java.util.ArrayList;
public class SetupActivity extends AppCompatActivity implements View.OnClickListener {
ActivitySetupFridgeBinding binding;
SearchView searchView;
ListView listView;
Button btn;
String[] ingredients = {"Avocado", "Tomato", "Pasta", "Cauliflower", "Egg", "Salmon", "Chicken", "Beef", "Broccoli", "Cheese", "Zucchini", "Lemon", "Sweet Potato", "Kale", "Carrot", "Black Beans", "Asparagus",
"Spinach", "Rice", "Potato", "Yoyo Beans"};
Boolean[] checkboxes = {false, false, false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false};
int[] images = {R.drawable.ic_launcher_foreground, R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,
R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,
R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,
R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_setup_fridge);
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
listView = findViewById(R.id.list_item);
searchView = findViewById(R.id.searchViewSetup);
btn = (Button) findViewById(R.id.setup_floating_btn);
btn.bringToFront();
btn.setOnClickListener(this);
binding = ActivitySetupFridgeBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
ArrayList<Ingredient> ingredientArrayList = new ArrayList<>();
for (int i = 0; i < images.length; i++) {
Ingredient ingredient = new Ingredient(ingredients[i], images[i], checkboxes[i]);
ingredientArrayList.add(ingredient);
}
ListAdapter listAdapter = new ListAdapter(SetupActivity.this, ingredientArrayList);
binding.listItem.setTextFilterEnabled(true);
binding.listItem.setAdapter(listAdapter);
binding.listItem.setClickable(true);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
listAdapter.getFilter().filter(query);
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
listAdapter.getFilter().filter(newText);
return false;
}
});
binding.listItem.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Ingredient ig = (Ingredient) parent.getItemAtPosition(position);
ig.setIngredientCheckBox(!ig.isIngredientCheckBox());
CheckBox cb = view.findViewById(R.id.ingredientChekcBox);
cb.setChecked(!cb.isChecked());
//cb.setChecked(!cb.isChecked());
}
});
}
#Override
public void onClick(View v) {
v.startAnimation(buttonClick);
if (v == findViewById(R.id.setup_floating_btn))
{
System.out.println("press btn");
String[] ingredientsList = new String[ingredients.length];
int cnt = 0;
for (int i = 0; i<ingredients.length; i++)
{
if (checkboxes[i] == true)
{
ingredientsList[cnt] = ingredients[i];
cnt++;
}
}
System.out.println(ingredientsList);
Intent intent = new Intent (this, MainActivity.class);
intent.putExtra("ingredientsList", ingredientsList);
}
}
private AlphaAnimation buttonClick = new AlphaAnimation(1F, 0.8F);
public class Ingredient
{
private String ingredientTitle;
private int ingredientPhoto;
private boolean ingredientCheckBox;
public Ingredient(String ingredientTitle, int ingredientPhoto, boolean ingredientCheckBox) {
this.ingredientTitle = ingredientTitle;
this.ingredientPhoto = ingredientPhoto;
this.ingredientCheckBox = ingredientCheckBox;
}
public String getIngredientTitle() {
return ingredientTitle;
}
public void setIngredientTitle(String ingredientTitle) {
this.ingredientTitle = ingredientTitle;
}
public int getIngredientPhoto() {
return ingredientPhoto;
}
public void setIngredientPhoto(int ingredientPhoto) {
this.ingredientPhoto = ingredientPhoto;
}
public boolean isIngredientCheckBox() {
return ingredientCheckBox;
}
public void setIngredientCheckBox(boolean ingredientCheckBox) {
this.ingredientCheckBox = ingredientCheckBox;
}
}
public class ListAdapter extends ArrayAdapter<Ingredient>
{
public ListAdapter (Context context, ArrayList<Ingredient> ingredientList)
{
super(context, R.layout.activity_ingredients_layout, ingredientList);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
Ingredient ingredient = getItem(position);
if (convertView == null)
{
convertView = LayoutInflater.from(getContext()).inflate(R.layout.activity_ingredients_layout, parent, false);
}
ImageView imageView = convertView.findViewById(R.id.ingredientPhoto);
TextView title = convertView.findViewById(R.id.ingredientTitle);
CheckBox cb = convertView.findViewById(R.id.ingredientChekcBox);
imageView.setImageResource(ingredient.ingredientPhoto);
title.setText(ingredient.ingredientTitle);
cb.setActivated(ingredient.ingredientCheckBox);
return convertView;
}
}
public void finish() {
super.finish();
overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right);
}
}
Your way of using equality is wrong. You cannot use == to see if two objects are equal to each other.
If you really want to use equals to verify it's the same object, you should do this instead:
if (v.equals(findViewById(R.id.setup_floating_btn)) {
// Do whatever you need to do when the button is clicked here.
}
While this can work, it's not the recommended way of verifying whether this was the View clicked. Instead you should check the clicked View's ID like this:
if (v.getId() == R.id.setup_floating_btn) {
// Do whatever you need to do when the button is clicked.
}
Have a look at the difference between equals and == here.
On a side-note: you're mixing things together here - ViewBindings with normal findViewById which is really bad and makes things very difficult to read. ViewBindings are meant to make it easier to inflate all views in a screen as well as making all references to views type-safe and making sure no views are null. You should probably read up on this too.
Also in your XML you use sp as units for dividerHeight and padding, which is completely wrong. sp units are used only for text and not for heights or paddings of views.
Also take a look at what bringToFront() does on a View and see if this really should apply/be used on your Button.
Related
I am learning to make a simple time table managing application.
I have a list of courses displayed. Each item in a list is a textview + a delete button. The onClick Listener in my list item isn't working as expected. When I click on the delete button, it is working fine. However, I want to open up some other activity when user clicks on the textview of the list item.
Code:
ShowAll.java (the main activity in which I am displaying a list of classes)
package com.example.android.mytimetable;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
public class ShowAll extends ActionBarActivity {
private ArrayAdapter<String> adapter ;
ArrayList <ClassDetail> classesDetail ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_all);
this.bindAdapter();
ListView listView = (ListView) this.findViewById(R.id.class_list);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Log.v("Item", "clicked");
Intent intent = new Intent(view.getContext(), ShowAllClicked.class);
ClassDetail classDetail = classesDetail.get(i);
Bundle bundle = new Bundle();
bundle.putString("CLASS_NAME", classDetail.class_name);
bundle.putString("BUILDING", classDetail.building);
bundle.putString("MONDAY_START", classDetail.monday_start);
bundle.putString("MONDAY_END", classDetail.monday_end);
bundle.putString("TUESDAY_START", classDetail.tuesday_start);
bundle.putString("TUESDAY_END", classDetail.tuesday_end);
bundle.putString("WEDNESDAY_START", classDetail.wednesday_start);
bundle.putString("WEDNESDAY_END", classDetail.wednesday_end);
bundle.putString("THURSDAY_START", classDetail.thursday_start);
bundle.putString("THURSDAY_END", classDetail.thursday_end);
bundle.putString("FRIDAY_START", classDetail.friday_start);
bundle.putString("FRIDAY_END", classDetail.friday_end);
intent.putExtras(bundle);
startActivity(intent);
}
});
}
void bindAdapter() {
DBHelper db = new DBHelper(this);
classesDetail = db.getClassesDetail();
ArrayList <String> classes = new ArrayList<>();
for(int i = 0 ; i < classesDetail.size() ; i++) {
Log.v("Adding ", classesDetail.get(i).class_name);
classes.add(classesDetail.get(i).class_name);
}
if(classes.size() == 0)
((TextView) this.findViewById(R.id.holiday)).setText(getString(R.string.noClass));
CustomArrayAdapter customArrayAdapter = new CustomArrayAdapter(classes, this);
((ListView) this.findViewById(R.id.class_list)).setAdapter(customArrayAdapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_show_all, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
return super.onOptionsItemSelected(item);
}
}
activity_show_all.xml (the xml layout of ShowAll.java)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="com.example.android.mytimetable.ShowAll"
android:orientation="vertical">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/class_list"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/holiday"/>
</LinearLayout>
CustomArrayAdapter.java (The custom array adapter file)
package com.example.android.mytimetable;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.TextView;
import java.util.ArrayList;
/**
* Created by Aman Goel on 02-08-2015.
*/
public class CustomArrayAdapter extends BaseAdapter implements ListAdapter {
private ArrayList <String> list = new ArrayList<String>();
private Context context;
public CustomArrayAdapter(ArrayList <String> list, Context context) {
this.list = list;
this.context = context;
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int pos) {
return list.get(pos);
}
#Override
public long getItemId(int pos) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
if(view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.list_item, null);
}
((TextView) view.findViewById(R.id.list_item)).setText(list.get(position));
Button deleteBtn = (Button) view.findViewById(R.id.delete);
deleteBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DBHelper db = new DBHelper(context);
db.deleteClass(list.get(position));
list.remove(position);
notifyDataSetChanged();
}
});
return view;
}
}
list_item.xml (The layout of each list view)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:id="#+id/list_item"
android:focusableInTouchMode="false"
android:clickable="false"
android:focusable="false"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/delete"
android:id="#+id/delete"/>
</LinearLayout>
I tried to take help from here: Set onClickListener into custom adapter and here: Where should I place the onClickListener on a Custom ListView?
However, I am still not able to make the adapter work. Any help would be appreciated
set on custom adapter getview function
TextView lst_tv=(TextView)view.findViewById(R.id.list_item);
lst_tv.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
customArrayAdapter.setOnItemClickListener(...)
I am using ListView with a custom ArrayAdapter, and everything is working fine when I run my app in AVD emulator, but when I install it on my phone my app crashes when I touch any ListView item.
Activity 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"
android:background="#drawable/login_background"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.frequentbuyer.ui.activity.ShoppingListListActivity" >
<ListView
android:id="#+id/shoppingListsListView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/addShoppingListButton"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:cacheColorHint="#00000000" >
</ListView>
<Button
android:id="#+id/addShoppingListButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignEnd="#+id/shoppingListsListView"
android:layout_alignParentBottom="true"
android:layout_alignRight="#+id/shoppingListsListView"
android:text="#string/add_shopping_list" />
</RelativeLayout>
List item xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/list_item_gradient" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentStart="true"
android:background="#drawable/border_rectangle_shape"
android:orientation="horizontal" >
<TextView
android:id="#+id/shoppingListName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:id="#+id/shoppingListItemsNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
</RelativeLayout>
Activity class
package com.frequentbuyer.ui.activity;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import roboguice.inject.ContentView;
import roboguice.inject.InjectExtra;
import roboguice.inject.InjectView;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
import com.frequentbuyer.R;
import com.frequentbuyer.exception.DataAccessException;
import com.frequentbuyer.model.ShoppingList;
import com.frequentbuyer.model.User;
import com.frequentbuyer.service.contract.IShoppingListService;
import com.frequentbuyer.ui.adapters.ShoppingListListViewAdapter;
import com.google.inject.Inject;
#ContentView(R.layout.activity_shoppinglist_list)
public class ShoppingListListActivity extends AbstractBaseActivity {
/* shopping list list activity UI components */
#InjectView(R.id.shoppingListsListView)
private ListView shoppingListsListView;
#InjectView(R.id.addShoppingListButton)
private Button addShoppingListButton;
/* shopping list list activity injected services */
#Inject
private IShoppingListService shoppingListService;
/* shopping list list activity received extras */
// received from login activity
#InjectExtra(ActivityParameterNames.AUTHENTICATED_USER)
User loggedInUser;
private List<ShoppingList> allShoppingLists;
/* activity events */
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initializeShoppingListView();
// add listeners
addListeners();
registerForContextMenu(shoppingListsListView);
}
#Override
public void onBackPressed() {
showExitDialog();
}
#Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {
if (view.getId() == R.id.shoppingListsListView) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
menu.setHeaderTitle(allShoppingLists.get(info.position).getName());
menu.add(Menu.NONE, 0, 0, R.string.delete_shopping_list);
}
}
#Override
public boolean onContextItemSelected(MenuItem item) {
try {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
long shoppingListToDeleteId = info.id;
shoppingListService.deleteShoppingList(this, shoppingListToDeleteId);
reloadCurrentActivity();
} catch (DataAccessException e) {
showErrorMessageDialog(e.getLocalizedMessage());
}
return true;
}
/* activity methods */
private void initializeShoppingListView() {
try {
allShoppingLists = shoppingListService.getAllShoppingListsForUser(ShoppingListListActivity.this, loggedInUser.getId());
// pass context and data to the custom shopping list list adapter
ShoppingListListViewAdapter shoppingListListViewAdapter = new ShoppingListListViewAdapter(this, allShoppingLists);
// set shopping list list adapter
shoppingListsListView.setAdapter(shoppingListListViewAdapter);
} catch (DataAccessException e) {
showErrorMessageDialog(e.toString());
}
}
private void addListeners() {
shoppingListsListView.setOnItemClickListener(shoppingListListItemOnClickListener);
addShoppingListButton.setOnClickListener(addShoppingListButtonOnClickListener);
}
/* activity listeners */
private OnItemClickListener shoppingListListItemOnClickListener = new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long shoppingListId) {
try {
HashMap<String, Serializable> activityParametersMap = new HashMap<String, Serializable>();
activityParametersMap.put(ActivityParameterNames.SELECTED_SHOPPING_LIST, shoppingListService.getShoppingListById(ShoppingListListActivity.this, shoppingListId));
activityParametersMap.put(ActivityParameterNames.AUTHENTICATED_USER, loggedInUser);
startAnotherActivity(ShoppingListListActivity.this, EditShoppingListActivity.class, activityParametersMap);
} catch (DataAccessException e) {
showErrorMessageDialog(e.getLocalizedMessage());
}
}
};
View.OnClickListener addShoppingListButtonOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
HashMap<String, Serializable> shoppingListListActivityParametersMap = new HashMap<String, Serializable>();
shoppingListListActivityParametersMap.put(ActivityParameterNames.AUTHENTICATED_USER, loggedInUser);
ShoppingListListActivity.startAnotherActivity(ShoppingListListActivity.this, CreateShoppingListActivity.class, shoppingListListActivityParametersMap);
}
};
}
Custom adapter class
package com.frequentbuyer.ui.adapters;
import java.util.List;
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import com.frequentbuyer.R;
import com.frequentbuyer.model.ShoppingList;
public class ShoppingListListViewAdapter extends ArrayAdapter<ShoppingList> {
private final Context context;
private final List<ShoppingList> shoppingLists;
public ShoppingListListViewAdapter(Context context, List<ShoppingList> shoppingLists) {
super(context, R.layout.shoppinglist_list_item, shoppingLists);
this.context = context;
this.shoppingLists = shoppingLists;
}
#SuppressLint("ViewHolder")
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// create inflater
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// get rowView from inflater
View rowView = inflater.inflate(R.layout.shoppinglist_list_item, parent, false);
// get the two text view from the rowView
TextView shoppingListNameView = (TextView) rowView.findViewById(R.id.shoppingListName);
// set the text for textView
shoppingListNameView.setText(shoppingLists.get(position).getName());
// get the two text view from the rowView
TextView shoppingListItemNumberView = (TextView) rowView.findViewById(R.id.shoppingListItemsNumber);
// set the text for textView
int shoppingListSize = shoppingLists.get(position).getShoppingItems().size();
shoppingListItemNumberView.setText("(" + shoppingListSize + " item" + (shoppingListSize == 1 ? ")" : "s)"));
// return rowView
return rowView;
}
#Override
public long getItemId(int position) {
return shoppingLists.get(position).getId();
}
}
In some previous version of the app I used ListView in the same way on my phone without any problems, and now it is causing my app to crash.
Any idea why this is happening?
I used USB debugging, and found NullPointerException in logcat. It was thrown in getItemId method of my custom adapter, because my entities had null value for id field in database, for some reason. I defined id fields by using ORMLite with:
#DatabaseField(generatedId = true)
private Long id;
I changed type of id fields from Long to int and reinstalled app on phone and it worked, id fields were populated.
I try to make a custom view but I've got a problem with the spinner.
When I launch the application everything is ok. Preferences are read and the spinner setSelection method work great (display picture is ok).
When I change the spinner value, there is no problem too : Preferences are saved and when I start the application the new choice is display.
My problem comes when rotating the device, all my spinner value are reset to the last spinner value (vv2 in my code). I really don't understand...
Here is my code :
The widget_value_view.xml
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" >
<Spinner
android:id="#+id/my_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:background="#android:color/transparent" />
<TextView
android:id="#+id/my_value_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_centerVertical="true"
android:background="#android:color/transparent" />
</merge>
The ValueView.java class :
package com.example.spinnertest;
import java.util.Arrays;
import java.util.List;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
public class ValueView extends LinearLayout {
protected TextView mValueTv = null;
protected Spinner mSpinner = null;
protected List<String> mChoiceList;
private MySpinnerAdapter mSpinnerAdapter;
public ValueView(Context context) {
super(context);
}
public ValueView(Context context, AttributeSet attributes){
super(context,attributes);
TypedArray a = context.getTheme().obtainStyledAttributes(attributes,R.styleable.ValueView,0, 0);
try {
String valueList = a.getString(R.styleable.ValueView_valueList);
mChoiceList = Arrays.asList(valueList.split("\\|"));
} finally {
a.recycle();
}
setOrientation(LinearLayout.HORIZONTAL);
setGravity(Gravity.CENTER_VERTICAL);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.widget_value_view, this, true);
mSpinner = (Spinner) getChildAt(0);
mValueTv = (TextView) getChildAt(1);
mSpinnerAdapter = new MySpinnerAdapter(context, mChoiceList);
mSpinner.setAdapter(mSpinnerAdapter);
}
/**
* Change textview value
*/
public void setValue(double value,String format){
mValueTv.setText("todo");
invalidate();
requestLayout();
}
/**
* Set the current item of the spinner
* #param position of the item
*/
public void setSelection(int position, boolean animate) {
// mSpinnerAdapter.notifyDataSetChanged();
mSpinner.setSelection(position,animate);
// invalidate();
// requestLayout();
}
public int getSelectedItemPosition() {
return mSpinner.getSelectedItemPosition();
}
}
In this class I use a adapter define with 2 layout and one class :
MySpinnerAdapter.java
package com.example.spinnertest;
import java.util.List;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class MySpinnerAdapter extends BaseAdapter {
public static final String ITEM_ALTITUDE = "altitude";
public static final String ITEM_SPEED = "speed";
public static final String ITEM_DISTANCE = "distance";
private static final String LOG_TAG = "SPINNER_TEST";
private Context mContext;
private List<String> mChoiceList;
public MySpinnerAdapter(Context context, List<String> values) {
this.mContext = context;
this.mChoiceList = values;
}
#Override
public int getCount() {
return mChoiceList.size();
}
#Override
public Object getItem(int position) {
return mChoiceList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater layout = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layout.inflate(R.layout.item_spinner_value, null);
}
ImageView imView = (ImageView) convertView.findViewById(R.id.item_spinner_value_iv);
Log.d(LOG_TAG,"Spinner Adapter position = " + String.valueOf(position));
imView.setImageResource(getSpinnerItemImage(position));
return convertView;
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater layout = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layout.inflate(R.layout.item_spinner_list, null);
}
ImageView imView = (ImageView) convertView.findViewById(R.id.item_spinner_list_iv);
TextView textView = (TextView) convertView.findViewById(R.id.item_spinner_list_tv);
textView.setText(mChoiceList.get(position));
imView.setImageResource(getSpinnerItemImageSmall(position));
return convertView;
}
private int getSpinnerItemImageSmall(int position) {
String item = mChoiceList.get(position);
if (item.equals(ITEM_ALTITUDE)) {
return R.drawable.altitude_small;
} else if (item.equals(ITEM_DISTANCE)) {
return R.drawable.distance_small;
} else if (item.equals(ITEM_SPEED)) {
return R.drawable.vitesse_small;
} else {
return R.drawable.date_small;
}
}
private int getSpinnerItemImage(int position) {
String item = mChoiceList.get(position);
if (item.equals(ITEM_ALTITUDE)) {
return R.drawable.altitude;
} else if (item.equals(ITEM_DISTANCE)) {
return R.drawable.distance;
} else if (item.equals(ITEM_SPEED)) {
return R.drawable.vitesse;
} else {
return R.drawable.date;
}
}
}
and the 2 layout item_spinner_list.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/item_spinner_list_iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:padding="5dp"
android:src="#android:drawable/ic_menu_gallery" />
<TextView
android:id="#+id/item_spinner_list_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:padding="5dp"
android:layout_toRightOf="#+id/item_spinner_list_iv"
android:text="Durée" />
</RelativeLayout>
and item_spinner_value.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent" >
<ImageView
android:id="#+id/item_spinner_value_iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:padding="5dp"
android:src="#android:drawable/ic_menu_gallery" />
</RelativeLayout>
and finally my MainActivity.java
package com.example.spinnertest;
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
public class MainActivity extends Activity {
private SharedPreferences mPref;
private ValueView mVv1;
private ValueView mVv2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
mVv1 = (ValueView)findViewById(R.id.value1);
mVv2 = (ValueView)findViewById(R.id.value2);
mVv1.setSelection(mPref.getInt("pref_val1", 0),false);
mVv2.setSelection(mPref.getInt("pref_val2", 1),false);
}
#Override
public void onPause() {
SharedPreferences.Editor editor = mPref.edit();
editor.putInt("pref_val1", mVv1.getSelectedItemPosition());
editor.putInt("pref_val2", mVv2.getSelectedItemPosition());
editor.commit();
super.onPause();
}
}
and the layout :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res/com.example.spinnertest"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.spinnertest.ValueView
android:id="#+id/value1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_margin="10dp"
android:background="#android:color/transparent"
custom:valueList="speed|altitude|distance" />
<com.example.spinnertest.ValueView
android:id="#+id/value2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/value1"
android:layout_margin="10dp"
custom:valueList="speed|altitude|distance" />
</RelativeLayout>
I cannot really explain why your code is not working, but I would prefer to save the state of the spinner locally (I mean in the activity); it's the normal Android workflow for screen rotation.
Something like this:
String MVV1="1";
String MVV2="2";
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
mPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
mVv1 = (ValueView)findViewById(R.id.value1);
mVv2 = (ValueView)findViewById(R.id.value2);
if (savedInstanceState != null) {
mVv1.setSelection(savedInstanceState.getInt(MVV1),false);
mVv2.setSelection(savedInstanceState.getInt(MVV2),false);
}
else{
mVv1.setSelection(mPref.getInt("pref_val1", 0),false);
mVv2.setSelection(mPref.getInt("pref_val2", 1),false);
}
}
#Override
public void onPause() {
SharedPreferences.Editor editor = mPref.edit();
editor.putInt("pref_val1", mVv1.getSelectedItemPosition());
editor.putInt("pref_val2", mVv2.getSelectedItemPosition());
editor.commit();
super.onPause();
}
#Override
protected void onSaveInstanceState (Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(MVV1, mVv1.getSelectedItemPosition());
outState.putInt(MVV2, mVv2.getSelectedItemPosition());
}
My syntax is maybe not perfect because I wrote it in the SO editor but hope you got the idea: the status is written in the Preferences as soon as the Activity is paused but if the activity rotates (your method should work but maybe is there a cache to access to the preferences or something...) then, it'll use the specific bundle for it: the one which is filled just when the screen rotates and used when the screen is recreated.
Test it and say if it's working ;)
I have an interface designed as a ListView (but I can change if needed). Each row has 2 buttons: MS and DROP.
Clicking on the buttons should affect only the corresponding row. For example, on the last row (where int "3" is displayed), clicking on MS should call function1(rowPosition) and clicking on DROP should call function2(rowPosition).
I have 2 problems:
Even without any click listener, clicking on any row activate both corresponding buttons. Maybe ListView is not the correct choice for this kind of interface.
I can't figure out how to implement the Click listener.
Here is the main code:
package com.thomas.calculation.app;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
public class Memory_listview extends Activity {
ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.memory_listview);
listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(new MyAdapter(this));
}
}
class MyAdapter extends BaseAdapter {
Context context;
ArrayList<String> singleRow_list;
MyAdapter(Context c) {
context = c;
singleRow_list = new ArrayList<String>();
for (int i=1; i<10; i++)
singleRow_list.add(i, Integer.toString(i) );
}
#Override
public int getCount() {
return singleRow_list.size();
}
#Override
public Object getItem(int i) {
return singleRow_list.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
class MyViewHolder
{
TextView myTextView;
MyViewHolder(View view) {
myTextView = (TextView) view.findViewById(R.id.textView);
}
}
#Override
public View getView(int i, View view, ViewGroup viewGroup)
{
View view_single_row = view;
MyViewHolder myViewHolder = null;
if (view_single_row==null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view_single_row = inflater.inflate(R.layout.memory_listview_row, viewGroup, false);
myViewHolder = new MyViewHolder(view_single_row);
view_single_row.setTag(myViewHolder);
}
else
{
myViewHolder = (MyViewHolder) view_single_row.getTag();
}
String newData = singleRow_list.get(i);
//This is not working:
//Button button_MS = (Button) findViewById(R.id.button_MS); //ERROR: findViewById undefined
//Button button_MS = (Button) this.findViewById(R.id.button_MS); //ERROR: findViewById undefined
//Button button_MS = (Button) view.findViewById(R.id.button_MS); //APP CRASH
//Button button_MS = (Button) view_single_row.findViewById(R.id.button_MS); //APP CRASH
//Button button_MS = (Button) viewGroup.findViewById(R.id.button_MS); //APP CRASH
myViewHolder.myTextView.setText(newData);
return view_single_row;
}
}
Here is the row.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#color/bgStack"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textView"
android:text=""
style="#style/memory_monitor"
android:weightSum="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_toLeftOf="#+id/linearView" />
<LinearLayout
android:id="#+id/linearView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentRight="true">
<TextView
android:id="#+id/button_MS"
style="#style/memory_tiny"
android:text="#string/calc_MS" />
<TextView
android:id="#+id/button_del"
style="#style/memory_tiny"
android:text="#string/calc_del" />
</LinearLayout>
</RelativeLayout>
Inside your getView.
MyViewHolder.button.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
// do for the other button too..
// yout methods here.
}
});
And change the TextView to Button in your xml
my app has custom ListView, each row contains checkbox ,edit text and 2 buttons. In the main xml layout file i have 1 submit button and listView. i want that, when i click on submit button, i should get all checked row position.I am new to android programming ,so plz help me my code is not working here is my code:
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button android:layout_height="wrap_content"
android:text="#string/button_submit"
android:layout_width="wrap_content"
android:id="#+id/main_submit_button" android:onClick="#string/button_submit"></Button>
<ListView
android:id="#+id/list_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
items.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout android:layout_height="wrap_content"
android:layout_width="fill_parent">
<TextView
android:layout_height="wrap_content"
android:layout_width="fill_parent" android:layout_weight="1"
android:id="#+id/items_name"
android:gravity="left"
android:textStyle="bold" />
<CheckBox android:id="#+id/items_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right"
/>
</LinearLayout>
<LinearLayout android:layout_height="wrap_content"
android:layout_width="fill_parent">
<Button android:id="#+id/items_add_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:text="#string/text_switcher_plus" />
<EditText android:digits="10"
android:textStyle="bold" android:gravity="left"
android:id="#+id/items_plates" android:layout_height="wrap_content"
android:layout_width="90dp"></EditText>
<Button android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/items_minus_button"
android:text="#string/text_switcher_minus"
android:gravity="right"
/>
</LinearLayout>
</LinearLayout>
VegmenuActivity
package com.sagar.resmenu;
import java.util.ArrayList;
import java.util.Arrays;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
// reference:http://pareshnmayani.wordpress.com/tag/android-custom-listview-example
public class VegmenuActivity extends Activity implements OnItemClickListener{
//dynamic array that contains names of items
private ArrayList<String> items = new ArrayList<String>
(Arrays.asList("Veg pulav", "Pav bhaji", "Panir tikka", "veg kolhapuri",
"Coconut Rice", "Curd rice", "Mint Pulao",
"Banana Custard","Basundi", "Cheese potato Tikkis",
"Dum aloo"));
private ArrayList<Integer> counter = new ArrayList<Integer>
(Arrays.asList(0, 0,0, 0, 0,0, 0,0, 0,0,0));
private SparseBooleanArray a;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final ListView lv =(ListView)findViewById(R.id.list_view);
// lv.setOnClickListener(null);
MyAdapter adapter = new MyAdapter(getApplicationContext(),items,counter);
lv.setAdapter(adapter);
lv.setItemsCanFocus(false);
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
Button submit1;
submit1 = (Button)findViewById(R.id.main_submit_button);
submit1.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
a = new SparseBooleanArray();
a.clear();
a = lv.getCheckedItemPositions();
int len = items.size();
for (int i = 0; i < len; i++)
{
if(a.valueAt(i) == true)
Log.d("Returned ", String.valueOf(a.valueAt(i)));
}
}
});
}
//private OnItemClickListener selectCat = new OnItemClickListener();
public void onItemClick(AdapterView<?> a, View v, int positon, long id) {
// TODO Auto-generated method stub
}
}
MyAdapter.java
package com.sagar.resmenu;
import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextSwitcher;
import android.widget.TextView;
public class MyAdapter extends BaseAdapter implements OnClickListener{
private LayoutInflater inflater;
private ArrayList<String> data;
VegmenuActivity m;
private ArrayList<Integer> counter;
public MyAdapter(Context context, ArrayList<String> data,ArrayList<Integer> counter) {
// TODO Auto-generated constructor stub
super();
// Caches the LayoutInflater for quicker use
this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Sets the events data
this.data= data;
this.counter=counter;
}
public int getCount() {
return this.data.size();
//return this.counter.size();
}
public String getItem(int position) throws IndexOutOfBoundsException{
return null;
}
public long getItemId(int position) throws IndexOutOfBoundsException{
return 0;
}
public int getViewTypeCount(){
return 1;
}
public static class ViewHolder
{
TextView items_name;
CheckBox items_check ;
Button items_plus_button;
Button items_minus_button;
EditText plates;
}
public View getView(int position, View convertView, ViewGroup parent){
//String myText = getItem(position);
ViewHolder holder;
if(convertView == null){ // If the View is not cached
// Inflates the Common View from XML file
holder = new ViewHolder();
convertView = this.inflater.inflate(R.layout.items,parent,false);
holder.items_name = (TextView) convertView.findViewById(R.id.items_name);
holder.plates = (EditText) convertView.findViewById(R.id.items_plates);
holder.items_check = (CheckBox) convertView.findViewById(R.id.items_check);
convertView.setTag(holder);
}
else
holder=(ViewHolder)convertView.getTag();
holder.items_name.setText(data.get(position));
holder.plates.setText(String.valueOf(counter.get(position)));
return convertView;
}
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
}
}
when I need check boxes inside listview, I often code as following:
MyAdapter.java:
- Declare an boolean array to mark which item is checked/unchecked:
....
boolean[] checked;
...
inside constructor:
checked = new boolean[data.size()];
- Inside getView()
{
.....
holder.items_check.setChecked(checked[position]);
holder.items_check.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
checked[position] = isChecked;
}
});
.....
- And method to get all checked items:
boolean[] getCheckedItems() {
return checked;
}
That's !
Could it be that your getItem and getItemId only return null and 1? These methods need to return the correct data for this to work I believe. getItem would need to be:
String getItem(int position)
{
return data.get(position);
}
and getItemId would simply return position instead of 0:
String getItemId(int position)
{
return position;
}