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);
}
});
}
}
Related
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!!
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.
public void Add_text() {
ll.setOrientation(LinearLayout.HORIZONTAL);
ll.setId(i);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
TextView product = new TextView(getActivity());
product.setText(" Product" + 5 + " ");
ll.addView(product);
EditText qty = new EditText(getActivity());
qty.setText(i + "");
qty.setId(i);
qty.setWidth(120);
ll.addView(qty);
Button btn = new Button(getActivity());
ll.addView(btn);
btn.setLayoutParams(params);
btn.setOnClickListener(o);
ly.addView(ll);
i++;
}
I wrote the above code to create the textfields and buttons dynamically; But now I need to remove 2 textfields and a button when the button is clicked. How do I do that?
Try following code.
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
LinearLayout linearParent = (LinearLayout) v.getParent().getParent();
LinearLayout linearChild = (LinearLayout) v.getParent();
linearParent.removeView(linearChild);
}
});
Explanation
Here first take "GrandParent" of any view.
Then take its "Parent" view
With reference to "GrandParent" remove that "Parent" view.
this will remove all views which that "Parent" holds. As per your code, your "ll" will be "linearChild" here. And "ly" will be "linearParent" here. So whole "ll" will be removed from "ly" which you have added dynamically.
If you want to permanently remove the views you created.
OnClick(View view){
ly.removeAllViews()
}
If you do not want to permanently remove the views you created.
OnClick(View view){
ly.setVisibility(View.GONE); //This will hide the all views
qty.setVisibility(View.GONE);//This will hide the EditText qty
product .setVisibility(View.GONE);//This will hide the TextView product
}
So use appropriate code line which you want.
EDIT:
Use this code for your situation:
public void Add_text() {
ll.setOrientation(LinearLayout.HORIZONTAL);
ll.setId(i);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
TextView product = new TextView(getActivity());
product.setText(" Product" + 5 + " ");
ll.addView(product);
EditText qty = new EditText(getActivity());
qty.setText(i + "");
qty.setId(i);
qty.setWidth(120);
ll.addView(qty);
Button btn = new Button(this);
ll.addView(btn);
btn.setLayoutParams(params);
ly.addView(ll);
i++;
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View button) {
qty.setVisibility(View.GONE);//This will hide the EditText qty
product .setVisibility(View.GONE);//This will hide the TextView product
}
});
}
i think you got to use this method on your LinearLayout :
public void removeView (View view)
first you call :
EditText et = (EditText)linearLayout.findViewById(yourEditText.getId());
then call the remove view method :
linearLayout.removeView (et) ;
and to remove all of the Views that are in the LinearLayout do the following :
public void removeAllViews ()
like the following :
linearLayout.removeAllViews()
and give me some feedback
Hope that Helps .
you can simply use qty.setVisibility(View.GONE) on the onClickListener() of the Button of your choice. like this.
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
qty.setVisibility(View.GONE); //for temporary purpose
//or u can also do this
layout.removeView(qty); //removes permanently
}
});
The benefit of using View.GONE is that you can get the View back if you want but layout.removeView(qty) will remove the view permanently and you have to re add the view again.
[EDIT] 1. changed to View.GONE instead of View.INVISIBLE because of reasons explained here
Hope I answered your question. :)
just use index for which you want to remove your view from linear layout
Linearlayout.removeViewAt();
if you want again that view then you can call addViewAt()in same way.
I hope it will help you.
Add this line
mLayout.removeViewAt(mLayout.getChildCount()-1);
I am adding buttons to a linear layout at runtime and need to add the functionality of removing them if the user desires. At the moment I have a button which opens a popup with a list consisting of the text for each button added. If possible, would I be able to have each onItemClick delete the corresponding button? If not, what would be the best way to remove a specific button?
Here is the code for adding buttons:
private void addButton(){
LinearLayout lL = (LinearLayout) findViewById(R.id.requirement_linear);
lL.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
p.setMargins(0,2,0,0);
Button b = new Button(this);
b.setBackgroundResource(R.drawable.blue_button);
b.setOnClickListener(openRequirement);
b.setTextColor(Color.parseColor("#FFFFFF"));
String button_text = (index + 2) + ". " + requirement_list.get(index + 1).getName();
b.setText(button_text);
requirements_text.add(button_text);// requirements_text is an arraylist<string> which stores the text so I can display them in my popup to delete them.
index ++;
lL.addView(b,p);
}
You can use removeView() on your LinearLayout and pass your button. You can identify the button on the OnClick(View view) callback, the view there is the button.
as requested, here is an example.
final LinearLayout lL = (LinearLayout) findViewById(R.id.requirement_linear);
Button b = new Button(this);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View button) {
lL.removeView(button);
}
});
lL.addView(b);
Alternatively you can use removeViewAt() to remove a child view by index. You can use the index of your 'list of text of buttons'. Assuming its a listview, you can try this.
lview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
lL.removeViewAt(position);
}
});
here is how i hide and show the buttons
Button b = new Button(this);
b.setVisibility(View.GONE); // this will hide the button and it will now show
b.setVisibility(View.VISIBLE); // this will show the button if it was hidden before
Enjoy!
I have to create layout dynamically using Java.
I have created 9 linear layouts dynamically as below:
for (int i=0;i<10;i++)
{
Element e = (Element) nl.item(i);
cpName = parser.getValue(e,"coverpage");
System.out.println("coverpage name :" + cpName);
LinearLayout lbottomLayoutu1=new LinearLayout(getApplicationContext());
lbottomLayoutu1.setGravity(Gravity.CENTER);
LinearLayout.LayoutParams layoutParams1u1= new LinearLayout.LayoutParams(width,height/4);
layoutParams1u1.weight=1.0f;
lbottomLayoutu1.setLayoutParams(layoutParams1u1);
lbottomLayoutu1.setBackgroundColor(Color.RED);
lbottomLayoutu1.setBackgroundResource(R.drawable.image);
linearLayout.addView(lbottomLayoutu1);
ImageView iv1=new ImageView(getApplicationContext());
LinearLayout.LayoutParams layoutParams= new LinearLayout.LayoutParams(width/4,height/4);
iv1.setLayoutParams(layoutParams);
iv1.setImageResource(R.drawable.coverpage3);
lbottomLayoutu1.addView(iv1);
lbottomLayoutu1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
System.out.println("Calling coverpage");
String Url = WebUrl+cpName;
System.out.println("web Url: " + Url);
Intent in = new Intent(getApplicationContext(),CurlActivity.class);
Bundle bundle = new Bundle();
bundle.putString("Image Url",Url);
in.putExtras(bundle);
startActivity(in);
}
});
setContentView(linearLayout);
}
I put a touch event for every layout. But if I touch any layout how can I know which layout is touching?
I think it's better to use custom listView (like here http://www.codeproject.com/Articles/507651/Customized-Android-ListView-with-Image-and-Text)
You need to set the ids of each layout as
obj.setId(i)
so that in your touch event you can identify it with
int id=obj.getId()
and work accordingly!
If you implement the OnClickListener for the view, like you did...
lbottomLayoutu1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// ...
}
}
... the parameter View v tells you which layout has been touched. You can then cast it to your expected layout, like:
LinearLayout clickedLayout = (LinearLayout) v;
This will be the layout that has been clicked.
If you want, however, know the index that you used in the loop, you have to overwrite your LinearLayout and give it a member that holds the index. Then you can cast it to your custom LinearLayout class and get the index. (If you need more help on this, let me know in the comments).