Add dynamically input text and buttons in activity android - android

I have an application with an input text where the users have to insert an information and a button "+" beside to input text.
I would like to make my form dynamic in a way that when a user pushes on "+" button appears dynamically another text input and another "+" button beside this one, the process is repeated in the same way.
I created and xml file, sample_content:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/attempt"
android:layout_alignParentBottom="true"
android:text="TextView" />
<Button
style="?android:attr/buttonStyleSmall"
android:layout_width="36dp"
android:layout_height="32dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="22dp"
android:text="+" />
<EditText
android:layout_width="229dp"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginRight="14dp"
android:layout_toLeftOf="#+id/addKey"
android:background="#drawable/inputtext_corner"
android:ems="10"
android:textSize="18sp" >
<requestFocus />
</EditText>
</RelativeLayout>
and in my Activity, AddDeviceActivity I put:
inflater = LayoutInflater.from(AddDeviceActivity.this);
Button addKey = (Button) findViewById(R.id.addKey);
addKey.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
final RelativeLayout canvas = (RelativeLayout) AddDeviceActivity.this.findViewById(R.id.my_canvas);
final View childView = inflater.inflate(R.layout.sample_component, canvas, false);
// TODO: Look up the 5 different signatures of the addView method,
// and pick that best fits your needs
canvas.addView(childView);
}
});
But this solution doesn't work because when I add the first input text and the first button, I don't know how to make the second button work in my AddDeviceActivity dynamicly

Just wondering whether you can do this:
Have your activity implement OnClickListener and add this method to your activity:
public void onClick(View v) {
final RelativeLayout canvas = (RelativeLayout) AddDeviceActivity.this.findViewById(R.id.my_canvas);
final View childView = inflater.inflate(R.layout.sample_component, canvas, false);
canvas.addView(childView);
((Button)childView.findViewById(R.id.addKey)).setOnClickListener(AddDeviceActivity.this);
}
And then change your initial code to use
addKey.setOnClickListener(this);
instead of an anonymous inner class.
I haven't tested this, but don't see why it wouldn't work.

check out this, pass null instead of canvas object in inflate() method
addKey.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
final RelativeLayout canvas = (RelativeLayout) AddDeviceActivity.this.findViewById(R.id.my_canvas);
final View childView = inflater.inflate(R.layout.sample_component, null, false);
// TODO: Look up the 5 different signatures of the addView method,
// and pick that best fits your needs
canvas.addView(childView);
}
});

Related

Android my App crash after set button disabled

My app crashes after I pressed a button.
My code:
<android.support.v7.widget.AppCompatButton
android:id="#+id/btn_print_trans"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:onClick="OnClickPrintSimpleApiTest"
android:text="PRINT"
android:textColor="#FFFFFF" />
and:
public void OnClickPrintSimpleApiTest(View view) {
final Button BTN_print = (Button) findViewById(R.id.btn_print_trans);
BTN_print.setBackgroundColor(Color.GREEN);
BTN_print.setEnabled(false);
}
Because the OP defined the onClick method OnClickPrintSimpleApiTest as an attribute in their xml layout file as:
android:onClick="OnClickPrintSimpleApiTest"
They do not need to get a reference to the Button using findViewById().
The Button view is passed to the OnClickPrintSimpleApiTest() method as the parameter "view". Therefore, simply do this:
public void OnClickPrintSimpleApiTest(View view) {
Button BTN_print = (Button) view
BTN_print.setBackgroundColor(Color.GREEN);
BTN_print.setEnabled(false);
}

on adding a child layout more than one time using addView() the child layout buttons stops working

This is my child xml file(repeat.xml) which i want to add in main xml file
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_marginTop="200dp"
android:id="#+id/divider_parent"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp">
<EditText
android:layout_width="350dp"
android:layout_height="50dp"
android:text="enter name here"
android:id="#+id/tv2"
android:layout_marginTop="90dp"/>
<Button
android:layout_width="100dp"
android:layout_height="50dp"
android:text="edit"
android:id="#+id/b1"
android:layout_marginTop="160dp"/>
<Button
android:layout_width="100dp"
android:layout_height="50dp"
android:text="save"
android:id="#+id/b3"
android:layout_marginTop="160dp"
android:layout_marginLeft="110dp"/>
<Button
android:layout_width="100dp"
android:layout_height="50dp"
android:text="button2"
android:id="#+id/b2"
android:layout_marginTop="160dp"
android:layout_marginLeft="220dp"/>
</RelativeLayout>
</FrameLayout>
this is my main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/main"
tools:context="com.example.pawan.recyclerview.Main2Activity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/main1"
android:layout_marginTop="200dp">
</RelativeLayout>
this is my main.java
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
RelativeLayout rl=findViewById(R.id.main1);
// RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
// params.addRule(RelativeLayout.BELOW,R.id.main1);
for (int i=0;i<4;i++) {
View child = getLayoutInflater().inflate(R.layout.repeat, null);
rl.addView(child);
}
final EditText textView2=findViewById(R.id.tv2);
textView2.setEnabled(false);
Button button1=findViewById(R.id.b1);
Button button2=findViewById(R.id.b2);
Button button3=findViewById(R.id.b3);
final TimePicker tp=findViewById(R.id.timePicker);
tp.setEnabled(false);
button3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
textView2.setEnabled(false);
tp.setEnabled(false);
Toast.makeText(getApplicationContext(),textView2.getText().toString()+" time is:" +tp.getCurrentHour() + ":" + tp.getCurrentMinute(),Toast.LENGTH_SHORT).show();
}
});
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent=new Intent(Main2Activity.this, Main3Activity.class);
startActivity(intent);
finish();
}
});
}
}
when i do not use the for loop in main.java and direct add child view only once it's working fine. But since i want to add it multiple times and on adding it using for loop multiple times the repeat.xml buttons stops working, thwy does'nt give any feedback i.e they becomes fixed(not clickable) and textview are not editable. Please give a solution for this :)
Your main error is here:
for (int i=0;i<4;i++) {
// add several layouts
}
// findViewById is outside the loop. So, this code will be executed only once and only for one view.
findViewById does not automatically changes all view with that ID. It just seach and return the first view with that ID. If you have more than one view using the same ID only the first view with that ID will be returned (which is your case because you are inflating same layout several times).
Also, you must find for a View not in the whole screen (since you have several views with same ID). You can search "inside" a specific layout or inside a view...
Instead of:
// Search a view inside the whole screen (root layout).
findViewById(R.id.tv2);
You can use:
// Search a view only inside child
child.findViewById(R.id.b1);
You should do something like:
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
RelativeLayout rl=findViewById(R.id.main1);
for (int i=0;i<4;i++) {
View child = getLayoutInflater().inflate(R.layout.repeat, null);
rl.addView(child);
// -----------------------------------------------------------------
// Not that I'm looking for a R.id.tv2 but inside child view... and not in root view
// Use child.findViewById(R.id.tv2) instead of findViewById(R.id.tv2)
final EditText textView2 = child.findViewById(R.id.tv2);
textView2.setEnabled(false);
// SAME HERE
Button button1 = child.findViewById(R.id.b1);
Button button2 = child.findViewById(R.id.b2);
Button button3 = child.findViewById(R.id.b3);
final TimePicker tp = child.findViewById(R.id.timePicker);
tp.setEnabled(false);
button3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
textView2.setEnabled(false);
tp.setEnabled(false);
Toast.makeText(getApplicationContext(),textView2.getText().toString()+" time is:" +tp.getCurrentHour() + ":" + tp.getCurrentMinute(),Toast.LENGTH_SHORT).show();
}
});
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent=new Intent(Main2Activity.this, Main3Activity.class);
startActivity(intent);
finish();
}
});
}
Note that are better ways to what you want such as ListView, RecyclerView etc... but this is another history.

Android: Unable to Prevent buttons from increasing size and overlapping with other buttons

I am new to Android Programming, what I am trying to do in this Android Application is to create a xml page filled with buttons.
When I click the button, the button would change to light green color and when I click it again, it would change to light grey
The error: I am getting is when I click the button, it increases in size and overlaps with the other buttons, please help me out here, it is not user friendly in this case
attached below is the code:
lockerbooking.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="#+id/sisButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="16dp"
android:layout_marginTop="28dp"
android:text="#string/sis"
/>
<Button
android:id="#+id/solButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/soeButton"
android:layout_alignBottom="#+id/soeButton"
android:layout_alignParentRight="true"
android:text="#string/sol" />
<Button
android:id="#+id/soeButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/sisButton"
android:layout_alignBottom="#+id/sisButton"
android:layout_centerHorizontal="true"
android:text="#string/soe" />
</RelativeLayout>
Code:
makeBooking.java
public class makeBooking extends Activity {
Button sisButton;
Button solButton;
Button soeButton;
Button sobButton;
super.onCreate(savedInstanceState);
// Get the message from the intent
setContentView(R.layout.lockerbookpage);
Intent intent = getIntent();
// Initialize TextViews
sisButton = (Button) findViewById(R.id.sisButton);
solButton = (Button) findViewById(R.id.solButton);
soeButton = (Button) findViewById(R.id.soeButton);
sobButton = (Button) findViewById(R.id.sobButton);
}
public OnClickListener solButtonListener = new OnClickListener(){
boolean flag = true;
public void onClick(View arg0) {
// TODO Auto-generated method stub
if(flag){
solButton.setBackgroundColor(Color.GREEN);
}
else{
solButton.setBackgroundColor(Color.LTGRAY);
}
flag=!flag;
}
};
...The code goes on
Please help me out here, I am eager to learn
to avoid overlapping of buttons, use fixed width and height for buttons:
change this:
android:layout_width="wrap_content"
android:layout_height="wrap_content"
to some this like this:
android:layout_width="100dp" //what ever size suits your layout
android:layout_height="50dp" //fixing this,will not overlap the buttons

How to attach OnClickListener to a button in a custom preference layout?

I have a preference screen that is populated with items from a database. I have this working by creating my own PreferenceActivity. In the activity I create DialogPreference items and add them to my PreferenceCategory To style to preference item on the screen I use a custom layout and apply it using setLayoutResource(R.layout.custom_pref_row)
This basically adds an ImageButton to the view aligned to the right of the layout. This all works fine and my preference screen shows the custom view with the button. My question is how do I attach a click listener to the button in the custom view? I was not able to find a way to get at View for the row from the PreferenceActivity. If my items were not created dynamically I might be able to do this all from XML and then reference the id or the button, but I can do that because I am creating the list dynamically.
Any suggestions on how to get a handle on the ImageButton for each item? In the end I want to configure the button to launch a delete confirmation dialog.
R.layout.custom_pref_row:
<?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="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:paddingRight="?android:attr/scrollbarSize">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dip"
android:layout_marginRight="6dip"
android:layout_marginTop="6dip"
android:layout_marginBottom="6dip"
android:layout_weight="1">
<TextView android:id="#+android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceLarge"
android:ellipsize="marquee"
android:fadingEdge="horizontal" />
<TextView android:id="#+android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#android:id/title"
android:layout_alignLeft="#android:id/title"
android:textAppearance="?android:attr/textAppearanceSmall"
android:maxLines="2" />
<ImageButton android:id="#+id/pref_delete_station" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="#drawable/ic_trash_can" android:layout_alignParentRight="true" android:background="#null"></ImageButton>
</RelativeLayout>
<!-- Preference should place its actual preference widget here. -->
<LinearLayout android:id="#+android:id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:orientation="vertical" />
</LinearLayout>
Related part of my PreferenceActivity:
DialogPreference diaPref;
for (Station mStation : sList) {
diaPref = new StationEditor(this.getPreferenceScreen().getContext(), null, this, mStation);
diaPref.setLayoutResource(R.layout.custom_pref_row);
diaPref.setTitle(mStation.getName());
diaPref.setKey(STATION_PREFIX + mStation.getId());
// add new preference
stationTypesCategory.addPreference(diaPref);
}
You can extend DialogPreference and override the onBindDialogView(View view). Inside this method you can do:
#Override
protected void onBindDialogView(View view) {
((ImageButton) view.findViewById(R.id.pref_delete_station)).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
super.onBindDialogView(view);
}
Your sublcass of DialogPreference can hold any state/value related to the item it represents.
Take a look at this question about general guidelines to extend DialogPreference.
Hope this helps!
OK, Chopin got me thinking in a different direction. I did not realize that the Preference object is also responsible for how its selector appears in a Preference screen.
The setLayoutResouce() function sets the resource for the Dialog itself not the row seen in a Preference screen. This was confusing and I was incorrectly trying to use this in the preference screen to adjust the selector layout there.
The solution is to override onCreateView and return a custom layout there. To me this is counterintuitive because that method usually controls the final view in most other situations.
I alraedy subclassed my Preference (DialogPreference) so all I had to do was add the following...
#Override
protected View onCreateView (ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View customRow = inflater.inflate(R.layout.preferences_station_list_row, null);
((ImageButton) customRow.findViewById(R.id.pref_delete_station)).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.i("c","clicked");
}
});
customRow.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
showDialog(null);
}
});
customRow.setClickable(true);
return customRow;
}
One problem I ran into was that at first the row itself was no longer clickable but the button was. I had to add a listener on the whole view and manually call ShowDialog(). The only thing missing now is that when clicked from the Preference screen the item no longer shows a highlight. Any idea what styles I should apply so the list shows the highlight like it normally does?

dynamic number of gui elements in Android?

I want to create a gui application for android where the user will be able to add or remove fields of certain type (4 different type of fields) to the application. Is there a way to do so in xml?
The only way I could figure to do so is by edditing the xml file from within the app which sounds as a bad idea for me.
Hope my question is clear.
Yotam.
Edit:
I have added a simple code for direct java implantation:
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.TextView;
public class Leonidas extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.counter);
TextView TV = new TextView (this);
TextView UV = new TextView (this);
TV.setText("hello");
UV.setText("goof");
//setContentView(TV);
//setContentView(UV);
ViewGroup.LayoutParams lpars = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
this.addContentView(UV,lpars);
this.addContentView(TV, lpars);
this.setVisible(true);
}
}
Edit2:
I have searched for example and got the following working:
LayoutInflater inflater;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
inflater = LayoutInflater.from(this);
Button b = (Button) this.findViewById(R.id.alert);
b.setOnClickListener(this);
}
#Override
public void onClick(View v) {
final LinearLayout canvas = (LinearLayout)Leonidas.this.findViewById(R.id.counter_field);
final View cv = this.inflater.inflate(R.layout.counter,canvas,false);
canvas.addView(cv);
}
You can do it from within your handler too (in the implementation class).
After inflating your xml layout, you respond to some kind of user interactions.
In the handler you
either create a new View from
scratch, and specify its
layoutparams,
or inflate one using xml
After having the new view, you add it to the current (this) view, and due to its layoutparams, it will be the size, shape, color, etc. that you want.
Update:
If you'd like to add more complex views to your activity, it's better to write them in xml, and inflate them:
sample_component.xml: //inside res/layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:padding="0px">
<TextView android:id="#+id/servicename_status" android:paddingLeft="15px"
android:paddingRight="5px"
android:textStyle="bold" android:focusable="false" android:textSize="14px"
android:layout_marginLeft="10px" android:layout_marginRight="3px"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
<TextView android:id="#+id/lastcheck" android:focusable="false"
android:textSize="14px" android:layout_width="fill_parent"
android:layout_marginLeft="10px" android:layout_marginRight="3px"
android:layout_height="wrap_content" android:layout_below="#id/servicename_status" />
<TextView android:id="#+id/duration" android:focusable="false"
android:textSize="14px" android:layout_width="fill_parent"
android:layout_marginLeft="10px" android:layout_marginRight="3px"
android:layout_height="wrap_content" android:layout_below="#id/lastcheck" />
<TextView android:id="#+id/attempt" android:focusable="false"
android:textSize="14px" android:layout_width="fill_parent"
android:layout_marginLeft="10px" android:layout_marginRight="3px"
android:layout_height="wrap_content" android:layout_below="#id/duration" />
<TextView android:id="#+id/statusinfo" android:focusable="false"
android:textSize="14px" android:layout_width="fill_parent"
android:layout_marginLeft="10px" android:layout_marginRight="3px"
android:layout_height="wrap_content" android:layout_below="#id/attempt" />
<CheckBox android:id="#+id/alert" android:focusable="false"
android:layout_alignParentRight="true" android:freezesText="false"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="5px" />
</RelativeLayout>
Inside your Leonidas activity class you have the handlers that have to respond to different user actions by adding/removing items to/from the view.
Below is a sample handler of a click event, which uses LayoutInflater, to add the sample_component.xml view to your activity:
public final class MyClickListener implements View.OnClickListener
{
private LayoutInflater inflater;
public MyClickListener()
{
inflater = LayoutInflater.from(Leonidas .this);
}
#Override
public void onClick(View v)
{
// TODO: change RelativeLayout here to whatever layout
// you'd like to add the new components to
final RelativeLayout canvas = (RelativeLayout)Leonidas.this.findViewById(R.id.my_canvas);
final View childView = inflater.inflate(R.layout.sample_component, canvas, false);
// TODO: Look up the 5 different signatures of the addView method,
// and pick that best fits your needs
canvas.addView(childView);
// check which button was pressed
switch (view.getId())
{
case R.id.btn_prev:
//handler for the prev button
break;
case R.id.btn_next:
//handler for the next button
break;
default:
break;
}
}
}
Note, that MyClickListener is implemented as an inline class within your Leonidas activity, thay's why for the context parameter it is used: this.Leonidas.
Update
The R.id.my_canvas would be the id of the view that you want to add components to. it is in your main.xml (or whatever xml you use for your Leonidas view).
If you put the MyClickListener class inside your Leonidas.java class (declare as inline class), it will recognize it.
Instead of specifying elements in the XML, you can create them dynamically and add it to the UI. This is demonstrated in the Android Hello World Tutorial here.

Categories

Resources