I have an app which inflates button views on a click of a button(Button A). The button views inflated work properly, executing the code in their onClick method.
Now to save the layout generated, I keep a count of number of times the Button A is clicked and save this value using SharedPreferences. In onCreate method I create a for loop for the number of times the Button A was clicked and re-inflate those buttons, thus generating the same layout that was on screen when the app was killed. Though now, the buttons generated in the onCreate method no longer function.
I hope I have made some sense. The problem, when the app is started again in future, it builds the layout as it was when the app was clicked, but the button views no longer function for the onCLick method.
Here's the code for reference:
MainActivity.java
public class MainActivity extends Activity {
EditText et;
String z, r;
LinearLayout ll;
SharedPreferences sp;
Button fb1;
int c=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et=(EditText) findViewById(R.id.et);
sp=getSharedPreferences("MY_PREFS", 0);
if (sp.contains("counter")) {
for (int i=1;i<=sp.getInt("counter", 1);i++) {
cr();}
}
c=sp.getInt("counter", 0);
}
public void cr() {
ll=(LinearLayout) findViewById(R.id.ll);
LayoutInflater li=getLayoutInflater();
View vw=li.inflate(R.layout.infla, null);
ll.addView(vw);
fb1=(Button) vw.findViewById(R.id.btn);
fb1.setId(c);
}
public void click(View v) {
int z=v.getId();
switch (z) {
case (R.id.button):
et=(EditText) findViewById(R.id.et);
cr();
et.setText("");
c=c+1;
break;
}
Editor e=sp.edit();
//e.putString("check", r);
e.putInt("counter", c);
//e.putInt("id", c);
e.commit();
for (int i=0; i<=c;i++){
if (z%2==0) {//Present
et.setText("Present");}
else if(z%2==1)
et.setText("Absent");
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
activity_main.xml
<LinearLayout 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/ll"
tools:context=".MainActivity" >
<EditText
android:id="#+id/et"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:ems="10"
android:hint="Enter something" >
<requestFocus />
</EditText>
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:onClick="click"
android:text="Click" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="remove" />
</LinearLayout>
infla.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="#+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:onClick="click" />
</LinearLayout>
Edit:
You seem to have assigned redundant id's to the button during initialization.Each button would be assigned the value 'c' instead of 0 to 'c'.
Additionally It seems only logical to create click listeners on the fly as well ,since you are inflating button on the go.Try implementing the onclicklistener instead of the hardwired click() method in the xml.
i.e
public void cr() {
ll=(LinearLayout) findViewById(R.id.ll);
LayoutInflater li=getLayoutInflater();
View vw=li.inflate(R.layout.infla, null);
ll.addView(vw);
fb1=(Button) vw.findViewById(R.id.btn);
fb1.setId(c);
fb1.setOnClickListener(new View.OnClickListener(){
//Stuff you wish to do on click
});
}
Related
I given Long Click on Linear layout.Code is given below .Its working on Many devices.but not working on few devices Like Samsung Galaxy Tab E, SM-T561 .
activity_main layout,
<LinearLayout
android:id="#+id/ll_accept"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.5"
android:gravity="center">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="10dp"
android:background="#drawable/ic_accept_24dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="#string/new_accept"
android:textColor="#color/new_accept_color"
android:textSize="#dimen/new_job_accept_reject_txt_size" />
</LinearLayout>
MainActivity() class,
public class MainActivity extends AppCompatActivity implements View.OnLongClickListener {
...........
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
.....................
llAccept = (LinearLayout) findViewById(R.id.ll_accept);
llAccept.setOnLongClickListener(this);
......................
}
#Override
public boolean onLongClick(View v) {
switch (v.getId()) {
case R.id.ll_accept:
//do your need
break;
}
}
}
longClicklistener need to return boolean, false if a click listener has to still execute after the long click and true if there are no further actions needed
Another solution could be adding clickable, focusable and other attributes like those to the LinearLayout.
I have a button that calls a dialog. From that button i have 8 buttons: 1,2,3,4,5,6,7, and cancel. These buttons will be used to change the text of the button. The thing is that it doesn't do anything if i set the text inside the dialog.
buttonDefineHits = (Button) rowView.findViewById(R.id.button_define_hits);
buttonDefineHits.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Dialog 1-7 i x para definir los holes
setDialogSetHits();
}
});
.
private void setDialogSetHits(){
final Dialog dialogConfirmPlayers = new Dialog (activity);
dialogConfirmPlayers.setCancelable(false);
dialogConfirmPlayers.setContentView(R.layout.dialog_set_hits);
Button button1Hit = (Button) dialogConfirmPlayers.findViewById(R.id.button_1_hit);
button1Hit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Dialog 1-7 i x para definir los holes
buttonDefineHits.setText("1");
dialogConfirmPlayers.cancel();
}
});
dialogConfirmPlayers.show();
}
You can set the Text of a Button that is defined in a activity from the dialogBox. I guess Aniruddha is wrong in his comment. I mean yes the user cannot have a "Iteration" with the Activity's UI elements as long as a Dialog is shown over it, But programatically you can change the Text property of the Button in your activity. To confirm, this is what I tried:
Created a Dialog on the click event of ImageView.
From the Dialog Button's Click listener, I changed the Text of a editText in the Activity.
Similarly, you should also be able to set the text of the button from the dialog button's click listener.
I think you should remove the 7 buttons from your dialog, and for testing purpose just have one button on it. Then handle the click event on this button and try n set the Activity button's Text. This should work like charm.
Then later you can integrate your 7-buttons.
Here is the working example, you need to modify it accordingly
activity_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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:id="#+id/tv1"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
<Button
android:id="#+id/buttonMain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/tv1"
android:layout_below="#+id/tv1"
android:layout_marginTop="44dp"
android:text="Button" />
</RelativeLayout>
dialog_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cancel" />
</LinearLayout>
MainActivity.java
public class MainActivity extends Activity {
TextView t;
Button bMain;
Dialog d;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
t = (TextView) findViewById(R.id.tv1);
bMain = (Button) findViewById(R.id.buttonMain);
bMain.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
d = new Dialog(MainActivity.this);
d.setTitle("Hello Android..!");
d.setContentView(R.layout.dialog_view);
Button bOK = (Button) d.findViewById(R.id.button1);
Button bCancel = (Button) d.findViewById(R.id.button2);
d.show();
bOK.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
t.setText("OK");
bMain.setText("Changed the text");
d.cancel();
}
});
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
I want to create an activity such as mentioned in photo...
as soon as I press the maximize button I want it to become full screen for the activity and part 1 become minimize, and again when I press the restore button I want it to become in a first state: to be able to see part 1 and part 2 ...
I think if we put two layouts it is possible? Isn't it? Please refer me to a resource to help me about this, or show me the code to achieve a solution.
Part one and two should be in their own layout. After, play with the visilibity property of each layout. Specifically to hide any view without it continues to occupy its space, use the value gone for the visibility property.
Ok, here I go. Below you have a complete example of how to hide/show grouped views.
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" >
<LinearLayout
android:id="#+id/viewsContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5dp" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextBox One" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="TextBox Two" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="TextBox Three" />
</LinearLayout>
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="Hide" />
</RelativeLayout>
Activity
public class MyActivity extends Activity implements OnClickListener {
private boolean viewGroupIsVisible = true;
private View mViewGroup;
private Button mButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mViewGroup = findViewById(R.id.viewsContainer);
mButton = findViewById(R.id.button);
mButton.setOnClickListener(this);
}
#Override
public void onClick(View button) {
if (viewGroupIsVisible) {
mViewGroup.setVisibility(View.GONE);
mButton.setText("Show");
} else {
mViewGroup.setVisibility(View.VISIBLE);
mButton.setText("Hide");
}
viewGroupIsVisible = !viewGroupIsVisible;
}
I hope this helps ;)
There is a bit simplified solution, than Diego Palomar produced, without using additional variable. I'll take his code to show:
public class MyActivity extends Activity implements OnClickListener {
private View mViewGroup;
private Button mButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mViewGroup = findViewById(R.id.viewsContainer);
mButton = findViewById(R.id.button);
mButton.setOnClickListener(this);
}
#Override
public void onClick(View button) {
if (mViewGroup.getVisibility() == View.VISIBLE) {
mViewGroup.setVisibility(View.GONE);
mButton.setText("Show");
} else {
mViewGroup.setVisibility(View.VISIBLE);
mButton.setText("Hide");
}
}
Background
I have a form-like activity, which has some views that can be created dynamically upon pressing.
I'm using an xml for each field that is inflated upon clicking on a button.
What I need is that upon choosing to add a new item, it will get focus, scroll if needed, and show the keyboard so that the user can type things into it. The keyboard may be shown upon adding the field or when clicking on the EditText.
The problem
For some reason, on some devices (and I don't think it's even an android version issue) when inflating the new view, the editText within it can get focus but it doesn't show the keyboard, even if it has focus and the user clicks on it.
In such a case, the only way to show the keyboard is to click on another EditText.
I've tested it, and noticed that it doesn't occur when I don't use xml at all, meaning when i create the views only in code.
The question
Why does it occur? What can I do in order to fix it?
I've already tried so many possible solutions, but none work on all devices.
Sample Code
the next code has the described issue on xperia j (android 4.0.4) an galaxy mini (android 2.3.6) .
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ViewGroup container = (ViewGroup) findViewById(R.id.LinearLayout1);
final LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
findViewById(R.id.button).setOnClickListener(new OnClickListener() {
#Override
public void onClick(final View v) {
final View view = inflater.inflate(R.layout.field, null);
// using the next code works when using it instead of inflating a layout:
// final EditText editText = new EditText(MainActivity.this);
// editText.setText("item " + container.getChildCount());
container.addView(view);
}
});
}
the field layout file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFffffff"
android:gravity="center_vertical" >
<Spinner
android:id="#+id/typeSpinner"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_centerVertical="true"
android:background="#null"
android:padding="5dp" />
<include
android:id="#+id/removeItemView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
layout="#layout/remove_item_view" />
<EditText
android:id="#+id/fieldEditText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="#+id/removeItemView"
android:layout_toRightOf="#+id/typeSpinner"
android:ems="10"
android:focusable="true"
android:focusableInTouchMode="true"
android:hint="field"
android:imeOptions="actionDone"
android:inputType="phone"
android:minWidth="200dp"
android:padding="5dp"
android:singleLine="true"
tools:ignore="HardcodedText" >
<requestFocus />
</EditText>
</RelativeLayout>
the main layout file:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="click"
tools:ignore="HardcodedText" />
</LinearLayout>
</ScrollView>
EDIT: found a partial solution which won't show the keyboard right away, but at least it will be shown when pressing the editText:
public static void forceFocusOnView(final View view) {
if (view == null)
return;
view.post(new Runnable() {
#Override
public void run() {
view.clearFocus();
view.post(new Runnable() {
#Override
public void run() {
view.requestFocus();
}
});
}
});
}
I'm not sure in a reason of that problem. Could be some missmatches when Android sdk were rewritten in order to match some devices.
So I think that the best solution to you is to show your keyboard manually and do not try to move a train, just take the path of the least resistance:
EditText et=(EditText)this.findViewById(R.id.edit_text);
et.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(et, 0);<----------------
}
});
Here you go , man. Wish you luck.
Oh i see...
private EditText et;
private Runnable setFocus;
......
protected void onCreate(...){
.
.
.
setFocus=new Runnable(){
#Override
public void run() {
et.requestFocus();
}
};
}
....
findViewById(R.id.button).setOnClickListener(new OnClickListener() {
#Override
public void onClick(final View v) {
final View view = inflater.inflate(R.layout.field, null);
//try this:
et=(EditText)view.findViewById(r.id.fieldEditText);
et.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(et, 0);<----------------
}
});
container.addView(view);
container.requestLayout();<--------------
et.postDelayed(setFocus,300);
}
});
I have two layouts xml and can't get the second layout to work correctly.
A EditText placed on the second layout doesn't work as expected. It doesn't accept characters.
What am i missing here?
Should i use startActivity() instead?
Main.java
public class Main extends Activity implements View.OnClickListener {
EditText box1, box2;
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
showXml1();
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
String box11 = box1.getText().toString();
Toast.makeText(this, box11,Toast.LENGTH_SHORT).show();
showXml2();
break;
case R.id.button2:
String box22 = box2.getText().toString();
Toast.makeText(this, box22,Toast.LENGTH_SHORT).show();
showXml1();
break;
}
}
public void showXml2() {
setContentView(R.layout.main2);
box2 = (EditText) findViewById(R.id.editText2);
}
public void showXml1() {
setContentView(R.layout.main);
box1 = (EditText) findViewById(R.id.editText1);
}
}
main.xml
<?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="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Main1" />
<EditText
android:id="#+id/editText1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<requestFocus />
</EditText>
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1"
android:onClick="onClick"
/>
</LinearLayout>
mail2.xml
<?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="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Main2" />
<EditText
android:id="#+id/editText2"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<requestFocus />
</EditText>
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button2"
android:onClick="onClick"
/>
</LinearLayout>
Use a meta layout xml file with a structure similar to this one:
meta_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<ViewFlipper
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/root">
<include
layout="#layout/main" />
<include
layout="#layout/main2" />
</ViewFlipper>
And then main.java:
public class Main extends Activity implements View.OnClickListener {
EditText box1, box2;
ViewFlipper root;
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.meta_main);
box1 = (EditText) findViewById(R.id.editText1);
box2 = (EditText) findViewById(R.id.editText2);
root = (ViewFlipper) findViewById(R.id.root);
}
public void onClick(View v) {
EditText editText = null;
switch (v.getId()) {
case R.id.button1:
editText = box1;
root.showNext();
break;
case R.id.button2:
editText = box2;
root.showPrevious();
break;
}
if(editText != null) {
Toast.makeText(this, editText.getText(), Toast.LENGTH_SHORT).show();
}
}
}
Hope it helps ;)
I don't think you can load a new layout that way.
Just put the two EditTexts in one XML and put one visible and the other invisble and with a button click vice versa.
As an alternative to different activities you might want to look at ViewFlipper http://developer.android.com/reference/android/widget/ViewFlipper.html
You are only allowed to call setContentView() once in your activity.
You can either
Create a "Main" layout that just contains a parent I.E. LinearLayout, or Relative layout
setContentView() on the parent. Then acquire a reference to it with findViewById() and call .addView() on your reference passing the inflated xml from one of these two files. .removeView() will allow you to switch to the other one when you like.
or
Include all of your views in one xml layout, but make half of them Visibility.GONE and when you want to switch just make the ones that were GONE be VISIBLE and vice versa
I think it should work, you have to reinitialize references for example every findViewById needs to be called again after calling setContentView(). You are exactly doing so first you are calling showXml1() & then you are clicking button1 which is executing Case1, you are getting the value of box1 & displaying it & then you are calling showXml2() & so on. I have tried your code & it works, i am wounding why its not working on your side?
Another thing is that it may not be a good idea if you have to call findViewbyId() a LOT OF TIMES, so you should avoid it i guess.