I am creating one view from XML, I have defined one row in xml and in my main layout I am adding it through layout inflator and setting the id's of component( TextView, EditText, Button) run time. I have three requirements
User can add new row( It is done)
User can delete row ( It is done
I need to fetch the data from the created row. ( It is done too)
I am following this tutorial
https://github.com/laoyang/android-dynamic-views#readme and it is great tutorial as well.
I am creating the ID of each component at run time and adding it to arraylist so that I can fetch the data from it through loop. i.e
for (EditText editText : Quanitity) { }
Problem is that when user presses the delete button on each row, It deletes the row from the layout and its components as well through this code:
Main.removeView((View) v.getParent());
but its corresponding components ID's are already added to the arraylist. I want when user presses the delete button of the row I should get the position of it so that I can remove it through the arraylist as well.
Each row has a textview which is spinner style. I want to open the spinner on click of textview and value should be set for that Textview not all rows.
Please help me in this case. I am really stucked and deadline is today.
Thanks
aray
First thing to achieve this is to get your selected view's ID and after that search the arraylist for that id and if found delete it.That should look something similar to this :
int myEditTextID = myEditText.getId(); // ids of your selected editext
ids.remove(ids.indexOf(myEditTextID)); // ArrayList<Integer> where you are storing your ids.
The code above first get the id of your selected edittext and than search for the it's index in your arraylist and remove it.
That's all! : )
You can get the index of the child in the ViewGroup with indexOfChild(View). You may need to subtract an offset from that index depending on how many child views come before the rows you are adding (if any).
http://developer.android.com/reference/android/view/ViewGroup.html#indexOfChild(android.view.View)
public void onDeleteClicked(View v) {
// get index
int index = mContainerView.indexOfChild((View) v.getParent()) - offset;
// remove from ArrayList
myArrayList.remove(index);
// remove the row by calling the getParent on button
mContainerView.removeView((View) v.getParent());
}
You can get the offset by storing the initial index of the ViewGroup that you will be adding the views (rows) at before you add any. Which, in the case of the link provided (although unnecessary since it equals 0), would be something like this:
private int offset = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
...
// this should be equal to the index where the first row will be inserted
// offset = 0 with the code in your link
offset = mContainerView.getChildCount() - 1;
// Add some examples
inflateEditRow("Xiaochao");
inflateEditRow("Yang");
}
Related
I have an Activity, which has a RecyclerView and save Button. Each item (football match) of the RecyclerView contains some text (name of teams) and EditText, where user enters data (actually bet the match). My goal is to save those scores to the list in the Activity, when user clicked on save Button.
I implemented this method in Activity, which actually get particular item from LinearLayoutManager and then get data from EditText, but the findViewByPosition() method (or getChildAt() there are different way to do this) sometimes returns null.
I saw another answers on similar question, but they didn't help me. Maybe my strategy is wrong, because I made whole my logic in Activity (better to do this in Adapter?) and I get though all of my items in RecyclerView even if only in one user entered the score.
private List<Bet> getUserBets() {
View betView;
Bet betItem;
EditText userBet1;
EditText userBet2;
int numberOfMatches = rvBetsAdapter.getItemCount();
List<Bet> bets = new ArrayList<>();
for (int i = 0; i < numberOfMatches; i++)
{
betItem = rvBetsAdapter.getItem(i);
betView = linearLayoutManager.findViewByPosition(i);
userScore1 = (EditText) betView.findViewById(R.id.result1); // <- NPE appears
userScore2 = (EditText) betView.findViewById(R.id.result2);
//here i checked whether the editText is empty and other stuff
bets.add(betItem);
}
return bets;
}
How do I fix it? I suppose I should do something in onBindViewHolder method in my adapter, but what exactly?
I would really appreciate any help.
You should add to your Bet model variable which holds EditText value for example editTextValue.
And access it using list in adapter list like this end use EditText value from there. rvBetsAdapter.getItem(i).editTextValue
editTextValue can be set using TextWatcher.afterTextChanged() callback
You can only find or get views that are visible on the screen.
before using findViewByPosition(2)
go to position 2 by recyclerView.scrollToPosition(2);
if you want to change value of this views, The best way is get your item in list
yourModel item = (yourModel) itemList.Get(2)
item.Name = "Edited";
yourAdapter.notifyItemChanged(2);
I am developing an android application, in which I have Edit texts in adapter rows of Recyclerview. Now I want to get sum of these Edit text values entered by user in activity. I have used below code for this purpose:
int count = listArray.size();
int sum = 0;
for (int i = 0; i < count; i++) {
LinearLayout ll = (LinearLayout) mRv_products.getLayoutManager().findViewByPosition(i);
if (ll != null) {
Log.v("TAG", "Item considered:" + i);
EditText t = (EditText) ll.findViewById(R.id.edt_quantity_ship_now);
String amount = t.getText().toString().trim();
if (!amount.isEmpty())
sum += Float.parseFloat(amount);
}
}
Now the problem is, I am getting views only for items which are visible on screen, not all. For example, if I have 10 total items in Recyclerview and only 3 items are visible on screen, I am getting sum of only 3 items which are visible on screen.
So far I have used other options for getting Edit text:
mRv_products.findViewHolderForAdapterPosition(i);
and
mRv_products.getChildAt(i);
Firstly in your adapter class create a string Array list.
private ArrayList<String> list;
Initialize this list in your adapters constructor and also create its getter setter and then in your onBindViewHolder() method add the editext textchangelistener and in this listeners onchangedtext() method add the following code
list.set(position,edittext.getText().toString);
Now you can get all the edittext value through the getter then you combine all the values using string builder.
Here is what i would do:
I will add textWatcher for every editText in RecyclerView item.
then will declare a variable in recyclerView Item model
when any text changed in editText, store the value in that item model.
when sum need to be calculated, iterate the list of model & calculate the result.
Main theme of recyclerView of any adapterView is that your view may or may not exist but your item list always exist. So, always update & use your item list as per as your requirement. It will help you a lot.
Hope it will help you. Thanks in advance.
I am adding a layout on a Button click that layout contains a TextView and the 2 Spinners name spGrades and spMarks.
User can add multiple layout. So all I want is to get the value of Spinners on the TextView click . well I am getting of values of Spinner but I am facing following problems.
In Case1: Suppose there is just one layout added by the user let say
Student1MarksLayout then on the click of the TextView I am getting
the values of Spinners.
In Case 2: Suppose now user has added and other layout let say
Student2MarksLayout with same 2 spinners and a TextView . Now in
this case on the click listener of TextView I am getting the value
of spinners which are currently added. even though i click on the
TextView of the Student1MarksLayout. It brings the values of
Student2MarksLayout values.
Question:
So in fact I want to get the values of spinners differently from the
same view group in which the TextView click has been originated by the
user.
Please help me and any suggestion about this on how to maintain this .
On the function that creates the layout, add to final variables that hold the 2 Spinners. Then create the onClick function, and reference these 2 final variables. I have written a quick example (in a bit of shorthand)
void createLayout()
{
View v = inflate....
final Spinner a = v.findViewById...
final Spinner b = v.findViewById...
TextView t = v.findById...
t.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View v) {
int val = a.get....
}
});
}
Good day.
I am building an Android Application. In my main activity, I have a FragmentPageAdpater and what I basically do is I have this reusable Fragment class that I instantiate three times.
My fragment contains data for three different "pages". I use the current "Active Tab" in my action bar to be able to figure out and filter which data I should show the user. The data is basically a list (dogs, cats, birds) and the user can select a breed. The dog fragment starts first and when the user selects one, my application highlights the selected row and proceeds to the next one (cat fragments). The process repeats until the user is able to select a breed from all three categories.
In order to highlight the user selection, I do this in my onItemClickListener in my ListView
view.setBackgroundColor(Color.GREEN);
where view is the View viewargument in the onItemClickListener function.
However, what happens is when I get to the birds fragment and select then scroll/swipe back to the dog fragment, the green highlight disappears.
What I did try was to have an int to mark which breed index was selected, and then on the Fragment's onResume, fetch the appropriate int marker and then get my listView, get the child at that row, and then set the background colour. However, I am encountering a NullPointerException in my block of code as such:
This is my onResume function in the Fragment:
#Override
public void onResume() {
super.onResume();
//I get my MainActivity/the base one, get the view pager, and get the current item
int index = ((MainActivity)getActivity()).mViewPager.getCurrentItem();
Log.d("hi", "index is = " + index);
switch(index){
case 0:
//dogSelected is the index of the selected item in the dogFragment
if(((MainActivity)getActivity()).dogSelected > -1){
Log.d("hi","selected dog = " + ((MainActivity)getActivity()).dogSelected);
//I reinitialize the listView
listViewBreeds = (ListView) rootView.findViewById(R.id.listViewBreeds);
adapter = new ArrayAdapter<>(getActivity(),
android.R.layout.simple_list_item_1, android.R.id.text1, DogBreeds);
//DogBreeds is an ArrayList of DogBreeds
listViewBreeds.setAdapter(adapter);
//check for null
if(listViewBreeds == null){
Log.d("hi", "hello, lvn NULL");
}
int pos = ((MainActivity)getActivity()).dogSelected; // + 1;
listViewBreeds.getChildAt(pos).setBackgroundColor(Color.GREEN);
}
break;
case 1:
//same as case 0
}
}
As you can see in my code, during the onResume of the Fragment, I check which fragment index is active so I know which list to look up in my switch-case statement. The index logged are correct. Then based on the index, I then look up my lists and the index saved in the base activity. The selected dog (or cat) is correct. After that I reinitialize the listView to make sure it's not null (the log statement does not show up). I then get the listView, get the child at the selected position and then set the background colour.
However, I am getting a NullPointer at the line:
listViewBreeds.getChildAt(pos).setBackgroundColor(Color.GREEN);
and I don't know which part of that is null.
Can anyone help me with this issue? I have a feeling I'm overlooking something simple and I can't figure it out.
Thank you for any help.
I actually got it to work already. The solution was to use a CustomListView Adapter and then create an object for the row entry. That object has a boolean isSelected, then in the Custom ListView Adapter, the background is set to a different color or is set back to white depending on the isSelected variable.
I have a custom listView in my app I would like to implement my select all button I have created.
My ListView looks like.
[(Image)(Text)(CheckBox)]
I have looked at some similar questions, the most common answer was with the user of the notifyDataSetChanged () method, iv'e tried researching and implementing without any luck, I was wondering can you think of a way round it or give me an example of how I can implement the method
A simple way of doing this would be to iterate through the ListView to get each item View, then check it off. I have provided some sample code below given that you are able to acquire the ListView as sampleListView and have an id of the checkbox of checkBoxId:
// Loop through all the items in the list view
for(int viewIndex = 0; viewIndex < sampleListView.getCount(); viewIndex++)
{
// Get the current list item
View listItem = sampleListView.getChildAt(sampleListView.getFirstVisiblePosition() + viewIndex);
// Get the checkbox within the list item
CheckBox currentBox = (CheckBox)listItem.findViewById(R.id.checkBoxId);
// Check the checkbox
currentBox.setChecked(true);
}
You could place this code within the OnClickListener() of the button and it should do the trick.
I couldn't get the above answer to work, so I used parts of another answer and found the answer.
I added this this globally.
ListView list;
//\\ 0 = None set \\// 1 = Select all \\// 2 = Un-Select all//\\
int selState = 0;
Then in the onClick method I used
selState = 2;
list.invalidateViews();
selState being equal to what function you want to do
In the Adapter, this is final part of code
switch(selState)
{
...
case 2:
CheckBox.setChecked(false);
break;
}