Add & delete item from LinearLayout using ArrayAdapter - android

I am doing bubble display of selected contacts. Each telephone bubble is a LinearLayout, which contains ImageView and TextView. These bubbles are then displayed in another LinearLayout which is child of HorizontalScrollView.
It child/parent tree looks like this:
- HorizontalScrollView
|- LinearLayout (id="#+id/telField")
|- LinearLayout (id="#+id/telBox") <- is programmatically added to parent
|- TextView (id="#+id/telNumber")
|- ImageView (id="#+id/delNumber")
In my .java class I call this method to display "telBox" LinearLayout in "telField" LinearLayout:
public void createAdapter() {
telList = new ArrayAdapter<>(this, R.layout.text_buble, R.id.telNumber, telNumList);
telField = (LinearLayout) findViewById(R.id.telField);
telField.removeAllViews();
final int adapterCount = telNumList.size();
for (ik = 0; ik < adapterCount; ik++) {
final View item = telList.getView(ik, null, null);
telField.addView(item);
item.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
telField.removeView(item);
telNumList.remove(ik-1);
telList.notifyDataSetChanged();
refresh();
}
});
}
}
Method refresh(); – is custom method which helps to "reload" Activity: it gets App values, refreshes warning ImageViews and cals createAdapter() method.
Big button "SELECT" calls an Intent which returns a selected phone number from a contacts book. I call this code to update my LinearLayout with id "telField":
telNumList.add(cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER)));
createAdapter();
Problem I face is:
After I click on LinearLayout with id "telNumber" it one by one deletes every bubble (no matter which I clicked) until it reaches first added bubble. It also crashes 50/50 when reaches first added element, I have not figured out a dependency. The error it returns is "out of bounds error", so I think it is connected with ik - 1 line.
My question is: How do I better construct my ArrayAdapter?

In your code you are trying to remove the view by ik which is getting change continuously because of which your coding is removing last view I have modified your code as given below
for (ik = 0; ik < adapterCount; ik++) {
final int position=ik;
final View item = telList.getView(ik, null, null);
telField.addView(item);
item.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
telField.removeView(item);
telNumList.remove(position);
telList.notifyDataSetChanged();
//refresh();
createAdapter();
}
});
}
Here position will help you to remove the particular view which you want to remove. I hope this is what you are asking for.

Inside your for loop, write these line of code:
for (ik = 0; ik < adapterCount; ik++) {
final View item = telList.getView(ik, null, null);
item.setTag(ik);
telField.addView(item);
item.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
int index = Integer.parseInt(v.getTag().toString());
telNumList.remove(index);
refresh();
}
});
}
Hope it will help you out.

Related

Find child of a LinearLayout inside a LinearLayout

I have a LinearLayout ("ll") that is already created in xml and the app dynamically creates another LinearLayout inside of it and creates an EditText and a Button inside of that view. The button makes the whole LinearLayout destroy itself along with the EditText and Button inside it (the whole system is a player name entering activity). Anyway, I am trying to find a way to get the text from all of the EditTexts. I have tried using a for loop on "ll" and using ll.getChildAt() but I can't seem to use .getChildAt() on whatever ll.getChildAt() generates because getChildAt() generates a "View" not a "LinearLayout." I basically just need a way to search two children in, rather than just one. Also, if there is just a better way I should be doing this, let me know. I'm open to suggestions.
Here's my code if it will help:
NewGameCreate.java
public class NewGameCreate extends Activity {
int numOfPlayers = 0;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.new_game_create);
}
public void newPlayer(View view) {
numOfPlayers++;
final LinearLayout ll = findViewById(R.id.playerView);
final LinearLayout llNew = new LinearLayout(getApplicationContext());
llNew.setOrientation(LinearLayout.HORIZONTAL);
llNew.setId(numOfPlayers);
ll.addView(llNew);
EditText newName = new EditText(this);
newName.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1));
newName.setHint("Enter Player Name");
newName.setId(numOfPlayers);
newName.setWidth(0);
llNew.addView(newName);
final Button delete = new Button(this);
delete.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0));
delete.setText("Delete");
delete.setId(numOfPlayers);
delete.setWidth(0);
delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int id = delete.getId();
ll.removeViewInLayout(findViewById(id));
Drawable back = ll.getBackground();
ll.setBackgroundColor(00000000);
ll.setBackground(back);
ll.invalidate();
}
});
llNew.addView(delete);
}
public void startGame(View view){
LinearLayout ll = findViewById(R.id.playerView);
List text = new ArrayList();
for(int loop = 0; loop < ll.getChildCount(); loop++) {
//this is the code in question and where I want to get the text from
//all my EditTexts
LinearLayout inner = ll.getChildAt(loop);
}
}
}
I think I found the answer to it. You need to change a little bit of code in the startGame() method I m providing the code for startGame below.
public void startGame(View view) {
LinearLayout ll = findViewById(R.id.playerView);
List text = new ArrayList();
for (int loop = 0; loop < ll.getChildCount(); loop++) {
//this is the code in question and where I want to get the text from
//all my EditTexts
LinearLayout inner = (LinearLayout) ll.getChildAt(loop);
for (int j = 0; j < inner.getChildCount(); j++) {
if (inner.getChildAt(j) instanceof EditText) {
EditText textET = (EditText) inner.getChildAt(j);
Log.d("TAG",textET.getText().toString());
}
}
}
}
In the above code you were able to get the first child only but as you have added a linearLayout with orientation Horizontal in a parent LinearLayout with orientation Vertical, you have written code for the child of parent layout i.e playerView. I have modified the code to get the elements of the child Linear layout and Log prints all the text from the EditText.
Hope that helps!!

Adding Layout dynamically for number of times on button click

The scenario is, When the user clicks the button, I need to add
particular layout in known position of parent layout for the number of times button clicked.
I don't know whether it works or not. I tried this following solution which I got from other posts
Buttononclicklistenercode is,
parent = (ViewGroup) C.getParent();//c is a layout in which position i want to add view
final int index = parent.indexOfChild(C);
tobeadded=getLayoutInflater().inflate(R.layout.block_tobeadded_foremi,null);
((Button)findViewById(R.id.button88)).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
addviewcount+=1;
LinearLayout addinglayout=new LinearLayout(MyActivity.this);
addinglayout.setOrientation(LinearLayout.VERTICAL);
parent.removeViewAt(index);
addinglayout.removeAllViews();
for(int i=0;i<addviewcount;i++)
addinglayout.addView(tobeadded);
parent.addView(addinglayout, index);
}
});
But I am getting java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. In my code, before adding that layout, I have invoked the method removeViewAt() for parent.
Can anyone help me to know what is wrong in that.And Is there any other way to do this? Thanks in advance!
You are getting an IllegalStateException because you've already attached the child to the root of the layout.
parent.removeViewAt(index);
addinglayout.removeAllViews();
for(int i=0;i<addviewcount;i++)
addinglayout.addView(tobeadded);//Exception in this line
parent.addView(addinglayout, index);
Let's say addviewcount is 2.
Now in the first iteration, tobeadded is attached to addinglayout.
In the second iteration, you're again trying to attach tobeadded to addinglayout which results in an exception, since The specified child already has a parent. To solve this, You must call removeView() on the child's parent first.
All in all no child is supposed to have more than one parent. And the way you're implementing what you're trying to do is wrong. Create an array of View objects and attach them to the layout in a loop. This will solve your problem.
Here's a link where I've answered a similar question in detail few months back.
https://stackoverflow.com/a/46672959/2356570
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
On Click of button try this:
addinglayout.removeAllViews();
View text = new View(context);
textNotes.setLayoutParams(lparams);
addinglayout.addView(text);
public class SampleDynamiclay extends AppCompatActivity {
Button add, replace;
LinearLayout dynamiclay;
int newid = 100;
int replaceid;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sampledynamiclay);
add = (Button) this.findViewById(R.id.add);
replace = (Button) this.findViewById(R.id.replace);
dynamiclay = (LinearLayout) this.findViewById(R.id.dynamiclay);
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TextView txt = new TextView(SampleDynamiclay.this);
txt.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
newid = newid + 1;
txt.setTag(newid + "");
txt.setTextColor(getResources().getColor(R.color.black));
txt.setText("TextView " + newid);
dynamiclay.addView(txt);
}
});
replace.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
newid = newid + 1;
View removableView = dynamiclay.getChildAt(2);
dynamiclay.removeView(removableView);
TextView txt = new TextView(SampleDynamiclay.this);
txt.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
txt.setTag(newid + "");
txt.setTextColor(getResources().getColor(R.color.black));
txt.setText("TextView is replaced " + newid);
dynamiclay.addView(txt, 2);
}
});
}
}

Android layout doesn't refresh after calling removeAllViews()

I have a Linearlayout called "resultView". I then dynamically added many textViews in it after clicking a button.
I want to remove all the textviews that I just created when I click the button again.
btn_search.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View view) {
resultView.removeAllViews();
String strFileName = et_fileName.getText().toString();
searchFiles(strFileName);
}
});
public void searchFiles(String strFileName){
....
for (int i = 0; i < fileList.size(); i++) {
TextView textView = new TextView(this);
textView.setText(fileList.get(i).getName());
textView.setPadding(5, 5, 5, 5);
if (fileList.get(i).isFile())
resultView.addView(textView);
}
}
App Screenshot, All the listed results are dynamically created textViews.
My XML, the id "view" is my resultView.
But resultView.removeAllViews(); doesn't work. The results are still appened.
Calling resultView.invalidate(); after that doesn't work either.
What should I do to make the layout refresh?
Use .invalidate() to upddate UI.

Passing a value via Button ( maybe hidden)

This code was working until last night, but now now. I'm wanting a value to be record that is linked to the buttons, I have used set and get tag but is only returning last value.
//create a layout
LinearLayout layout = (LinearLayout)findViewById(R.id.linearlayout);
// create a list of buttons
for(x=0; x<3; x++)
{
newBut = new Button(this);
newBut.setText("("TEXT");
newBut.setTextColor(Color.parseColor("#FFFFFF"));
newBut.setTag(x); //hide job id within the button.
newBut.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
int newValue = Integer.parseInt(newBut.getTag().toString());
System.out.println(newValue); //this just a test to display the value
}
});
layout.addView(newBut);
}
Is the error obvious - not to me.
It is returning the last value, because in all the created listeners you always reference the same button (last value of newBut variable), ignoring the actual click source view you have as the argument. Is should be:
newBut.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
int newValue = Integer.parseInt(v.getTag().toString());
System.out.println(newValue);
}
});

How to get the row id of a particular selected row?

I have added two TableRows to TableLayout that is in a for loop. In every first TableRow there are 6 TextViews and 1 ImageView & 1 Toggle Button. I have added an OnClickListener to the first row & Toggle Button. My question is in the onclick method for the First Row, how should I get the row id of that particular selected row?
Can someone help me?
Plz help me.....
I want to get the row id of a particular selected row......
Plz anyone reply me....
Navigate through the View hierarchy in the ImageView OnCLickListener like this:
imageView.setOnClickListener(new OnClickListener() {
public void onCLick(View v) {
// v represents the view that was clicked(the ImageView)
// if the ImageView is added directly to the TableRow then you could simply do
TableRow tr = (TableRow) v.getParent(); // if the ImageView isn't a direct child of the TableRow then walk through all the parent with getParent().
// do stuff
}
});
Edit :
Your code doesn't help and by looking at what you're doing I would advise you to start with something a little simpler to learn about android. Also, tabLayout.addView(openedRow1, n_D); doesn't add a tag to the openedRow1 View(if this is what you want to do), it just position that View to the specific position in the parent(like 0 to be the first child of the parent).
I would guess that you're trying to get the text from the second TextView( tv_vin_val ?!?!) when it's parent is clicked. If this is all you want to do then try something like this:
public void onClick(View v) {
// you set the listener on the TableRow so v is the TableRow that was clicked
TableRow lTableRow = ((TableRow) v);
// to get the TextView use getChildAt or findViewById
TextView lTextView = (TextView)lTableRow.getChildAt(1);
//get the text from the TextView
vinNum = lTextView.getText().toString();
// the tag
int theTag = (Integer) v.getTag();
Intent intent = new Intent(DeliveryInspectionActivity.this, ExceptionsActivity.class);
//intent.putExtra("row id value", theTag);
startActivityForResult(intent, 0);
}
I'm not certain how you would get the correct row number for that, but what I would suggest instead is to use the getParent() method of View to get a reference to the TableRow containing the image and work directly from that. Something like this:
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TableRow row = (TableRow)v.getParent();
//handle your stuff here
}
});

Categories

Resources