OnClick button ,create a layer in the same form. Android - android

I m very new to Android.
I want to create a dynamic OnClick button functionality.
OnClick of "+" above , it should create a other layer , like this below.
My confusion , my entire design UI is in layout.xml.
How we can we include another layer in our UI on OnClick of "+" button.
Any input would be helpful.
Thanks !!!

You could do this programatically. XML is for static layouts.
Excuse my pseudo Android:
private LinearLayout root;
public void onCreate(Bundle b){
LinearLayout root = new LinearLayout(this);
root.addChild(createGlucoseReadingView());
setContentView(root);
}
private View createGlucoseReadingView() {
LinearLayout glucoseRoot = new LinearLayout(this);
glucoseRoot.addChild(new TextView(this));
return glucoseRoot;
}
public void onPlusClick(View button){
root.addChild(createGlucoseReadingView());
}
Something along those lines, I've obviosuly left out formatting and adding the layout params to the views, but you get the idea.

In your XML have one Vertical Linear Layout to add and remove EditTexts at runtime, Here I have shown you code I have used in my demos. To handle and maintain the usage.
Onclick of your Add and Minus button click
public void onClick(View view) {
super.onClick(view);
switch (view.getId()) {
case R.id.btnadd:
createTextview(counter);
counter++;
if (counter > 3) {
btnAdd.setVisibility(View.GONE);
btnRemove.setVisibility(View.VISIBLE);
}
break;
case R.id.btnremove:
removeView(counter);
txtoption[counter - 1] = null;
counter--;
if (counter < 3) {
btnAdd.setVisibility(View.VISIBLE);
btnRemove.setVisibility(View.GONE);
}
break;
}
}
Functions to create and remove view
private void createTextview(int index) {
txtoption[index] = new EditText(this);
txtoption[index].setSingleLine(true);
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
param.bottomMargin = 10;
txtoption[index].setLayoutParams(param);
txtoption[index].setBackgroundResource(R.drawable.textbox);
txtoption[index].setTypeface(ttfDroidSherif);
lnpolloptions.addView(txtoption[index]);
}
private void removeView(int index) {
lnpolloptions.removeView(txtoption[index - 1]);
}
Your vertical LinearLayout to contain all the edittext childs
LinearLayout lnpolloptions = (LinearLayout) findViewById(R.id.lnpolloptions);
Arrays of edittext to be created of removed at runtime
private EditText[] txtoption = new EditText[4];
Onclick of submit to get value from each textbox
int length = txtoption.length;
for (int i = 0; i < length; i++) {
if (txtoption[i] != null) {
Log.i("Value",""+txtoption[i].getText());
}
}

Related

How to remove dynamic button on android studio

I add some button with image and animation in my code, the following is my code.
//add diamond to relativelayout
private void addDiamond(){
Drawable img = getContext().getResources().getDrawable( R.drawable.diamond );
img.setBounds( 0, 0, diamondWidth, diamondHeight );
for (int i = 0; i < diamondRow; i++) {
LinearLayout row = new LinearLayout(getContext());
row.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
diamondHeight+120));
for (int j = 0; j < diamondCol; j++) {
Button btnTag = new Button(getContext());
btnTag.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
btnTag.setCompoundDrawables(null, img, null, null);
btnTag.setText("0.0158" + (j + 1 + (i * diamondCol)));
btnTag.setTextColor(Color.WHITE);
btnTag.setTextSize(8);
btnTag.setBackgroundColor(Color.TRANSPARENT);
btnTag.setId(j + 1 + (i * diamondCol));
btnTag.setOnClickListener(btnClick);
row.addView(btnTag);
}
diamond_lyt.addView(row);
}
animate(diamond_lyt);
}
private Button.OnClickListener btnClick = new Button.OnClickListener(){
public void onClick(View v){
Button button = diamond_lyt.findViewById(v.getId());
Toast.makeText(getContext(), String.valueOf(button.getId()), Toast.LENGTH_SHORT).show();
ViewGroup layout = (ViewGroup) button.getParent();
layout.removeView(button);
}
};
Now I wnat to click these button to remove it individually.
But it is very strange in the result.
When I click two column first button, it remove two column last button.
Please how can I solve this problem?
There's nothing wrong with the click, it removes the views correctly as you click on them. I guess whenever you remove a button, the remaining buttons in the row shift towards left creates an illusion which makes you think it removes the wrong button.
If you intend to have a grid-like layout, that the buttons should always stay in their positions on screen, you could try setting the visibility to View.INVISIBLE instead of removing the view, or replace it with an empty view of the same size.
This one too simple.....
Instead of this ...
private Button.OnClickListener btnClick = new Button.OnClickListener(){
public void onClick(View v){
Button button = diamond_lyt.findViewById(v.getId());
Toast.makeText(getContext(), String.valueOf(button.getId()), Toast.LENGTH_SHORT).show();
ViewGroup layout = (ViewGroup) button.getParent();
layout.removeView(button);
}
};
Try this one ....
private Button.OnClickListener btnClick = new Button.OnClickListener(){
public void onClick(View v){
Button button =((Button)v);
((ViewGroup) button.getParent()).removeView(button);
}
};
When Your button click onClick(View v) v give you instance of button. TypeCaste from View to Button and remove it.

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!!

OnClickListener() for dynamic amount of buttons

Background
I am creating buttons dynamically in a for loop by following Pragnesh Ghota's solution of one onClick listener for every button in the format of dymmeh's individual initialization solution:
LinearLayout someLayout = (LinearLayout) findViewById(R.id.theRoom);
for (int i = 0; i < neededButtons.length; i++){
neededButtons[i] = new Button(this);
neededButtons[i].setText(names[i]);
neededButtons[i].setOnClickListener(this);
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
}
In addition, I am making one onClick listener by implementing View.OnClickListener in the actvity class. My class is defined as such:
public class RecallActivity extends AppCompatActivity implements View.OnClickListener{
...
}
I have followed the other steps of Pragnesh Ghota's solution with success. However...
Problem
The fourth step of Pragnesh Ghota's solution mentions the use of a case statement to check if any of the buttons have been clicked. This works when the amount of buttons is known. However, since I am following the format laid out in dymmeh's solution, I do not know how many buttons I am checking until execution time.
Question
How do I do a control flow statement within an overrided onClickMethod for a dynamic amount of buttons?
Just create a new OnClickListener for each button when you're creating them.
LinearLayout someLayout = (LinearLayout) findViewById(R.id.theRoom);
for (int i = 0; i < neededButtons.length; i++){
neededButtons[i] = new Button(this);
neededButtons[i].setText(names[i]);
neededButtons[i].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// add your click listener code here
}
})
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
}
you can set a id for button .just like this:
LinearLayout someLayout = (LinearLayout) findViewById(R.id.theRoom);
for (int i = 0; i < neededButtons.length; i++){
neededButtons[i] = new Button(this);
neededButtons[i].setText(names[i]);
neededButtons[i].setId(i);
neededButtons[i].setOnClickListener(this);
...
);
}
then find view by id in OnClickListener. for example:
public class RecallActivity extends AppCompatActivity implements View.OnClickListener{
#overide
public void onClick(View view){
if(view.getId == 0){
.....
}
}
}
The simplest solution is using setTag and getTag for your buttons. You can use an object with setTag and getTag. Whenever you're creating a button, set the tag for it:
for (int i = 0; i < neededButtons.length; i++){
neededButtons[i] = new Button(this);
neededButtons[i].setText(names[i]);
neededButtons[i].setTag(names[i]);
// or you can use the index as the tag with:
// neededButtons[i].setTag(i);
neededButtons[i].setOnClickListener(this);
}
Then you do something for each button by checking the tag:
#Override
public void onClick(View v) {
doSomething(v.getTag());
}
private void doSomething(Object tag) {
// in case your tag is the index, than you can convert it to
// integer and use switch case
int index = (int) tag;
switch(index) {
case 1:
...
break;
case 2:
...
break;
...
}
}

How I can save a linear layout and all its inner views and use it later android

I have one activity and inside it I have a Linear layout (lets name it the "main linear layout") and I am adding dynamically created view inside it (text views, linear layouts, edit texts, ...etc).
In the bottom of the screen there are two button (next and back).
If the user clicked on next button I should save the current "main linear layout " in a list for example and then I am generating a new views and I add it inside the "main linear layout" then .
And if the user clicked on back button I should restore the "main linear layout" and show all its views.
I don't know how I can do it.
I hope my description is clear :)
Take a look at onSaveInstance for preserving the view on the main screen when leaving to a different activity or screen orientation.
You can also try and use the buttons to hide the layouts using Visibility instead of trying to navigate through them.
This may help you. but concrete code need you write it yourself.
public class TestActivity extends Activity{
Stack<LinearLayout> layouts = new Stack<>();
FrameLayout container;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button btnPre = new Button(this);
Button btnNext = new Button(this);
btnPre.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
container.addView(layouts.pop());
}
});
btnNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
LinearLayout linearLayout = (LinearLayout) container.getChildAt(0);
layouts.push(linearLayout);
container.removeAllViews();
container.addView(createNextView());
}
});
}
private LinearLayout createNextView(){
LinearLayout linearLayout = new LinearLayout(this);
return linearLayout;
}
}
Thank you all for your comments.
I haven't test Cyrus answer. I will post my answer as well in case someone has the same problem in Xamarin.Android since I am using it.
I fixed it like this:
I added this in next button click event and previous button click event:
AddQuestionsLinearLayoutToPagesLinearLayoutsList();
And the AddQuestionsLinearLayoutToPagesLinearLayoutsList() body is, of course you can change it the way you want:
private void AddQuestionsLinearLayoutToPagesLinearLayoutsList()
{
//Create a new linear layout to add views into it and saved it in _mPagesLinearLayouts list at index _mPageIndex
LinearLayout savedLinearLayout = new LinearLayout(this);
//List of _mQuestionsLinearLayout views
List<View> views = new List<View>();
//Add all _mQuestionsLinearLayout to views list
for (int i = 0; i < _mQuestionsLinearLayout.ChildCount; i++)
{
views.Add(_mQuestionsLinearLayout.GetChildAt(i));
}
//Remove views from main questions linear layout
_mQuestionsLinearLayout.RemoveAllViews();
//Add all views from the views list to savedLinearLayout
for (int i = 0; i < views.Count; i++)
{
savedLinearLayout.AddView(views[i]);
}
//Add savedLinearLayout to _mPagesLinearLayouts list at index _mPageIndex
_mPagesLinearLayouts.Insert(_mPageIndex, savedLinearLayout);
}
In creating views method:
if(NeedToCreateViews())
{
//create views here and add it to _mQuestionsLinearLayout
}
//Get all saved views and add it to _mQuestionsLinearLayout
else
{
//List of _mPagesLinearLayouts[_mPageIndex] LinearLayout views
List<View> views = new List<View>();
//Add all _mPagesLinearLayouts[_mPageIndex] LinearLayout to views list
for (int i = 0; i < _mPagesLinearLayouts[_mPageIndex].ChildCount; i++)
{
views.Add(_mPagesLinearLayouts[_mPageIndex].GetChildAt(i));
}
//Remove all views from _mPagesLinearLayouts[_mPageIndex] linear layout
_mPagesLinearLayouts[_mPageIndex].RemoveAllViews();
//Remove the linear layout at index _mPageIndex
_mPagesLinearLayouts.RemoveAt(_mPageIndex);
//Add all views from views list to _mQuestionsLinearLayout
for (int i = 0; i < views.Count; i++)
{
_mQuestionsLinearLayout.AddView(views[i]);
}
}

Dynamically creating Buttons and setting onClickListener

I have problem with handling dynamically created Buttons on Android. I'm creating N buttons and I have to do the same method when button is clicked but I have to know which button is clicked.
for (int i = 0; i < NO_BUTTONS; i++){
Button btn = new Button(this);
btn.setId(2000+i);
...
btn.setOnClickListener((OnClickListener) this);
buttonList.addView(btn);
list.add(btn);
Cucurrently I'm adding ID to every button and I'm using the method below to see which button was clicked. (line btn.setId(2000+i); and btn.setOnClickListener((OnClickListener) this);). This method is also implemented in the activity.
#Override
public void onClick(View v) {
switch (v.getId()){
case 2000: selectButton(0);
break;
...
case 2007: selectButton(7);
break;
}
}
This doesn't look good to me so i'm asking is there some better way to do this? or how to send some information to onclick event? any suggestions?
You could create a method that returns an onclickListener and takes a button as a parameter. And then use that method to set the onClicklistener in the first loop you have..
Update: code could be soemthing along these lines:
View.OnClickListener getOnClickDoSomething(final Button button) {
return new View.OnClickListener() {
public void onClick(View v) {
button.setText("text now set.. ");
}
};
}
as a method in the activity and then use it in the loop like this
button.setOnClickListener(getOnClickDoSomething(button));
I got one solution for this..
use this code in onCreate
linear = (LinearLayout) findViewById(R.id.linear);
LayoutParams param = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1.0f);
Button[] btn = new Button[num_array_name.length];
for (int i = 0; i < num_array_name.length; i++) {
btn[i] = new Button(getApplicationContext());
btn[i].setText(num_array_name[i].toString());
btn[i].setTextColor(Color.parseColor("#000000"));
btn[i].setTextSize(20);
btn[i].setHeight(100);
btn[i].setLayoutParams(param);
btn[i].setPadding(15, 5, 15, 5);
linear.addView(btn[i]);
btn[i].setOnClickListener(handleOnClick(btn[i]));
}
after onCreate create one method of return type View.OnClickListener like this..
View.OnClickListener handleOnClick(final Button button) {
return new View.OnClickListener() {
public void onClick(View v) {
}
};
}
Button.OnClickListener btnclick = new Button.OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Button button = (Button)v;
Toast.makeText(getApplicationContext(), button.getText().toString(),2).show();
}
};
call this listener by btn.setOnClickListener(btnclick);
View IDs should not be used for these purposes as View Ids are generated on compilation time depending on IDs defined in xml layout files.
Just place your own IDs in the setTag() method which is available at the View level (so Buttons inherit them). This "tag" can be anything that allow you to recognize a View from others. You retrieve its value with getTag().
instead use setTag() function to distinct easily.
for(int i=0;i<4;i++) {
Button btn = new Button(this);
btn.setTag(i);
btn.setOnClickListener(new View.OnclickListener() {
#Override
public void onClick(View v) {
int i=v.getTag();
switch(i) {
case 1: btn.setText(i);
break;
case 2: btn.setText(i);
break;
case 3: btn.setText(i);
break;
case 4: btn.setText(i);
break;
default: btn.setText("Others");
}
}
}
"This doesn't look good to me" why not? doesn't it work? You could also create a static member variable holding a list of all added buttons, and then look for the clicked button in that list instead.
I don't know why you would want to create N buttons, it looks like your value of N is greater than 10 at least, if you are not trying to show them all at once (I mean fit all of them into one single screen, no scrolling) you could try to recycle the invisible buttons just like we do for list view using a list view holder. This would reduce your memory footprint and boost performance, and differentiate the buttons based either on the text you set on them or a tag or you can even hold a reference to those small number of buttons.
Is preferable not to mess up with the ids, setTag and getTag methods were designed for that purpose, it's the fast and clean way to set a bunch of button listeners on a dynamic layout
This answer may you help:
https://stackoverflow.com/a/5291891/2804001
public class MainActivity extends Activity implements View.OnClickListener
{
LinearLayout linearLayout;
Button [] button;
View.OnClickListener listener;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
linearLayout=(LinearLayout)findViewById(R.id.parent_lay);
String[] array={"U123","U124","U125"};
int length=array.length;
System.out.println("11111111111111111111111111");
button=new Button[length];
for(int i=0;i<length;i++)
{
button[i]=new Button(getApplicationContext());
button[i].setId(i);
button[i].setText("User" + i);
button[i].setOnClickListener(this);
linearLayout.addView(button[i]);
}
}
#Override
public void onClick(View view)
{
view.getId();
Button button=(Button)findViewById(view.getId());
button.setText("Changed");
}
}

Categories

Resources