I've got a ListView with a customer ArrayAdapter and a custom ListItem-XML. At the bottom of this ListView I've added a FooterView with a Button. Now I want to get all the values of the three EditTexts in each of my ListItems when I click this Button.
Here below is my code:
activity_checklistresult.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">
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
result_inner_view.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/item_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<TextView
android:id="#+id/tv_result_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/default_margin" />
<EditText
android:id="#+id/et_result_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/default_margin"
android:inputType="number" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="#+id/tv_result_product_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="end"
android:layout_margin="#dimen/default_margin" />
<AutoCompleteTextView
android:id="#+id/actv_search_product"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:singleLine="true"
android:ellipsize="end"
android:layout_margin="#dimen/default_margin"
android:inputType="textAutoComplete" />
</LinearLayout>
<TextView
android:id="#+id/tv_result_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/default_margin" />
<EditText
android:id="#+id/et_result_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/default_margin"
android:inputType="numberDecimal" />
</LinearLayout>
ResultListActivity.java:
public class ChecklistResultActivity extends ListActivity
{
private MyResultAdapter adapt;
private Button confirmButton;
private ChecklistResultActivity rActivity;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_checklistresult);
// Set my Custom ArrayAdapter for this ListActivity
setAdapter();
rActivity = this;
}
private void setAdapter(){
adapt = new MyResultAdapter(this, R.layout.result_inner_view, Controller.getInstance().getOrderedProducts());
setListAdapter(adapt);
// Add the confirm button at the end of the list
addFooterConfirmButton();
}
private void addFooterConfirmButton(){
ListView lv = (ListView)findViewById(android.R.id.list);
FrameLayout footerLayout = (FrameLayout) getLayoutInflater().inflate(R.layout.result_footer_view, null);
confirmButton = (Button)footerLayout.findViewById(R.id.confirm_result_button);
confirmButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
...
// Get all EditText values (and compare them with the Default Value)
}
});
lv.addFooterView(footerLayout);
}
...
MyResultAdapter.java:
public class MyResultAdapter extends ArrayAdapter<OrderedProduct>
{
private Context context;
private int layoutResourceId;
private LayoutInflater inflater;
public MyResultAdapter(Context c, int layoutResourceId, List<OrderedProduct> objects){
super(c, layoutResourceId, objects);
this.layoutResourceId = layoutResourceId;
this.context = c;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
View view = convertView;
if(view == null)
view = inflater.inflate(layoutResourceId, parent, false);
...
return view;
}
}
In the ResultListActivity at // Get all EditText values (and compare them with the Default Value) I want to loop through all the OrderedProducts and compare the default values of those, with the new filled-in values of the two EditTexts and the AutoCompleteTextView. So how can I get those values from within the onClick of the Footer-Button?
Thanks in advance for the responses.
Your adapter has to save text on change for each created EditText :
create a map to save values
Define and set a generic TextWatcher for every EditText
set a Tag on the editText (using its position or any
id you want) we'll use this tag as the key in the hashMap
create a method to retrieve the value for a given EditText
Adapter :
public class MyResultAdapter extends ArrayAdapter<OrderedProduct>
{
...
private HashMap<String, String> textValues = new HashMap<String, String>();
...
public ViewView getView(int position, View convertView, ViewGroup parent){
View view = convertView;
boolean convertViewWasNull = false;
if(view == null){
view = inflater.inflate(layoutResourceId, parent, false);
convertViewWasNull = true;
}
myEditText1 = findViewById...
myEditText2 = findViewById...
if(convertViewWasNull ){
//be aware that you shouldn't do this for each call on getView, just once by listItem when convertView is null
myEditText1.addTextChangedListener(new GenericTextWatcher(myEditText1));
myEditText2.addTextChangedListener(new GenericTextWatcher(myEditText2));
}
//whereas, this should be called on each getView call, to update view tags.
myEditText1.setTag("theFirstEditTextAtPos:"+position);
myEditText2.setTag("theSecondEditTextAtPos:"+position);
}
private class GenericTextWatcher implements TextWatcher{
private View view;
private GenericTextWatcher(View view) {
this.view = view;
}
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
public void afterTextChanged(Editable editable) {
String text = editable.toString();
//save the value for the given tag :
MyResultAdapter.this.textValues.put(view.getTag(), editable.toString());
}
}
//you can implement a method like this one for each EditText with the list position as parameter :
public String getValueFromFirstEditText(int position){
//here you need to recreate the id for the first editText
String result = textValues.get("theFirstEditTextAtPos:"+position);
if(result ==null)
result = "default value";
return result;
}
public String getValueFromSecondEditText(int position){
//here you need to recreate the id for the second editText
String result = textValues.get("theSecondEditTextAtPos:"+position);
if(result ==null)
result = "default value";
return result;
}
}
You can store all edittext values and get them when needed, you can store it in afterTextChange or onTextChange, it's up to you.
public class MyResultAdapter extends ArrayAdapter<OrderedProduct>{
...
private final String[] valueList;
public MyResultAdapter(Context c, int layoutResourceId, List<OrderedProduct> objects){
super(c, layoutResourceId, objects);
...
valueList = new String[objects.size()];
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
View view = convertView;
if(view == null)
view = inflater.inflate(layoutResourceId, parent, false);
...
//for edittext add text watcher listener
final pos = position;
editText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
valueList[pos] = s.toString();
}
#Override
public void afterTextChanged(Editable s) {
}
});
return view;
}
public String[] getValueList(){
return valueList;
}
}
Related
I tried all the solution that i found here in the stackoverflow but it seems like none of them work.
Here is my main activity:
public class MerchantLocatorActivity extends AppCompatActivity implements OnMapReadyCallback {
public void init(){
merchantLocatorResponseObject = new MerchantLocatorResponse();
merchantLocatorResponseObject.setTitle("Spherical");
merchantLocatorResponseObject.setAddress("8007 Pioneer St, Kapitolyo, Mandaluyong, 1550 Metro Manila");
merchantLocatorResponseObject.setLatitude( 14.573249);
merchantLocatorResponseObject.setLongitude(121.057022);
merchantLocatorObjectArray.add(merchantLocatorResponseObject);
merchantLocatorResponseObject = new MerchantLocatorResponse();
merchantLocatorResponseObject.setTitle("Globe");
merchantLocatorResponseObject.setAddress("SCT, 584 Shaw Blvd, Mandaluyong, 1552 Metro Manila");
merchantLocatorResponseObject.setLatitude(14.585095);
merchantLocatorResponseObject.setLongitude(121.048893);
merchantLocatorObjectArray.add(merchantLocatorResponseObject);
merchantLocatorResponseObject = new MerchantLocatorResponse();
merchantLocatorResponseObject.setTitle("Sparndium");
merchantLocatorResponseObject.setAddress("Xavier, San Juan, 1502 Metro Manila");
merchantLocatorResponseObject.setLatitude(14.601918);
merchantLocatorResponseObject.setLongitude(121.042169);
merchantLocatorObjectArray.add(merchantLocatorResponseObject);
addMarker();
}
#OnClick(R.id.fab)
public void showAccToDialog() {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
View alertView = LayoutInflater.from(this).inflate(R.layout.dialog_biller, null);
alertDialogBuilder.setView(alertView);
final AlertDialog dialog = alertDialogBuilder.create();
dialog.show();
final ListView listViewBillers = (ListView) dialog.findViewById(R.id.biller_institutions_listview);
if (listViewBillers != null) {
MerchantLocatorAdapter adapter = new MerchantLocatorAdapter(
this, R.layout.merchant_locator_adapter, merchantLocatorObjectArray);
listViewBillers.setAdapter(adapter);
listViewBillers.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
geoLocate(merchantLocatorObjectArray,position);
DebugUtils.log("TESTTESTACTIVITYZXC");
DebugUtils.showToast(MerchantLocatorActivity.this,"HAHAHAH");
dialog.dismiss();
}
});
final EditText mSearchedittext = (EditText) dialog.findViewById(R.id.search_edittext);
mSearchedittext.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) {
final ArrayList<MerchantLocatorResponse> searchResultObject = new ArrayList<>();
searchResultObject.clear();
for (int hay = 0; hay <= merchantLocatorObjectArray.size() - 1; hay++) {
if ( merchantLocatorObjectArray.get(hay).getTitle().toLowerCase().contains(charSequence)) {
searchResultObject.add( merchantLocatorObjectArray.get(hay));
}
}
MerchantLocatorAdapter adapter = new MerchantLocatorAdapter(
MerchantLocatorActivity.this, R.layout.merchant_locator_adapter, searchResultObject);
listViewBillers.setAdapter(adapter);
listViewBillers.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapter, View view, int position, long arg) {
geoLocate(searchResultObject,position);
dialog.dismiss();
}
});
}
#Override
public void afterTextChanged(Editable editable) {
}
});
}
}
}
i remove some part of the code because i think it's un necessary to include but let me know if there's some part that i need some clarification.
currently in my main activity, i'm calling a dialog that contains a listview and in my listview i have items.
My problem is i can't select any of my items even thought i have my setOnitemclick listener.
here is my adapter:
public class MerchantLocatorAdapter extends BaseAdapter {
private int resourceLayout;
private Context mContext;
ArrayList<MerchantLocatorResponse> merchantLocatorarray = new ArrayList<>();
public MerchantLocatorAdapter(Context context, int resource, ArrayList<MerchantLocatorResponse> merchantLocatorResponsesobjectArray) {
this.resourceLayout = resource;
this.mContext = context;
this.merchantLocatorarray = merchantLocatorResponsesobjectArray;
}
#Override
public int getCount() {
return merchantLocatorarray.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(mContext.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(resourceLayout, parent, false);
}
TextView tt1 = (TextView) convertView.findViewById(R.id.field_name_textview);
TextView tt2 = (TextView) convertView.findViewById(R.id.field_value_textview);
ImageButton direction = (ImageButton) convertView.findViewById(R.id.direction);
tt1.setText(merchantLocatorarray.get(position).getTitle());
tt2.setText(merchantLocatorarray.get(position).getAddress());
return convertView;
}
}
here is my layout for my adapter:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:id="#+id/card_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_margin="8dp"
android:elevation="3dp">
<LinearLayout
android:id="#+id/card_overflow"
android:focusable="true"
android:clickable="true"
android:background="#fff"
android:paddingLeft="16dp"
android:paddingRight="0dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="1">
<TextView
android:id="#+id/field_name_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_toLeftOf="#+id/branch_btns"
android:layout_alignParentLeft="true"
android:textSize="17sp"
android:textStyle="bold"
android:textColor="#color/edittext_text"
android:text="test"/>
<LinearLayout
android:id="#+id/branch_btns"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:orientation="horizontal"
>
<ImageButton
android:id="#+id/direction"
android:layout_width="50sp"
android:layout_height="wrap_content"
android:src="#drawable/ic_direction"
android:scaleType="fitCenter"
android:background="#color/translucent_clear_bg"
/>
<ImageButton
android:id="#+id/btn_branch_phone"
android:layout_width="50sp"
android:layout_height="wrap_content"
android:src="#drawable/ic_call_phone"
android:scaleType="fitCenter"
android:background="#color/translucent_clear_bg"
/>
</LinearLayout>
</RelativeLayout>
<View
android:id="#+id/seperator"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginBottom="5dp"
android:background="#android:color/darker_gray"
android:visibility="gone"
android:layout_marginTop="2dp"/>
<TextView
android:id="#+id/field_value_textview"
android:textSize="14sp"
android:textColor="#color/edittext_tint"
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="test"/>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
i tried every solution that i found here in stackoverflow, and yet i can't still click my item. so please don't mark this as a duplicate.
if there's any part of the code that need clarification, please leave a comment and i'll answer as soon as possible. thanks.
Try to use Observable in you custom adapter:
// Define
private final PublishSubject<MerchantLocatorResponse> onItemClick = PublishSubject.create();
// Create the observable method
public Observable<ConversationMessage> getObservable(){
return onItemClick;
}
// Set the onClickListener into getView()
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onItemClick.onNext(merchantLocatorarray.get(position));
}
});
Then, in your main activity listen to it and handle the click:
#OnClick(R.id.fab)
public void showAccToDialog() {
// bla bla bla
listViewBillers.setAdapter(adapter);
listViewBillers.getObservable().subscribe(geoLocate);
// bla bla bla
}
Consumer<MerchantLocatorResponse> geoLocate = new Consumer<MerchantLocatorResponse>() {
#Override
public void accept(MerchantLocatorResponse mlr) {
// Code after click event
}
};
Add those library in your gradle:
implementation "io.reactivex.rxjava2:rxjava:2.1.5"
implementation "io.reactivex.rxjava2:rxandroid:2.0.1"
Add convertView.setOnclickListener() in your code. Try below code in your adapter
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(mContext.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(resourceLayout, parent, false);
}
TextView tt1 = (TextView) convertView.findViewById(R.id.field_name_textview);
TextView tt2 = (TextView) convertView.findViewById(R.id.field_value_textview);
ImageButton direction = (ImageButton) convertView.findViewById(R.id.direction);
tt1.setText(merchantLocatorarray.get(position).getTitle());
tt2.setText(merchantLocatorarray.get(position).getAddress());
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(context, String.valueOf(position), Toast.LENGTH_SHORT).show();
}
});
return convertView;
} }
I have ListView and it include 2 EditTextI want to initialize 6 empty EditText when activity started.How can I do that?
I can not add list null Model and set it so I dont know how can i handle it.
This is listview_row.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="#+id/SerialNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="3"
android:ellipsize="end"
android:padding="5dp"
android:singleLine="true">
<requestFocus />
</EditText>
<EditText
android:id="#+id/countItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:padding="5dp"
android:singleLine="true"
android:inputType="number">
</EditText>
This is my layout;
activity_reader.xml
<RelativeLayout 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">
<Button
android:id="#+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content""
android:text="btn" />
<GridLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#+id/listview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:divider="#null" />
</GridLayout>
Here is the ListView Adapter;
public class ListViewAdapter extends BaseAdapter {
public ArrayList<Model> productList;
Activity activity;
ViewHolder holder;
public ListViewAdapter(Activity activity, ArrayList<Census> productList) {
super();
this.activity = activity;
this.productList = productList;
}
#Override
public int getCount() {
return productList.size();
}
#Override
public Object getItem(int position) {
return productList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
private class ViewHolder {
EditText SerialNumber;
EditText countItem;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = activity.getLayoutInflater();
if (convertView == null) {
convertView = inflater.inflate(R.layout.listview_row, null);
holder = new ViewHolder();
holder.SerialNumber = (EditText) convertView.findViewById(R.id.SerialNumber );
holder.countItem = (EditText) convertView.findViewById(R.id.countItem );;
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.SerialNumber.addTextChangedListener(new TextWatcher() { #Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
holder.SerialNumber.requestFocus();
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
holder.censusRowSerialNumber.requestFocus();
}
#Override
public void afterTextChanged(Editable s) {
//holder.countItem.requestFocus();
}
});
Model item = productList.get(position);
holder.SerialNumber.setText(item.getID().toString());
holder.countItem.setText(String.valueOf(item.getQuantity()));
return convertView;
}
}
Here is the Activity;
public class ReaderActivity extends AppCompatActivity {
EditText countItem,SerialNumber;
private ArrayList<Model> csList;
Model item;
ListViewAdapter adapter;
ListView lview;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reader);
csList = new ArrayList<Model>();
lview = (ListView) findViewById(R.id.listview);
adapter = new ListViewAdapter(this, csList);
SerialNumber= findViewById(R.id.SerialNumber);
countItem = findViewById(R.id.countItem );
lview.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
For achieving CRUD operations, its good to go with Custom Layouts.
For instance a LinearLayout, who's default layout is already defined. Now according to runtime requirement/parameters you can add/edit/delete all these. For which the logic can be completely yours. This is handy than creating a static view and manipulating.
Let me show you custom layouts preparation and adding into a rootiew. I have given example where layout landing_hori_view is having an EditText and Button
public class LandingHorizontalView extends LinearLayout implements View.OnClickListener{
public LandingHorizontalView(Context context){
super(context);
initialize();
}
public LandingHorizontalView(Context context, ModelClassObject modelObject,ButtonClicked listener){
super(context);
mTypeContent = modelObject;//If you want to pass some params for population
mListener = listener;
initialize();
}
private void initialize(){
View view = LayoutInflater.from(getContext()).inflate(R.layout.landing_hori_view, this, true);
EditText edtOne =findViewById(R.id.txt_price_list);
Button button= findViewById(R.id.btn_place_order);
button.setTag(count);
button.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(v instanceof Button){
int count = (int) v.getTag();
mListener.onButtonClicked(count);
}
}
public interface ButtonClicked{
public void onButtonClicked(int index);
}
}
In your parent activity, implement the interface (here ButtonClicked) and handle click events/manipulating UI etc
#Override
public void onButtonClicked(int index) {
}
Now coming to , how to add these to parent layout, create a ScrollView and include one LinearLayout to which LandinghorizontalView will be added.
Below shows content of my parent Activity
<ScrollView
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#android:color/white"
app:layout_constraintTop_toBottomOf="#id/guideline"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/landingScrollLinearView"
>
</LinearLayout>
Now for adding this vew , the following can be done.
LandingHorizontalView horizontalView=new LandingHorizontalView(getActivity(),modelObject,this);
mScrollLinearView.addView(horizontalView);
Now as per your comment, create few LandingHorizontalView and add
to root. Now according to your logic/user interaction , keep on
modifying mScrollLinearView
I can not figure out what going wrong with my ListView, because it is too small. I want bigger items like default list views on Android.
SelectContactActivity
public class SelectContactActivity extends Activity {
private ArrayList<Contact> listContacts = new ArrayList<Contact>();
private ArrayList<SongInfo> listSong = new ArrayList<SongInfo>();
private ListContactsAdapter adapter;
private Util util = new Util();
private ListView list;
private EditText txt_search;
private ArrayList<Contact> listSearch;
private Handler guiThread;
private Runnable updateTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.setContentView(R.layout.mycontacts);
list = (ListView)findViewById(R.id.list);
txt_search = (EditText)findViewById(R.id.txt_search);
final int position = this.getIntent().getIntExtra("position", 0);
listSong = util.getAllSong(this);
listContacts = util.getAllContact(this);
Log.i("LOG", "Size: " + listContacts.size());
adapter = new ListContactsAdapter(this, android.R.layout.simple_list_item_1, listContacts);
list.setAdapter(adapter);
list.setTextFilterEnabled(true);
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
util.assignRingtoneToContact(SelectContactActivity.this,
listSong.get(position), listContacts.get(arg2));
Toast.makeText(
SelectContactActivity.this,
"Ringtone set successfully",
Toast.LENGTH_LONG).show();
finish();
}
});
innitThread();
txt_search.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
queueUpdate(500);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
}
private void queueUpdate(long delayMillisecond) {
guiThread.removeCallbacks(updateTask);
// update data if no change in textSearch after time config
// timer by = milliseconds
guiThread.postDelayed(updateTask, delayMillisecond);
}
private void innitThread() {
guiThread = new Handler();
updateTask = new Runnable() {
#Override
public void run() {
String word = txt_search.getText().toString().trim();
if (word.equalsIgnoreCase("")) {
// if not change set listView first
list.setAdapter(new ListContactsAdapter(SelectContactActivity.this,
android.R.layout.simple_list_item_1, listContacts));
} else
// if txtSearch not null
{
// get data from webservice
getDataByKeywords(word);
// Show on list
listSearch = new ArrayList<Contact>();
// get data from webservice
listSearch = getDataByKeywords(word);
list.setAdapter(new ListContactsAdapter(SelectContactActivity.this, android.R.layout.simple_list_item_1, listSearch));
adapter.notifyDataSetChanged();
}
}
};
}
public ArrayList<Contact> getDataByKeywords(String keyword) {
listSearch = new ArrayList<Contact>();
keyword = keyword.toUpperCase();
for (int i = 0; i < listContacts.size(); i++) {
String contain = listContacts.get(i).getName().toUpperCase();
if (contain.contains(keyword)) {
listSearch.add(listContacts.get(i));
}
}
return listSearch;
}
}
ListContactsAdapter
public class ListContactsAdapter extends ArrayAdapter<Contact>{
private ArrayList<Contact> contacts;
private Context context;
public ListContactsAdapter(Context context, int textViewResourceId,
ArrayList<Contact> objects) {
super(context, textViewResourceId, objects);
this.context = context;
this.contacts = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
if(convertView!=null){
convertView.setBackgroundResource(R.drawable.list_selector);
}
TextView textView = getGenericView();
textView.setBackgroundResource(R.drawable.list_selector);
textView.setText(contacts.get(position).getName());
return textView;
}
public TextView getGenericView() {
// Layout parameters for the ExpandableListView
AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT, 70);
TextView textView = new TextView(context);
textView.setLayoutParams(lp);
// Center the text vertically
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
// Set the text starting position
textView.setPadding(16, 0, 0, 0);
textView.setTextSize(18);
textView.setShadowLayer(1, 1, 1, Color.BLACK);
textView.setTextColor(0xffeeeeee);
return textView;
}
}
mycontacts.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="fill_parent" >
<RelativeLayout
android:id="#id/relativeLayoutSearch"
android:layout_width="fill_parent"
android:layout_height="55dp"
android:gravity="center_vertical"
android:paddingLeft="12dp"
android:paddingRight="12dp" >
<EditText
android:id="#id/txt_search"
android:layout_width="fill_parent"
android:layout_height="40dp"
android:background="#drawable/search_bar"
android:hint="#string/hint_apps_search"
android:paddingBottom="12dp"
android:paddingLeft="45.0dip"
android:paddingRight="14dp"
android:paddingTop="12dp"
android:singleLine="true"
android:textSize="15.0sp" />
<Button
android:id="#id/button2"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="#drawable/zoomicon" />
</RelativeLayout>
<ListView
android:id="#id/list"
style="#style/ContactList"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#id/relativeLayoutSearch"
android:cacheColorHint="#e0000000" />
</RelativeLayout>
styles.xml
<style name="ContactList">
<!-- <item name="android:background">#color/listbg</item> -->
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">fill_parent</item>
<item name="android:cacheColorHint">#e0000000</item>
<item name="android:divider">#color/listdiv</item>
<item name="android:dividerHeight">1.0dip</item>
</style>
This is my code for contact list, and here is a screenshot how this looks, but I want bigger items on list. Any suggestions?
Current listview:
I would start smaller, by revisiting your adapter. The ListView itself is very simple - in your activity layout, you set your ListView to be match_parent for both width and height.
The adapter is the component which creates each row, which in ListAdapter, is initiated by the getView() method.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView != null) {
convertView.setBackgroundResource(R.drawable.list_selector);
}
TextView textView = getGenericView();
textView.setBackgroundResource(R.drawable.list_selector);
textView.setText(contacts.get(position).getName());
return textView;
}
Note what you're doing here is incorrect; you do something to convertView but then you ignore it, and just make a new View. The pattern is more like:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
if (rowView == null) {
rowView = // create a new View that represents your row
}
// bind the data to rowView, then return it
return rowView;
}
which in your case might be:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView rowView = (TextView) convertView;
if (rowView == null) {
rowView = getGenericView();
rowView.setBackgroundResource(R.drawable.list_selector);
}
rowView.setText(contacts.get(position).getName());
return rowView;
}
See, you only need to create rowView if it's null. Also, the background only needs to be set once (and this can be done in XML if you want).
With creating the row View, I'd recommend starting by inflating a layout that contains a single TextView as the only element.
view_item_contact.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
then your getGenericView() can be renamed to createContactRowView():
private TextView createContactRowView(ViewGroup parent) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
return ((TextView) layoutInflater.inflate(R.layout.view_item_contact, parent, false));
}
From there, you can start to style your row in view_item_contact.xml by adding padding, setting a minimum height, centering the text vertically by applying gravity, etc.
view_item_contact.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:gravity="center_vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:background="#drawable/list_selector" />
In almost all cases, I would avoid creating Views programmatically - always inflate them from XML, so you can separate styles and layout from your logic.
I'm trying to implement a listView with EditText Controls. Problem is when I edit one of the fields, some other fields are also modified in the view. However, my Java objects are reflecting the changes that i make only (and not the other EditTexts that get set)
My Android Activity
public class LoanRepaymentActivity extends ListActivity implements View.OnClickListener {
private Location lastKnownLocation;
private ArrayList<CurrentRepaymentInstallment> loansForRepayment;
#Override
public void onCreate(Bundle savedInstanceState){
lastKnownLocation = Utility.getLastKnownLocation(this);
super.onCreate(savedInstanceState);
Intent intent = getIntent();
RepaymentInfo repaymentInfo = (RepaymentInfo)intent.getSerializableExtra(Constants.CURRENT_REPAYMENT_INSTALLMENT);
loansForRepayment = repaymentInfo.getLoansForRepayment();
boolean repaymentsNotPresent = loansForRepayment == null || loansForRepayment.isEmpty();
if(repaymentsNotPresent){
Dialog dialog = Utility.getDialogWithText(LoanRepaymentActivity.this, getText(R.string.noLoansForRepayment).toString());
Utility.getDialogButton(dialog, LoanRepaymentActivity.this, PartnerGroupListActivity.class, intent.getStringExtra(Constants.ACECSS_TOKEN_PARAM));
dialog.show();
}
ArrayAdapter<CurrentRepaymentInstallment> adapter = new LoanRepaymentListAdapter(this, loansForRepayment);
View footer = getLayoutInflater().inflate(R.layout.loan_disbursement_footer, null);
getListView().addFooterView(footer);
setListAdapter(adapter);
/* if(!repaymentsNotPresent) {
TextView textView = (TextView)findViewById(R.id.screenTitle);
String currentInstallmentLabel = getText(R.string.currentInstallmentLabel).toString() + repaymentInfo.getCurrentGroupInstallment();
textView.setText(currentInstallmentLabel);
}*/
Button button = (Button)findViewById(R.id.disburse);
button.setOnClickListener(this);
}
My XML Layout
<?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:orientation="vertical"
>
<TextView android:id="#+id/screenTitle"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</TextView>
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+layout/loan_disbursement_footer"
/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/borrowerName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#+id/label"
android:textSize="14sp"
>
</TextView>
<TextView
android:id="#+id/loanAmount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#+id/label"
android:textSize="14sp"
>
</TextView>
<TextView
android:id="#+id/installmentNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#+id/label"
android:textSize="12sp"
>
</TextView>
<TextView
android:id="#+id/estimatedTotal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#+id/label"
android:textSize="12sp"
>
</TextView>
</LinearLayout>
<EditText
android:id="#+id/repaymentAmount"
android:layout_width="100sp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:inputType="numberDecimal"
android:textSize="12sp"
>
</EditText>
</RelativeLayout>
The Custom Array Adapter Used to set the ListView
public class LoanRepaymentListAdapter extends ArrayAdapter<CurrentRepaymentInstallment> {
private final List<CurrentRepaymentInstallment> loansForRepayment;
private final Activity context;
public LoanRepaymentListAdapter(Activity context, List<CurrentRepaymentInstallment> loansForRepayment) {
super(context, R.layout.loan_repayments, loansForRepayment);
this.context = context;
this.loansForRepayment = loansForRepayment;
}
static class ViewHolder {
protected TextView borrowerName;
protected TextView loanAmount;
protected TextView installmentNumber;
protected TextView estimatedTotal;
protected EditText repaymentAmount;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
view = inflator.inflate(R.layout.loan_repayments, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.borrowerName = (TextView) view.findViewById(R.id.borrowerName);
viewHolder.loanAmount = (TextView) view.findViewById(R.id.loanAmount);
viewHolder.installmentNumber = (TextView) view.findViewById(R.id.installmentNumber);
viewHolder.estimatedTotal = (TextView) view.findViewById(R.id.estimatedTotal);
viewHolder.repaymentAmount = (EditText) view.findViewById(R.id.repaymentAmount);
// viewHolder.repaymentAmount.setEditableFactory(Editable.Factory.getInstance());
viewHolder.repaymentAmount.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable arg0) {
}
#Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
// TODO Auto-generated method stub
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
CurrentRepaymentInstallment loanRepayment = (CurrentRepaymentInstallment) viewHolder.repaymentAmount.getTag();
String repaymentAmount = s.toString();
loanRepayment.setRepaymentAmount(repaymentAmount);
}
});
view.setTag(viewHolder);
viewHolder.repaymentAmount.setTag(loansForRepayment.get(position));
} else {
view = convertView;
((ViewHolder) view.getTag()).repaymentAmount.setTag(loansForRepayment.get(position));
}
ViewHolder holder = (ViewHolder) view.getTag();
holder.borrowerName.setText(loansForRepayment.get(position).getLoanProfileBasicInfo().getBorrowerBasicInfo().getFirstName());
holder.loanAmount.setText("Rs. " + Float.toString(loansForRepayment.get(position).getLoanProfileBasicInfo().getLoanAmountInPaisa()/100));
holder.estimatedTotal.setText("Rs. " + Float.toString(loansForRepayment.get(position).getEstimatedTotalAmount()/100));
holder.installmentNumber.setText("Inst no : " + Integer.toString(loansForRepayment.get(position).getInstallmentNumber()));
float repaymentAmt = loansForRepayment.get(position).getRepaymentAmount();
if(repaymentAmt != 0.0) holder.repaymentAmount.setText(Float.toString(repaymentAmt));
return view;
}
}
The reason being Android ListView recycling..
Please have a look at the accepted answer in the below link
EditText in ListView without it recycling input
Hope this helps.
The solution to this is removing the added textwatcher before setting the text. Otherwise, the previous textwatcher on that view will still be called along with the new textwatcher. Store the textwatcher as a tag on the EditText to keep track of it.
Object oldWatcher = viewHolder.quantitySold.getTag();
if(oldWatcher != null){
viewHolder.quantitySold.removeTextChangedListener((CustomTextWatcher)oldWatcher);
}
String oldText = inputValues.get("key"+position);
Log.d(TAG, "oldText: "+oldText+" position: "+position);
viewHolder.quantitySold.setText(oldText == null ? "" : oldText);
CustomTextWatcher watcher = new CustomTextWatcher(
cursor.getString(SKUFragment.COL_NAME),
cursor.getInt(SKUFragment.COL_ID),
cursor.getDouble(SKUFragment.COL_UNIT_PRICE),
position
) {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
if (s != null) {
int quantity = 0;
if (!TextUtils.isEmpty(s.toString())) {
quantity = Integer.parseInt(s.toString());
inputValues.put("key"+mPosition, "" + quantity);
}else{
inputValues.put("key"+mPosition, "");
}
double value = quantity * skuPrice;
mListener.onQuantityChanged(skuName+", position: "+mPosition, skuId, quantity, value);
}
}
};
viewHolder.quantitySold.setTag(watcher);
viewHolder.quantitySold.addTextChangedListener(watcher);
I am facing a problem of Filtered list view not updated.
In my application there is a custom list view which has two text views and one image view as row elements.
Filter works fine but my Custom list view not updated; the result shows the first rows of the List.
This is my code.
abc.java file
public class abc extends ListActivity
{
private ArrayList<String> m_orders = null;
private OrderAdapter m_adapter;
List<String> Title_List=new ArrayList<String>();
List<String> Author_List=new ArrayList<String>();
private ArrayAdapter<String> adapter = null;
private LayoutInflater mInflater;
private Vector data;
private EditText filterText = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
#Override
public void onStart() {
super.onStart();
m_orders = new ArrayList<String>();
filterText = (EditText) findViewById(R.id.search_box);
filterText.addTextChangedListener(filterTextWatcher);
setListAdapter(m_adapter=new OrderAdapter(this,R.layout.list_row, m_orders));
m_adapter.notifyDataSetChanged();
getListView().setTextFilterEnabled(true);
}
private TextWatcher filterTextWatcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after)
{
}
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
m_adapter.getFilter().filter(s, new Filter.FilterListener() {
public void onFilterComplete(int count) {
Log.d(null, "filter complete! count: "+ count);
m_adapter.notifyDataSetChanged();
}
});
}
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
};
private class OrderAdapter extends ArrayAdapter {
private ArrayList<String> items;
public OrderAdapter(Context context, int textViewResourceId, ArrayList<String> items) {
super(context, textViewResourceId, items);
this.items = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.list_row, null);
}
String order = m_orders.get(position);
String description = Item_List.get(position);
if (order != null)
{
TextView tt = (TextView) v.findViewById(R.id.toptext);
TextView bt = (TextView) v.findViewById(R.id.bottomtext);
if (tt != null) {
tt.setText("Title: "+order);
}
if (bt != null) {
bt.setText("des: "+description);
}
}
return v;
}
}
#Override
public void onListItemClick(ListView parent, final View v, int pos, long id)
{
}
}
list_row.xml file
<?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="?android:attr/listPreferredItemHeight"
android:padding="6dip">
<ImageView
android:id="#+id/icon"
android:layout_width="40px"
android:layout_height="40px"
android:layout_marginRight="6dip"
/>
<LinearLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="50px">
<TextView
android:paddingTop="1pt"
android:id="#+id/toptext"
android:layout_width="200px"
android:layout_height="0dip"
android:layout_weight="1"
android:gravity="center_vertical"
android:textColor="#ffffff"
android:textSize="18sp"
android:paddingBottom="1pt"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:lines="1"
android:scrollHorizontally="true"
/>
<TextView
android:paddingTop="1pt"
android:layout_width="200px"
android:layout_height="0dip"
android:layout_weight="1"
android:id="#+id/bottomtext"
android:paddingBottom="2pt"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:lines="1"
android:scrollHorizontally="true"
/>
</LinearLayout>
</LinearLayout>
I think filter works but only result is not updated in list view.
I think I had the same problem. It took me about 5 hours to find this out.
Fault could be in your getView().
Use the getItem() method of the ArrayAdapter method instead of
String order = m_orders.get(position);
String description = Item_List.get(position);
Problem is that the filtered data is contained in ArrayAdapter.mObjects. If you use your own data variable theres nothing filtered.