I have two Switchs buttons in my android Activity.
Both have custom dynamic On/Off texts (that are set at runtime with Switch.setTextOn(CharSeq) ).
They look like this (image found on another SO thread):
The first switch's on/off texts are set once.
My goal is to dynamically modify the on/off texts of the second switch, when the state of the first switch changed.
So I set up a OnCheckedChangeListener on the first switch like this:
switch2.setTextOff("ImOff"); // works, the text is updated on the switch
switch2.setTextOn("ImOn"); // same here
switch1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(!isChecked)
{
switch2.setTextOff(myStrings.get(2));
switch2.setTextOn(myStrings.get(3)); // here switch2.getTextOn() returns the value of myStrings.get(3), but the widget still displays ImOn...
} else
{
switch2.setTextOff(myStrings.get(4));
switch2.setTextOn(myStrings.get(5)); // here switch2.getTextOn() returns the value of myStrings.get(5), but the widget still displays ImOn...
}
// I tried to update the switch with this and this
switch2.invalidate();
switch2.setChecked(valuesSwitch.isChecked());
}
});
But this code doesn't work, the on/off texts of the second switch are set on the object (getTextOn/Off returns the right text), but widget still displays the initial text ImOn/ImOff ...
Any ideas? Thanks.
I found a solution in this link,
https://groups.google.com/forum/#!topic/android-developers/1IYypcoYXlk
In a derived class (Which extends switch), override the Following method:
Override
public void request layout () {
try {
java.lang.reflect.Field mOnLayout = Switch.class.getDeclaredField ( "mOnLayout");
mOnLayout.setAccessible (true);
mOnLayout.set (this, null);
java.lang.reflect.Field mOffLayout = Switch.class.getDeclaredField ( "mOffLayout");
mOffLayout.setAccessible (true) ;
mOffLayout.set (this, null);
} Catch (Exception ex) {
Log.e (TAG, ex.getMessage (), ex);
}
super.requestLayout ();
}
Related
I would like to know how I can change the background-color of a TextView, through a switch button. It is necessary to clarify that my switch buttons are in MainActivy and my TextView are in other Activities, to which I access like this:
tvBoton = (TextView) findViewViewById(R.id.Schedule);
tvBoton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(MainActivity.this, central.class);
startActivity(i);
}
});
I don't know if it influences anything, but my switch buttons have SharePreferences:
pol = (Switch) findViewById(R.id.switch18);
sharpol = getSharedPreferences("pol", MODE_PRIVATE);
final SharedPreferences.Editor editorpol = sharpol.edit();
pol.setChecked(sharpol.getBoolean(ex, false));
pol.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean ispolChecked) {
if (ispolChecked) {
editorpol.putBoolean(ex, true);
politica=(TextView) findViewViewById(R.id.polit);
politica.setText("Not working");
} else {
editorpol.putBoolean(ex, false);
}
editorpol.commit();
}
});
As it is in the previous code, I tried inside the ispolChecked, in the true option, to reference the TetView, and then put setText, but this TextView, being inside another layout does not work. I also put setContentView(R.layout.main_activity) several times, but changing it to the respective layouts, but it didn't work either.
Honestly, I don't know what to do anymore. Thanks for your answers.
Use SharedPreference to store the state of the Switch and when you have stored it go to the next Activity and change background color of TextView based on the state of the SharePreference.
Today I came across this really interesting situation.
Suppose:
An EditText is instantiated from XML.
EditText editText;
editText = findViewByID(R.id.editText_xml_id);
Now, I want to listen for change in focus in the EditText. So I write the following code:
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
Log.e("TAG", "Focus Changed in parent" );
}
});
Everything is good up until this point as when change in focus, the Log is triggered.
Now the interesting part:
Say, I want to put the same focus listener, but twice!
So what I will do is:
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
Log.e("TAG", "Focus Changed in parent: First callback" );
}
});
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
Log.e("TAG", "Focus Changed in parent: Second callback" );
}
});
What I had expected was, since editText instance has been set to listen to two instances of View.OnFocusChangeListeners I thought the results would arrive in both listeners.
But only later I realized that only the latter listener ( which was set at the latest ) sent the actual callback inside onFocuChange();
This means, when the focus was changed, I was expecting :
Log.e("TAG", "Focus Changed in parent: First callback" );
Log.e("TAG", "Focus Changed in parent: Second callback" );
but what I got was :
Log.e("TAG", "Focus Changed in parent: Second callback" );
With a little thought, I think this happened because the first listener that was set in editText was replaced by the latter one. And thus only one TAG was hit. (Please correct me if I'm wrong on this)
On experimenting further, I thought what if I assign editText to a different EditText variable and then set two unique listeners to each?
So I did this :
EditText childEditText1;
childEditText1 = editText;
Then I assigned two different listeners:
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
Log.e("TAG", "Focus Changed in child" );
}
});
childEditText1.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
Log.e("TAG", "Focus Changed in parent" );
}
});
On changing focus, what I was expecting was both the tags to be hit. This was because now there are two DIFFERENT instances of the same variable, and they each listen to two DIFFERENT listeners. But again, only one was hit.
Expectation:
//Expected
Log.e("TAG", "Focus Changed in child" );
Log.e("TAG", "Focus Changed in parent" );
Reality:
//Reality
Log.e("TAG", "Focus Changed in parent" );
What I am guessing is no matter what, both the EditText instances are pointing to the same memory space ? Or what is it? Because otherwise both the TAGS would have been hit.
Now, this would be as expected if there were some String and its values were being changed.
Like:
String str = "hi";
str1 = str;
str1 = str1 + " there";
Log.e("TAG", "str " + str );
Result: hi
Log.e("TAG", "str1 " + str1 );
Result : hi there
But from above experiment, it was like :
Log.e("TAG", "str " + str );
Result: hi there
//which is not the case
And this bugs my mind a lot.
Please explain why this sort of anomaly with EditText and if there is any technical term for this in Java. And do point to any resource or books that explain such better. I'm not new to Android but this definitely is.
Thanks!
his was because now there are two DIFFERENT instances of the same
variable, and they each listen to two DIFFERENT listeners. But again,
only one was hit. Expectation:
you are calling a setter on the same reference. The last one wins (it overrides the previous one)
Please explain why this sort of anomaly with EditText and if there is
an y technical term for this in Java.And do point to any resource or
books that explains such better. I'm not new to Android but this
definitely is.
Assigning a reference won't copy an object. It is not related to EditText
First question: the first listener that was set in editText was replaced by the latter one :
cause: http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/view/View.java#6318
//view.java
/**
* Register a callback to be invoked when focus of this view changed.
*
* #param l The callback that will run.
*/
public void setOnFocusChangeListener(OnFocusChangeListener l) {
getListenerInfo().mOnFocusChangeListener = l;
}
ListenerInfo getListenerInfo() {
if (mListenerInfo != null) {
return mListenerInfo;
}
mListenerInfo = new ListenerInfo();
return mListenerInfo;
}
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/view/View.java#4271
and so u can see , there is only one changelistener could be set . and the second one will replace the first one.
second question: upper answer is quite good.
This is a general programming concept.
1- editText.onFocusListener is null.
2- editText.onFocusListener is changed by the below block. It now prints the first Log.
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
Log.e("TAG", "Focus Changed in child" );
}
});
3- editText.onFocusListener is changed by the below block. It now prints the other Log.
childEditText1.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
Log.e("TAG", "Focus Changed in parent" );
}
});
This is completely different to something like addOnChangeListener.
The above is a set function which is different to an add Function.
Hope this clears it up!
private EditText editTextone;
private Editext editTexttwo;
editTextone =(EditText) findViewByID(R.id.editText_xml_id_one);
editTexttwo =(EditText) findViewByID(R.id.editText_xml_id_one);
I have dynamic buttons that are created by a variable that can change.I want that these buttons have two functions. I did one option but I don't know how to implement the other option.
the first time I click the button I call a function that do something and the second time that I click the same button I would like to do another action. And I want to repeat this running with all the dynamic buttons created.
My code is:
LinearLayout buttonsLayout = (LinearLayout)findViewById(R.id.linearlayoutUp);
for(int i=0;i<drawView.getNumeroMallas();i++){
Button buttonMalla = new Button(this);
buttonMalla.setText("Malla "+(i+1));
buttonMalla.setId(i+1);
final int index = i;
buttonMalla.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Malla malla = drawView.getMalla(index);
drawView.paintMallaSelected(malla);
}
}
});
buttonsLayout.addView(buttonMalla);
}
}
EDIT - Very important:
I readed your code again, you could use the getTag/setTag to remember the last state of the button (i missed the for part, sorry!)
for(int i=0;i<drawView.getNumeroMallas();i++){
Button buttonMalla = new Button(this);
buttonMalla.setText("Malla "+(i+1));
buttonMalla.setId(i+1);
buttonMaila.setTag(Boolean.FALSE);
Then in setOnClickListener
if (((Boolean)v.getTag()) == Boolean.TRUE)
{
// Do first action
v.setTag(Boolean.FALSE);
}
else
{
// Do second action
v.setTag(Boolean.TRUE);
}
An idea could be to use a variable to know which was the last action.
A boolean variable
private boolean action = false;
If action is false do the first thing and set it to true. If it's true do the second action and set it to false.
It should go out any method (global of the class)
Something like
private boolean action;
buttonMalla.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (action == true)
{
// Do first action
}
else
{
// Do second action
}
action = !action;
Malla malla = drawView.getMalla(index);
drawView.paintMallaSelected(malla);
}
}
});
Anyway if it does something of important you should manage better the button (example button action is not based on a boolean variable but in a specific state.) time ago i builded a "select all" and "unselect all" function in an app and i checked if the user have unselect manually something to let the button act again like a "select".. I hope i gave to you an idea.
Anyway the boolean variable is the most immediate way to do it.
In my app I have multiple TextViews (the number of this elements is changing on activity creation). I want to execute some function on touch of each element: for instance change the background. I try to avoid writing the same function for each element.
I would like it to work like jQuery so if I trigger some event that are from some class the this element changes.
I hope it is clear, thanks!
Have your activity implement OnClickListener, and then in the onClick method put your common code, and call setOnClickListener(this); on each of your TextViews.
If you have more than one type of View being clicked, enclose the TextView specific code in:
if(<name of the view parameter in your onClick method) instanceof TextView)
{
//Code here
}
EDIT
Another method would be to create your own Custom TextView and override the method in that itself. Something like:
public class MyTextView extends TextView {
//Various constructors go here
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//Do your stuff here, your textview has been touched
return true;
}
return super.onTouchEvent(event);
}
}
Then instead of using TextView tv = new TextView(context);, use MyTextView tv = new MyTextView(context);
simple:
onCreate( //...
// do your layout creation
TextView tv = new TextView(context)
tv.setOnClickListener(clickListener);
tv.setTag(0); // this tag can be any object. So feel free to add a KEY_string, or anything that u might use to later identify your view on the click listener.
tv = new TextView(context);
tv.setOnClickListener(clickListener);
tv.setTag(1);
} // finish on create
private OnClickListener clickListener = new OnClickListener() {
#Override
public void onClick(View v) {
int id = (Integer)v.getTag();
switch(id){
case 0):
// do stuff
case 1:
// do other stuff
}
};
you also can use several other listeners, depending on your needs, just use the auto complete on Eclipse to check all the options for tv.setOn...
I want my toggle button's ON text to be large and OFF text to be small. But can't do it.. any suggestions? This is what i was trying
mf=(ToggleButton)findViewById(R.id.mf);
if(mf.isEnabled()==true)
{
mf.setTextSize(13);
}
else
mf.setTextSize(8);
Your code has to be called each time you click on your button. so use :
toggleButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (toggleButton.isChecked()) {
toggleButton.setTextSize(13.0f);
} else {
toggleButton.setTextSize(8.0f);
}
}
});
You can set OnClickListner with a easy method. In your .xml put the option
android:onClick="nameOfMethod"
And then in your code:
public void nameOfMethod(View v){
}
Where v is the togglebutton in this case ( ToggleButton mf = (ToggleButton)v; )
I put the solution here:
mf=(ToggleButton)findViewById(R.id.mf);
if(mf.isChecked())
{
mf.setTextSize(13);
}
else
mf.setTextSize(8);
Use isChecked() instead of isEnabled()
You need to do some debugging.
Firstly:
if(mf.isEnabled()==true)
can be
if (mf.isEnabled())
Does mf.setTextSize(13) on it's own work as expected?
Add some logging:
if (mf.isEnabled())
{
// Add some logging, is this line reached correctly?
mf.setTextSize(13);
}
else
// Add some logging, is this line reached correctly?
mf.setTextSize(8);
Chances are you need to change isEnabled() to isChecked(). isEnabled() means exactly that, whether it's enabled or not. You want to know whether the button has been checked.