I have got a ListView with a custom UserAdapter, which holds a SparseBooleanArray with the currently activated (selected) Ids.
The method toggleSelection(position) creates or deletes an entry from my SparseBooleanArray.
So I have the possibility to call this method in my DriverFragment within the listView.onItemClickListener() and as a result the background drawable of the item changes on click.
Now i want to preselect one item in the DriverSelectionFragment programmatically.
So far i can add it to my SparseBooleanArray but the background doesn't change when entering the Fragment.
What am I missing? Do i have to notify the listView? I'm adding the selected item in onViewCreated(), so it should work.
EDIT: Added the xml files
The UserAdapter:
package com.example.convictedDriver.Adapters;
import android.content.Context;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.convictedDriver.Database.User;
import com.example.convictedDriver.R;
import com.mikhaellopez.circularimageview.CircularImageView;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class UserAdapter extends ArrayAdapter<User> {
// Declare Variables
private List<User> userList;
private ViewGroup parent;
private LayoutInflater inflater;
private SparseBooleanArray mSelectedItemsIds;
public UserAdapter(Context context, int resource, List<User> userList) {
super(context, resource, userList);
mSelectedItemsIds = new SparseBooleanArray();
this.userList = userList;
inflater = LayoutInflater.from(context);
}
private class ViewHolder {
TextView name;
TextView ratio;
CircularImageView circularImageView;
}
#Override
public View getView(int position, View view, #NotNull ViewGroup parent) {
final ViewHolder holder;
this.parent = parent;
if(view == null){
holder = new ViewHolder();
view = inflater.inflate(R.layout.list_item, null, false);
// Locate the TextViews and Imageview in list_item.xml
holder.name = view.findViewById(R.id.user_name_text);
holder.ratio = view.findViewById(R.id.user_ratio_text);
holder.circularImageView = view.findViewById(R.id.list_item_imageView);
view.setTag(holder);
}else{
holder = (ViewHolder) view.getTag();
}
// Capture position and set to the TextViews and ImageView
holder.name.setText(userList.get(position).getUsername());
holder.ratio.setText(String.valueOf((userList.get(position).getRatio())));
holder.circularImageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
return view;
}
#Override
public void remove(User user){
userList.remove(user);
notifyDataSetChanged();
}
public List<User> getUserList(){
return userList;
}
// Toggles the selection state of a given item position
public void toggleSelection(int position) {
selectView(position, !mSelectedItemsIds.get(position));
Log.i("Debug", "Position "+position+" changed state from "+!mSelectedItemsIds.get(position)+" to "+
mSelectedItemsIds.get(position));
}
// Removes all selections
public void removeSelection() {
mSelectedItemsIds = new SparseBooleanArray();
notifyDataSetChanged();
}
// Helper Class for toggling a specific item position
private void selectView(int position, boolean value) {
if (value) {
mSelectedItemsIds.put(position, value);
}
else {
mSelectedItemsIds.delete(position);
}
}
// Returns the amount of selected items
public int getCheckedCount() {
int num = 0;
for (int i = 0; i < mSelectedItemsIds.size(); i++) {
if (mSelectedItemsIds.valueAt(i)) {
num++;
}
}
return num;
}
// Returns the SparseBooleanArray for the ListView
public SparseBooleanArray getSelectedIds() {
return mSelectedItemsIds;
}
}
The DriverFragment:
package com.example.convictedDriver.Fragments.Drive;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.navigation.Navigation;
import com.example.convictedDriver.Adapters.UserAdapter;
import com.example.convictedDriver.Classes.MyListSorter;
import com.example.convictedDriver.Classes.MyToast;
import com.example.convictedDriver.Database.IntegratedDatabase.UserDbHelper;
import com.example.convictedDriver.Database.User;
import com.example.convictedDriver.R;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.ArrayList;
public class DriveFragment extends Fragment {
private FloatingActionButton fabContinue;
private ArrayList<User> userList;
private ListView listView;
private UserAdapter adapter;
private SparseBooleanArray checked;
public DriveFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_drive, container, false);
// Getting all the users out of the database and sort them
UserDbHelper db = UserDbHelper.getInstance(getContext());
userList = db.getAllUsers();
MyListSorter.sort(userList, MyListSorter.SortType.RATIO);
// Locate the ListView and in fragment_drive.xml
listView = view.findViewById(R.id.drive_listView);
fabContinue = view.findViewById(R.id.fab_continue);
return view;
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void onViewCreated(#NonNull View view, #Nullable final Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Pass userList to UserAdapter Class
adapter = new UserAdapter(getContext(), R.layout.list_item, userList);
// Binds the Adapter to the ListView
listView.setItemsCanFocus(false);
listView.setAdapter(adapter);
checked = adapter.getSelectedIds();
Toast.makeText(getContext(), "OnViewCreated: "+checked.toString(),Toast.LENGTH_SHORT).show();
// Capture ListView item click
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Toggle the ListViewItems State
adapter.toggleSelection(position);
Toast.makeText(getContext(), "OnItemClick: "+checked.toString(),Toast.LENGTH_SHORT).show();
}
});
/*
* Create an array out of the selectedUsers Arraylist and pass it
* towards DriveSelectionFragment
*/
fabContinue.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
checked = adapter.getSelectedIds();
Toast.makeText(getContext(), "OnClickListener: "+checked.toString(),Toast.LENGTH_SHORT).show();
if(adapter.getCheckedCount() > 2) {
User[] userArray = new User[checked.size()];
int j = 0;
for (int i = (checked.size() - 1); i >= 0; i--){
if (checked.valueAt(i)){
userArray[j] = adapter.getItem(checked.keyAt(i));
j++;
}
}
//listView.clearChoices();
adapter.removeSelection();
DriveFragmentDirections.ActionDriveFragmentToDriveSelectionFragment action =
DriveFragmentDirections.actionDriveFragmentToDriveSelectionFragment(userArray);
Navigation.findNavController(v).navigate(action);
}else{
new MyToast(getContext(), "Select at least 3 Users!", Toast.LENGTH_SHORT).show();
}
}
});
}
}
The DriverSelectionFragment:
package com.example.convictedDriver.Fragments.Drive;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import com.example.convictedDriver.Adapters.UserAdapter;
import com.example.convictedDriver.Database.User;
import com.example.convictedDriver.R;
import java.io.File;
import java.util.ArrayList;
public class DriveSelectionFragment extends Fragment {
private ArrayList<User> selectedDrivers = new ArrayList<>();
private ArrayList<User> userList = new ArrayList<>();
private ListView listView;
private UserAdapter adapter;
private User driver;
private View view;
private SparseBooleanArray checked;
public DriveSelectionFragment(){
// Empty constructor is needed
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_drive_selection, container, false);
listView = view.findViewById(R.id.driveSelection_listView);
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Receive an ArrayList as argument, including all the userList
if(getArguments() != null){
DriveSelectionFragmentArgs args = DriveSelectionFragmentArgs.fromBundle(getArguments());
userList = arrayToList(args.getSelectedUsers());
}
// Calculate the user with the highest ratio out of the userList
// and add it to the selectedDrivers ArrayList
driver = calculateDriver(userList);
selectedDrivers.add(driver);
Toast.makeText(getContext(), "Driver: "+driver.getUsername(),Toast.LENGTH_SHORT).show();
// Initialize listView and set the adapter
adapter = new UserAdapter(getContext(),R.layout.list_item, userList);
listView.setItemsCanFocus(false);
int driverPos = getDriverPosition(userList, driver);
Toast.makeText(getContext(), "DriverPosition: "+driverPos,Toast.LENGTH_SHORT).show();
adapter.toggleSelection(getDriverPosition(userList,driver));
checked = adapter.getSelectedIds();
Toast.makeText(getContext(), "OnViewCreated: "+checked.toString(),Toast.LENGTH_SHORT).show();
// Binds the Adapter to the ListView
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Toggle the ListViewItems State
adapter.toggleSelection(position);
Toast.makeText(getContext(), "OnItemClick: "+checked.toString(),Toast.LENGTH_SHORT).show();
}
});
}
/*
*
* Calculates a user out of a given list with the highest ratio
*
*/
private User calculateDriver(ArrayList<User> list){
User currUser = list.get(0);
for (User user : list){
if(user.getRatio() >= currUser.getRatio()){
Log.i("Test", user.getRatio() +">"+ currUser.getRatio());
currUser = user;
Log.i("Test", "Changed driver to "+currUser);
}
}
return currUser;
}
private int getDriverPosition(ArrayList<User> list, User driver){
int position = 0;
for (User user: list) {
if (user.getId() == driver.getId()){
return position;
}else{
position++;
}
}
return -1;
}
The fragment_drive_selection.xml file:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:orientation="vertical"
tools:context=".Fragments.Drive.DriveSelectionFragment">
<ListView
android:id="#+id/driveSelection_listView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:divider="#null"
android:dividerHeight="3dp"
android:layout_marginVertical="5dp"
android:choiceMode="multipleChoice"
android:listSelector="#android:color/transparent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
The list_item.xml file:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content"
android:foreground="?attr/selectableItemBackground"
android:background="#drawable/list_item_selector">
<com.mikhaellopez.circularimageview.CircularImageView
android:id="#+id/list_item_imageView"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="5dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
app:civ_border="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:src="#drawable/avatar_1"/>
<TextView
android:id="#+id/user_name_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginStart="8dp"
android:autoSizeTextType="uniform"
android:text=""
android:textColor="#color/colorSpotifyWhite"
android:textSize="22sp"
app:layout_constraintBottom_toTopOf="#+id/user_ratio_text"
app:layout_constraintStart_toEndOf="#+id/list_item_imageView"
app:layout_constraintTop_toTopOf="parent"
tools:text="name" />
<TextView
android:id="#+id/user_ratio_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginStart="8dp"
android:text=""
tools:text="ratio"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="#id/list_item_imageView"
app:layout_constraintTop_toBottomOf="#id/user_name_text" />
</androidx.constraintlayout.widget.ConstraintLayout>
The list_item_selector.xml File:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- pressed -->
<item android:state_enabled="true"
android:state_pressed="true" android:drawable="#drawable/list_item_background_selected" />
<!-- focused -->
<item android:state_enabled="true"
android:state_focused="true" android:drawable="#drawable/list_item_background_selected" />
<!-- selected -->
<item android:state_enabled="true"
android:state_selected="true" android:drawable="#drawable/list_item_background_selected" />
<!-- default -->
<item android:state_enabled="true"
android:state_checked="true" android:drawable="#drawable/list_item_background_selected" />
<item android:state_activated="true"
android:drawable="#drawable/list_item_background_selected" />
<!-- default -->
<item android:drawable="#drawable/list_item_background" />
</selector>
You have to use setItemChecked on ListView to select the item when set Multiple Choice Mode. Check below:
int selctedPosition = getDriverPosition(userList,driver);
adapter.toggleSelection(selctedPosition);
// Binds the Adapter to the ListView
listView.setAdapter(adapter);
listView.setItemChecked(selctedPosition, true);
Related
I have a list view inside a DialogFragment and onClick for the list item doesnt work. Dont know where Im going wrong here. Implemented onItemClick but no use. Code below.
DialogFragment
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
public class DFragment extends DialogFragment {
ListView mylist;
ArrayList dateitems ;
ArrayList descitems ;
ArrayList locationitems ;
ArrayList listitems ;
public void setList(ArrayList list){
listitems = list;
}
public void setDateList(ArrayList list){
dateitems = list;
}
public void setLocList(ArrayList list){
locationitems = list;
}
public void setDescList(ArrayList list){
descitems = list;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.popup_content, container,
false);
mylist = (ListView) rootView.findViewById(R.id.poplist);
TextView title = (TextView) rootView.findViewById(R.id.dialog_title);
title.setText("Today's Events");
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
mylist.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent intent = new Intent(getActivity(), SupportEventActivity.class);
intent.putExtra("rvEventTitle", listitems.get(position).toString());
intent.putExtra("rvEventDescription", descitems.get(position).toString());
intent.putExtra("rvEventLocation", locationitems.get(position).toString());
intent.putExtra("rvEventTimestamp", dateitems.get(position).toString());
}
});
// Do something else
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
R.layout.popup_content_row, R.id.poprow_text, listitems);
mylist.setAdapter(adapter); }
Layout file. popup_content.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#drawable/back"
>
<TextView
android:id="#+id/dialog_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="25dp"/>
<ListView
android:id="#+id/poplist"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:divider="#8F8F8F"
android:dividerHeight="2px"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#ffffff" /> </LinearLayout>
You didn't add startActivity(intent) to your OnClickListener.
I have dynamic CheckBoxes and now I want to check which CheckBox clicked or not
AdditionalInformation.Java File Here Simple Adapter is defined :
package com.example.ahmad.cvbuilder21;
import android.content.Intent;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class AdditionalInformation extends ActionBarActivity {
CheckBox cb;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_additional_infromation);
cb=(CheckBox)findViewById(R.id.additionalchk);
ABC s = ABC.getSingletonObject();
String[][] str = s.getString();
ListView lv=((ListView)findViewById(R.id.additionallist));
String[] additionalOptions={"Add your Picture","Add Experince / Project","Add Reference","Add Skills / Languages"};
String[] txtViewNames={"options"};
List<HashMap<String,String>>list=new ArrayList<HashMap<String, String>>();
for (int i = 0; i < additionalOptions.length; i++) {
HashMap<String, String> map= new HashMap<String, String>();
map.put("options", additionalOptions[i]);
list.add(map);
}
SimpleAdapter simpleAdpt = new SimpleAdapter(this, list, R.layout.mylayout2,txtViewNames , new int[] {R.id.additionaltxt1});
lv.setAdapter(simpleAdpt);
}
public void additionalData(View view1)
{
if(cb.isChecked())
{
cb.findViewById(R.id.additionalchk).setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View view)
{
Toast toast = Toast.makeText(getApplicationContext(), "Checked",
Toast.LENGTH_SHORT);
toast.setGravity(Gravity.TOP|Gravity.LEFT, 0, 0);
toast.show();
}
}
);
}
else{}
}
}
AdditionalInformation.xml file: where additionalData function is called to
check which CheckBox clicked.
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Choose Additional Options:"
android:id="#+id/additionalBtn"
/>
<ListView
android:layout_below="#id/additionalBtn"
android:layout_centerHorizontal="true"
android:id="#+id/additionallist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></ListView>
<Button
android:layout_below="#id/additionallist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add to CV"
android:onClick="additionalData"
/>
</RelativeLayout>
mylayout2.xml file where I define the controls for simple adapter:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<TextView
android:layout_alignParentLeft="true"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/additionaltxt1"
/>
<CheckBox
android:layout_alignParentRight="true"
android:layout_alignRight="#id/additionaltxt1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:id="#+id/additionalchk"
/>
</RelativeLayout>
What you actually need to do is create a custom adapter. In that custom you could listen for checkbox event at the right position.
Here is an example:
public class ListEmployeesAdapter extends BaseAdapter {
public List<Employees> items;
Context c;
public ListEmployeesAdapter(Context c, List<Employees> items) {
this.c = c;
this.items = items;
}
#Override
public int getCount() {
return items.size();
}
#Override
public Object getItem(int position) {
return items.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater)
c.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.employee_item, null);
}
TextView name = (TextView) convertView.findViewById(R.id.name);
name.setText(items.get(position).name);
name.setOnCLickListener(new OnClickListener(){
#Override
public void onClick(){
//listen to the click
}
});
return convertView;
}
}
Just replace the the layout with you layout and call checkbox instead of TextView and you are good to go.
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 am trying to display a custom listview but nothing appears.
My activity:
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONException;
import com.example.elnoorgeh.ServerAPI;
import android.app.Fragment;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView.FindListener;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
public class BlogFragment extends Fragment {
JSONArray jArray;
TextView title;
RelativeLayout layout;
int previousID = 0;
int currentID = 0;
ArrayList<String> titles;
ArrayList<String> contents;
ListView list;
public BlogFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_blog, container,
false);
new AsyncFetch().execute();
return rootView;
}
private class AsyncFetch extends AsyncTask<Object, Object, Object> {
#Override
protected Object doInBackground(Object... params) {
// TODO Auto-generated method stub
jArray = new JSONArray();
jArray = ServerAPI.getData();
titles = new ArrayList<String>();
contents = new ArrayList<String>();
for (int i = 0; i < jArray.length(); i++) {
String blogTitle = null;
String content = null;
try {
blogTitle = jArray.getJSONObject(i).getString("title");
content = jArray.getJSONObject(i).getString("content");
titles.add(blogTitle);
contents.add(content);
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println(blogTitle);
System.out.println(content);
}
// display(titles, contents);
return null;
}
protected void onPostExecute(Object result) {
layout = (RelativeLayout) getView().findViewById(R.id.blogPage);
layout.removeAllViews();
CustomList adapter = new CustomList(getActivity(), titles);
list = new ListView(getActivity());
System.out.println("list done");
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getActivity(),
"You Clicked at " + titles.get(position),
Toast.LENGTH_SHORT).show();
}
});
}
}
public void display(ArrayList<String> t, ArrayList<String> c) {
}
}
Custom ListView class:
import java.util.ArrayList;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class CustomList extends ArrayAdapter<String> {
private final Activity context;
private final ArrayList<String> web;
// private final Integer[] imageId;
public CustomList(Activity context, ArrayList<String>web) {
super(context, R.layout.fragment_listview);
this.context = context;
this.web = web;
// this.imageId = imageId;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView = inflater.inflate(R.layout.fragment_listview, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.txt);
ImageView imageView = (ImageView) rowView.findViewById(R.id.img);
txtTitle.setText((CharSequence) web.get(position));
// imageView.setImageResource(imageId[position]);
return rowView;
}
}
fragment_blog:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/blogPage"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
<TextView
android:id="#+id/txtLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:maxLines="20"
android:singleLine="false"
android:textSize="16dp" />
</RelativeLayout>
fragment_listview:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TableRow>
<ImageView
android:id="#+id/img"
android:layout_width="50dp"
android:layout_height="50dp" />
<TextView
android:id="#+id/txt"
android:layout_width="wrap_content"
android:layout_height="50dp" />
</TableRow>
</TableLayout>
I can't find any errors or notice something irregular, so why is that happening?
you should extend BaseAdapter and implement abstract methods
#Override
public int getCount() {
return web.size();
}
#Override
public Object getItem(int position) {
return web.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
also you might change
txtTitle.setText((CharSequence) web.get(position));
to
txtTitle.setText((CharSequence) getItem(position));
now your adapter don't know size of web array
edit:
you can get one inflater in constructor and keep in class, no need to getting inflater each time (little bit better for perfomance)
LayoutInflater inflater = context.getLayoutInflater();
edit 2:
localhost put proper comment - you are removing all Views from RelativeLayout, also ListView, and creating new ListView without adding to Relative. keeping reference will not auto-add View
protected void onPostExecute(Object result) {
layout = (RelativeLayout) getView().findViewById(R.id.blogPage);
layout.removeView(getView().findViewById(R.id.txtLabel);
//assuming you need to remove only txtLabel
CustomList adapter = new CustomList(getActivity(), titles);
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getActivity(),
"You Clicked at " + titles.get(position),
Toast.LENGTH_SHORT).show();
}
});
}
I meet a problem developing an android project.
Using adapter, I place many items in a ListView, and there is an ImageButton in each item. Now I want to set a click listener for these ImageButtons. What should I do?
This achieves your desired result. Its functionality is the button itself has a click response different from the container, which also has a response.
MainActivity.java
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list);
ListView lv = (ListView) findViewById( R.id.list );
lv.setOnItemClickListener(
new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0,
android.view.View arg1, int arg2, long arg3) {
Toast.makeText( MainActivity.this,
"List item clicked",
Toast.LENGTH_SHORT).show();
}
});
ArrayList<String> items = new ArrayList<String>();
items.add( "item1");
items.add( "item2");
items.add( "item3");
ListAdapter adapter = new ListAdapter( this, items);
lv.setAdapter( adapter );
}
}
ListAdapter.java
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.BaseAdapter;
import android.widget.Toast;
import java.util.List;
public class ListAdapter extends BaseAdapter {
public ListAdapter(Context context,
List<String> items ) {
inflater = LayoutInflater.from( context );
this.context = context;
this.items = items;
}
public int getCount() {
return items.size();
}
public Object getItem(int position) {
return items.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
String item = items.get(position);
View v = null;
if( convertView != null )
v = convertView;
else
v = inflater.inflate( R.layout.item, parent, false);
TextView itemTV = (TextView)v.findViewById( R.id.item);
itemTV.setText( item );
ImageButton button =
(ImageButton)v.findViewById( R.id.button);
button.setOnClickListener(
new OnClickListener() {
public void onClick(View v) {
Toast.makeText( context,
"ImageButton clicked",
Toast.LENGTH_SHORT).show();
}
});
return v;
}
private Context context;
private List<String> items;
private LayoutInflater inflater;
}
item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants" >
<TextView
android:id="#+id/item"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:textSize="28sp" />
<ImageButton
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="#android:color/transparent"
android:src="#drawable/emo_im_cool" />
</RelativeLayout>
list.xml
<?xml version="1.0" encoding="utf-8" ?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/list" />
Try it out and hopefully you can see what's going on to learn what you need