I have a simple searchable listview with checkboxes but it can't remember my selections when it's getting filtered.
when I filter a value and mark related checkbox then my choice won't be kept after clearing search value ...
activity_main.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="fill_parent"
android:orientation="vertical">
<Button
android:id="#+id/btnChecked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:foregroundGravity="center_horizontal"
android:text="Get checked items"></Button>
<EditText
android:id="#+id/searchFilter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:hint="Search Ingredients"
android:textColor="#color/material_on_surface_emphasis_medium" />
<ListView
android:id="#+id/lvMain"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
MainActivity.java
package com.example.listview;
import android.app.Activity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Filter;
import android.widget.ListView;
public class MainActivity extends Activity implements OnClickListener {
final String LOG_TAG = "myLogs";
ListView lvMain;
String[] names;
private ArrayAdapter<CharSequence> adapter;
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText theFilter = (EditText) findViewById(R.id.searchFilter);
lvMain = (ListView) findViewById(R.id.lvMain);
// here we adjust list elements choice mode
lvMain.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
// create adapter using array from resources file
adapter = ArrayAdapter.createFromResource(
this, R.array.names,
android.R.layout.simple_list_item_multiple_choice);
lvMain.setAdapter(adapter);
Button btnChecked = (Button) findViewById(R.id.btnChecked);
btnChecked.setOnClickListener(this);
// get array from resources file
names = getResources().getStringArray(R.array.names);
theFilter.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
(MainActivity.this).adapter.getFilter().filter(charSequence);
SparseBooleanArray scArray = lvMain.getCheckedItemPositions();
}
#Override
public void afterTextChanged(Editable editable) {
// Uncheck everything:
for (int i = 0; i < lvMain.getCount(); i++) {
if (lvMain.isItemChecked(i)) {
lvMain.setItemChecked(i, true);
} else {
lvMain.setItemChecked(i, false);
}
}
}
});
}
public void onClick(View arg0) {
Log.d(LOG_TAG, "checked: ");
SparseBooleanArray sbArray = lvMain.getCheckedItemPositions();
for (int i = 0; i < sbArray.size(); i++) {
int key = sbArray.keyAt(i);
if (sbArray.get(key))
Log.d(LOG_TAG, names[key]);
}
}
}
as you can see in below pictures, it can't remember "Petr" and "Ivan" selected wrongly after search ...
It is because ArrayAdapter does not support this. You need to create a custom adapter that will remember what has been checked so that when it redraws a view it does not take the default value of unchecked.
Create a class that extends from BaseAdapter that works on an ArrayList<Model> instead of string array. In this Model you can have a boolean checked (initially all false). That way when user scrolls around or searches your model will know weather current name is selected.
Related
I have a recycler view adapter which takes input from user in edittext. I want to pass those values as a list back to the activity in which the recycler view is present.
I need this list in activity to send as a parameter to api through retrofit.
Create an interface like this:
interface IList {
void addToList(String editTextValue);
}
Implement this interface in your Activity:
class MainActivity extends AppCompatActivity implements IList {
#Override
public void addToList(String editTextValue) {
//TODO("logic for adding to list and sending")
}
}
Add to Adapter's constructor Activity, that implementing IList interface, as paramert:
public Adapter(IList listener){
this.listener = listener;
}
Execute addToList method in your adapter:
#Override
public void onBindViewHolder(NewViewHolder holder, int position) {
holder.sendButton.setOnClickListener .setOnClickListener(v -> {
String newText = holder.editText.text.toString()
listener.addToList(newText)
});
}
There's a working sample.
MainActivity.java
```
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Adapter adapter = new Adapter();
RecyclerView recyclerView = findViewById(R.id.recyclerView);
recyclerView.setAdapter(adapter);
EditText editText = findViewById(R.id.editText);
editText.setOnEditorActionListener((textView, actionId, keyEvent) -> {
boolean handled = false;
if (actionId == EditorInfo.IME_ACTION_DONE) {
// add item
adapter.addItem(editText.getText().toString());
// clear text input
textView.setText("");
handled = true;
}
return handled;
});
}
}
```
activity_main.xml
```
<?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:padding="16dp"
tools:context=".MainActivity">
<EditText
android:id="#+id/editText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="Insert text.."
android:imeOptions="actionDone"
android:inputType="text"
app:layout_constraintBottom_toTopOf="#+id/recyclerView"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintVertical_chainStyle="packed" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/editText" />
</androidx.constraintlayout.widget.ConstraintLayout>
```
Adapter.java
```
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
private List<String> items = new ArrayList<>();
#NonNull
#Override
public Adapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(android.R.layout.test_list_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull Adapter.ViewHolder holder, int position) {
String currentItem = items.get(position);
holder.textView.setText(currentItem);
}
public void addItem(String item) {
// add at first position - replace with your desired index
int index = 0;
this.items.add(index, item);
notifyItemInserted(index);
}
#Override
public int getItemCount() {
return items.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
protected TextView textView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(android.R.id.text1);
}
}
}
You can use the "done" key on the keyboard to notify the adapter that an item has been added.
To display the "done" button in the xml it is necessary to use these two instructions in the edittext
android:imeOptions="actionDone"
android:inputType="text"
I want each tab to to show something different. To start things off, I want to make changes to the Place tab. The problem is, none of the changes are being reflected in the Android Simulator.
Image of what I'm referring to
In this case, I want the text something to show up, but it's not. What am I doing wrong? I've also included code that might be relevant to this issue.
Here's MainActivity.java:
import android.net.Uri;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.Arrays;
public class MainActivity extends AppCompatActivity implements Place.OnFragmentInteractionListener, Profile.OnFragmentInteractionListener, Take.OnFragmentInteractionListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabLayout tabLayout = (TabLayout)findViewById(R.id.tabLayout);
tabLayout.addTab(tabLayout.newTab().setText("Place"));
tabLayout.addTab(tabLayout.newTab().setText("Take"));
tabLayout.addTab(tabLayout.newTab().setText("Profile"));
final ViewPager viewPager = (ViewPager)findViewById(R.id.pager);
final PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager(),tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.setOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
#Override
public void onFragmentInteraction(Uri uri) {
}
}
Here's fragment_place.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"
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Place"
android:layout_centerInParent="true"
android:textSize="30dp"
android:id="#+id/textView" />
<EditText
android:id="#+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="41dp"
android:layout_marginStart="41dp"
android:layout_marginTop="80dp"
android:ems="10"
android:inputType="textPersonName"
android:text="Something" />
</RelativeLayout>
Here's PagerAdapter.java:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
public class PagerAdapter extends FragmentStatePagerAdapter {
int mNoOfTabs;
public PagerAdapter(FragmentManager fm, int NumberOfTabs) {
super(fm);
this.mNoOfTabs = NumberOfTabs; // set global number of tabs to local number of tabs
}
#Override
public Fragment getItem(int position) {
switch(position) {
case 0:
Place place = new Place();
return place;
case 1:
Profile profile = new Profile();
return profile;
case 2:
Take take = new Take();
return take;
default:
return null;
}
}
#Override
public int getCount() {
return 0;
}
}
I don't see in your code where you provide the layout xml to the fragment
Change the lines to given code.
#Override
public int getCount() {
return mNoOfTabs ;
}
Also make sure you inflate the layout belong to Place (Fragment) onViewCreated() method
Wasn't really sure how to ask this but...
My code is meant to generate ListView input on a button click.
When I click the button it should .execute() an Async which takes a list of items and adds them to an ArrayList< HashMap < String, String > > with a custom adapter.
The problem is, when I press the button, it generates the list and adds it to the ListView, however, instead of going... 1, 2, 3, 4, 5, ....20 it goes in a random order. 1, 2, 5, 1, 3, 0, 6, 7, 8, 3, 1 ...
And if I scroll up or down the ListView it changes.
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".MainActivity">
<Button
android:id="#+id/bLoadData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="Load api data" />
<ListView
android:id="#+id/lvMovies"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#id/bLoadData"
android:background="#efefef" />
</RelativeLayout>
results_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView android:id="#+id/ivPosters"
android:layout_width="120dp"
android:layout_height="120dp"
android:src="#drawable/place_holder_img"/>
<TextView
android:id="#+id/results_layout_tv_movie_name"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:paddingBottom="10dp"
android:paddingLeft="20dp"
android:paddingStart="20dp"
android:paddingTop="10dp"
android:text="hellow"
android:textColor="#000"
android:textSize="20sp" />
</LinearLayout>
</LinearLayout>
MainActivity.class:
package com.example.zdroa.testinggrounds;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.HashMap;
public class MainActivity extends AppCompatActivity {
static ArrayList<HashMap<String, String>> posters;
ListView listView;
Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.lvMovies);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
System.out.println(posters.get(position).values().toString());
}
});
button = (Button) findViewById(R.id.bLoadData);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
posters = new ArrayList<>();
ImageLoadTask ilt = new ImageLoadTask();
ilt.execute();
}
});
}
private class ImageLoadTask extends AsyncTask<Void, Void, ArrayList<HashMap<String, String>>> {
#Override
protected ArrayList<HashMap<String, String>> doInBackground(Void... params) {
posters = getPathFromAPI();
return posters;
}
#Override
protected void onPostExecute(ArrayList<HashMap<String, String>> result) {
SearchAdapter adapter = new SearchAdapter(MainActivity.this, result);
listView.setAdapter(adapter);
}
private ArrayList<HashMap<String, String>> getPathFromAPI() {
String moviePaths[] = new String[10];
for (int i = 0; i < moviePaths.length; i++) {
HashMap<String, String> map = new HashMap<>();
String s = "path";
map.put(s, s + "_" + i);
moviePaths[i] = "path_" + i;
posters.add(map);
}
return posters;
}
}
}
SearchAdapter.class:
package com.example.zdroa.testinggrounds;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.HashMap;
public class SearchAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<HashMap<String, String>> array;
private ImageView imageView;
private TextView textView;
SearchAdapter(Context context, ArrayList<HashMap<String, String>> paths) {
mContext = context;
array = paths;
}
#Override
public int getCount() {
return array.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = View.inflate(mContext, R.layout.results_layout, null);
imageView = (ImageView) convertView.findViewById(R.id.ivPosters);
textView = (TextView) convertView.findViewById(R.id.results_layout_tv_movie_name);
}
Drawable drawable = ContextCompat.getDrawable(mContext, R.drawable.place_holder_img);
String link_end = array.get(position).values().toString();
Picasso.with(mContext)
.load("http://image.tmdb.org/t/p/w185" + link_end)
// .resize(width, (int) (width * 1.5))
.placeholder(drawable)
.into(imageView);
textView.setText(position+"");
return convertView;
}
}
Your imageview and textview references are only set when the convertview is null...move those lines out of the parenthesis.
in onPost in Asyntask class
after creating and setting the adapter for listview
make the list that you're using in list view
list=new ArrayList<>();
It crashes on this line: alListView.setAdapter(adapter); It worked all last night and I didn't make any changes... I made a few formatting changes, maybe I deleted something I shouldn't have.
package com.grumpy.multipages;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
public class MainPage extends AppCompatActivity {
AlDatabaseAdapter AlHelper;
private ListView alListView;
//AlHelper helper;
private static final String TAG = "MultiPages";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_page);
AlHelper = new AlDatabaseAdapter(this);
//SQLiteDatabase db = AlHelper.getWritableDatabase();
String myHouses = LoadDB();
String[] values = myHouses.split("\n");
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, values);
//alListView.setAdapter(adapter);
alListView.setAdapter(adapter); // CRASHES HERE
Log.d(TAG, "Main Page ");
//Button myBtn = (Button)findViewById(R.id.button1_Button);
Button myBtn1 = (Button)findViewById(R.id.button1_Button);
myBtn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(), AddHouse.class);
//intent.putExtra("refer", "Called from Main Page");
startActivity(intent);
}
});
}
private String LoadDB() {
// Need to get list of Houses from Database
Log.d(TAG, "Calling LoadDB ");
String myHouses = AlHelper.getData();
Log.d(TAG, "Returning From LoadDB ");
Log.d(TAG,myHouses);
return myHouses;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return super.onCreateOptionsMenu(menu);
}
}
// Layout page
<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"
android:orientation="vertical"
tools:context=".MainPage">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/btnAddHouse"
android:id="#+id/button1_Button" />
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/listView"
android:layout_gravity="center_horizontal"
android:choiceMode="singleChoice"
android:clickable="true"
tools:listitem="#android:layout/simple_list_item_1" />
Before:
alListView.setAdapter(adapter); // CRASHES HERE
you should assign to alListView your widget, and from your code it looks like its null at above line.
So add:
alListView = (ListView)findViewById(R.id.listView);
This may be null pointer exception because you declared your Listview(i.e. alListView) but you missed to define it i.e alListView=(ListView)findviewById...
code and trying to set adapter in a null object reference where it crashed.
I am working on an app that works similar to the default text messaging app on all Android phones. My problem is selecting more than one user to send an SMS message to. What I have done so far is stored my contacts as listview items with check boxes. Now I just need to get the phone numbers from the selected contacts.
So what I am having trouble on doing.
1) Pulling a phone number from the contacts displayed in my listview
2)displaying that number in a textview in a new activity
Sorry if my code is difficult to understand, please ask if you need clerification.
This is the XML in which the listview is shown, called contact_manager.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="fill_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/contactList"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<Button
android:id="#+id/showInvisible"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/showInvisible" />
</LinearLayout>
This is my Activity that calls everything together.
public final class ContactManager extends Activity {
public static final String TAG = "ContactManager";
private ListView mContactList;
private boolean mShowInvisible;
private Button mShowInvisibleControl;
/**
* Called when the activity is first created. Responsible for initializing
* the UI.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
Log.v(TAG, "Activity State: onCreate()");
super.onCreate(savedInstanceState);
setContentView(R.layout.contact_manager);
// Obtain handles to UI objects
mContactList = (ListView) findViewById(R.id.contactList);
mShowInvisibleControl = (Button) findViewById(R.id.showInvisible);
// Initialize class properties
mShowInvisible = false;
// mShowInvisibleControl.setChecked(mShowInvisible);
mShowInvisibleControl.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
}
});
populateContactList();
}
/**
* Populate the contact list based on account currently selected in the
* account spinner.
*/
private void populateContactList() {
// Build adapter with contact entries
Cursor cursor = getContacts();
String[] fields = new String[] { ContactsContract.Data.DISPLAY_NAME };
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.contact_entry, cursor, fields,
new int[] { R.id.contactEntryText });
mContactList.setAdapter(adapter);
}
/**
* Obtains the contact list for the currently selected account.
*
* #return A cursor for for accessing the contact list.
*/
private Cursor getContacts() {
// Run query
Uri uri = ContactsContract.Contacts.CONTENT_URI;
String[] projection = new String[] { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME };
String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '"
+ (mShowInvisible ? "0" : "1") + "'";
String[] selectionArgs = null;
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME
+ " COLLATE LOCALIZED ASC";
return managedQuery(uri, projection, selection, selectionArgs,
sortOrder);
}
contact_entry.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<CheckBox
android:id="#+id/contactEntryText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#+id/contactEntryText" />
</LinearLayout>
<?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="fill_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/contactList"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<Button
android:id="#+id/showInvisible"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/showInvisible" />
</LinearLayout>
This is my invite_text.xml This is actually the text view i want to input the numbers into so i can send a mass text message.
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/contacts"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:gravity="center"
android:paddingBottom="10dp"
android:paddingLeft="10dp"
android:paddingTop="10dp"
android:text="#string/contacts"
android:textAppearance="?android:attr/textAppearanceLarge" />
<!-- android:textColor="#fff" android:background="#drawable/header" for header background -->
<Button
android:id="#+id/contactsButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="#string/contacts" />
</RelativeLayout>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/enter_contact"
android:textAppearance="?android:attr/textAppearanceMedium" />
<AutoCompleteTextView
android:id="#+id/contactnumber"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="#string/to" >
<requestFocus />
</AutoCompleteTextView>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/message_to_send"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
android:id="#+id/invite_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/message_join" />
<Button
android:id="#+id/sendtxt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="doLaunchContactPicker"
android:text="#string/send_txt" />
</LinearLayout>
</ScrollView>
If you need me to post any more information, please ask.
I have not looked at your code but here is the mechanism which worked for me:
1. Put setOnCheckedChangeListener to your checkbox.
2. If Checkbox is Checked then add that contact to arraylist.
3. If CheckBox is unchecked then remove that contact from arraylist.
4. Start your contact list activity with startActivityForResult() and override onActivityResult().
5. Before leaving contact activity set your selected contacts in intent.
6. Receive the selected contacts in your activity.
7. Now you have selected contacts which you can show in TextView.
Note: You need to use custom list adapter for this:
Custom List Adapter:
public class YourAdapterName extends BaseAdapter{
private Context mContext;
private ArrayList<string> mValuestoShow;
/**
* Constructor to be called to initialize adapter with values.
* #param context
* #param vector
*/
public YourAdapterName(Context context, ArrayList<string> contacts){
mContext = context;
mValuestoShow = contacts;
}
public int getCount() {
if(null != mValuestoShow){
return mValuestoShow.size();
}
return 0;
}
public Object getItem(int position) {
if(position < mValuestoShow.size())
return mValuestoShow.get(position);
else
return null;
}
public long getItemId(int position) {
return 0;
}
/**
* This method can be override to enable/disable particular list row.
*/
#Override
public boolean isEnabled(int position) {
//Write your code here......
return super.isEnabled(position);
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater li =(LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = li.inflate(R.layout.contact_list_layout, null);
holder = new ViewHolder();
holder.name = (TextView)convertView.findViewById(R.id.name);
holder.checkbox = (CheckBox)convertView.findViewById(R.id.checkbox);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
holder.name.setText(text goes here ....);
holder.checkbox.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if ( isChecked )
//Add contact...
else
//Remove contact.
}
});
return convertView;
}
class ViewHolder {
TextView name;
CheckBox checkbox;
}
}
your_layout.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="wrap_content"
android:padding="10dp" >
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:layout_marginRight="50dp"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#android:color/black" />
<CheckBox
android:id="#+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" />
</RelativeLayout>
Please follow below steps to make it working:
->Have a boolean array, of size equal to cursor. This array will represent checked state of contact.
->In xml make checkbox unclickable and unfocusable.
->setOnItemClickListener on ListVIew and in onItemClick method toggle boolean array's value on position, item selected.
->Set OnClickListener on Button, and onClick method of listener fetch numbers from cursor by follosing:
ArrayList<String> numbers=new ArrayList<String>();
cursor.moveToFirst();
for(int i=0;i<cursor.getCount;i++)
{
cursor.moveToNext();
if(selected[i])
{
//fetch contact from cursor
//add number to numbers
}
}
//Use ArrayList numbers to send Contact, it doesnot seems that you can append multiple numbers to same message, in the case send messages to numbers by a loop, see following thread:
Sending sms to multiple people in android
amd
Unable to send sms using SMSManager in Android
There is no stort ans to your question. You have to write your own adapter and have support for multi selection. I had replied on SO to similar problem (If this helps OK else let me know and I can explain in detail):
Android listview toggle button
android : checkboxes in a ListView ( strange behaviour of selected element)
I'm just going to post a strategy answer. Use hashmap for the list adapter. Use a key that is not displayed to store the phone number to call. Allow multiple selection in the listview. Use the stored phone numbers from the selected entries.
I suggest you to look at the tutorial that I have written last month at this link to manage the selection of the checkbox in the list (it helps you to keep states and retrieves items by ids).
I think that it's better if you manage your list by id but displaying to user the contact name. After that you can pass your ids and send them with the mechanisms that jeet has told you.
I think the below code will give the results as what you expected...
Your main class will lokk like the below...
import java.util.ArrayList;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
public class GetSelectedContacts extends Activity{
int CONTACTS_REQUEST_CODE =1;
Activity thisActivity;
ArrayList<String> selectedConatcts;
LinearLayout contactdisp;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
thisActivity = this;
Button btn = (Button)findViewById(R.id.btn_selectContact);
contactdisp = (LinearLayout)findViewById(R.id.lnr_contactshow);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(thisActivity,ListActivitySampleActivity.class);
startActivityForResult(intent, CONTACTS_REQUEST_CODE);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(data!=null){
Bundle bundle = data.getExtras();
if(requestCode ==1){
selectedConatcts = bundle.getStringArrayList("sel_contacts");
Log.v("", "Selected contacts-->"+selectedConatcts);
if(selectedConatcts.size()<0){
}else{
for(int i =0;i<selectedConatcts.size();i++){
LinearLayout lnr_inflate = (LinearLayout)View.inflate(thisActivity, R.layout.contacts_inflate, null);
EditText edt = (EditText)lnr_inflate.findViewById(R.id.edt_contact);
edt.setText(selectedConatcts.get(i));
contactdisp.addView(lnr_inflate);
}
}
}
}
}
}
The contacts selection class like
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
public class ListActivitySampleActivity extends Activity {
static ContentResolver cr;
String[] phone_nos;
ArrayList<String> selectedContacts = new ArrayList<String>();
Activity thisActivity;
Button btn;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
thisActivity = this;
final ListView lst = (ListView)findViewById(R.id.listView1);
populateContact();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(thisActivity, android.R.layout.simple_list_item_multiple_choice, phone_nos);
lst.setAdapter(adapter);
lst.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
lst.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
}
});
final int len = lst.getCount();
final SparseBooleanArray checked = lst.getCheckedItemPositions();
btn = (Button)findViewById(R.id.btn_send);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for (int i = 0; i < len; i++)
if (checked.get(i)) {
selectedContacts.add(phone_nos[i]);
//you can you this array list to next activity
/* do whatever you want with the checked item */
}
Bundle bundle = new Bundle();
bundle.putStringArrayList("sel_contacts", selectedContacts);
Intent contactIntent = new Intent();
contactIntent.putExtras(bundle);
setResult(1, contactIntent);
thisActivity.finish();
// Log.v("", "selected-->"+selectedContacts);
}
});
}
private void populateContact(){
Uri myContacts = ContactsContract.CommonDataKinds.Phone.CONTENT_URI ;
Cursor mqCur = managedQuery(myContacts, null, null, null, null);
phone_nos = new String[mqCur.getCount()];
int i =0;
if(mqCur.moveToFirst())
{
do
{
String phone_no = mqCur.getString(mqCur
.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER));
phone_nos[i] = phone_no;
i++;
}
while(mqCur.moveToNext());
}
}
}