SwitchCompat setTextOn() and setTextOff() doesn't work on runtime - java

I've tried to set the text on SwitchCompat, but it doesn't work. It only work for the first time. But when you tried to change the text (eg. when button is clicked), it doesn't work.
For example:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final SwitchCompat switchCompat = (SwitchCompat)findViewById(R.id.switch_test);
switchCompat.setTextOn("Yes");
switchCompat.setTextOff("No");
switchCompat.setShowText(true);
Button buttonTest = (Button)findViewById(R.id.button_test);
buttonTest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
switchCompat.setTextOn("YOO");
switchCompat.setTextOff("NAH");
//switchCompat.requestLayout(); //tried to this but has no effect
//switchCompat.invalidate(); //tried to this but has no effect
}
});
}
You will see that the text stays as Yes and No. I've tried to call requestLayout() and invalidate() with no success. Any idea?

The problem is, that SwitchCompat is not designed with that case in mind. It has private fields mOnLayout and mOffLayout, which are computed once and not recomputed later when text is being changed.
So, you have to explicitly null them out in order text change to initiate those layouts to be recreated.
buttonTest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
Field mOnLayout = SwitchCompat.class.getDeclaredField("mOnLayout");
Field mOffLayout = SwitchCompat.class.getDeclaredField("mOffLayout");
mOnLayout.setAccessible(true);
mOffLayout.setAccessible(true);
mOnLayout.set(switchCompat, null);
mOffLayout.set(switchCompat, null);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
switchCompat.setTextOn("YOO");
switchCompat.setTextOff("NAH");
}
});
Result:

Related

Clipboard returns null when I click on the button located in the top view activity and when MainActivity is not active

Clipboard data returns null when MainActivity is not active in top view activity when I click the button in Android java
I read this restriction about android10 and higher, but my activity is not a background service.
I need to get clipboard data when I click on the button located in the top view activity like the Google Translate application.
In my case, the clipboard returns null when MainActivity is not active.
https://developer.android.com/about/versions/10/privacy/changes#clipboard-data
public class MainActivity extends BridgeActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Initializes the Bridge
this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
// Additional plugins you've installed go here
// Ex: add(TotallyAwesomePlugin.class);
}});
startActivity(new Intent(MainActivity.this, FloatingWindow.class));
}
}
public class FloatingWindow extends Activity {
// ... additional code ....
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
floatingButtonDefinedInClass.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try {
self.getClipboardText();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
public void getClipboardText() throws IOException {
try {
ClipboardManager myClipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
ClipData clipData = myClipboard.getPrimaryClip();
if(clipData != null) {
text = (String) clipData.getItemAt(0).getText();
System.out.println(text); // returns null when mainactivity is not active
}
} catch (Exception e) {
e.printStackTrace();
}
}
// ... additional code ....
}
what does "mainactivity is not active" mean? you are getting access to ClipboardManager inside OnClickListener attached to Button, which is a View and need Context, so there must be alive Activity, which keeps this Button on the screen for clicking purpose...
btw. maybe you are you checking on Android 10 or above? it looks like according to docs
Limited access to clipboard data
Unless your app is the default input method editor (IME) or is the app
that currently has focus, your app cannot access clipboard data on
Android 10 or higher.
privacy/security reasons, thats how it will be working now

setOnClickListener not responding when button is clicked

I am fairly new to java but in this case, the button is not responding at all when it is clicked, no errors in the logcat are showing up, the ID of the button is correct and no other posts on here helped solve the issue, this is not all the code but hopefully, this will be enough.
public class activity_main extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_layout);
getSupportActionBar().hide();
}
int error_count;
public void on_click() {
Button page_2 = findViewById(R.id.page_2);
page_2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try {
int mother_edu_input = Integer.parseInt(((EditText) findViewById(R.id.mother_edu_input)).getText().toString());
error_writer("Text_View_Warning_1", mother_edu_input, 4);
if (error_count > 0) {
throw new NullPointerException();
} else {
Intent page_1_button = new Intent(activity_main.this, revision_time.class);
startActivity(page_1_button);
}
} catch (NullPointerException npe) {
}
}
});
}
You set your listener inside a method called on_click() and it doesn't appear like you call this method anywhere.
You should probably call on_click() inside your onCreate() to set the listener when creating your activity.

Set Button Text from a callback

I don't know why I am struggling with this so bad! I have two fragments that are communicating by an interface. The callback should change some data, then trigger a method to change the text of a button. This is the code for the fragment that should be changing button text.
public void updateIngredients(final ArrayList<Ingredient> ingredients){
for (Ingredient I : ingredients) {
recipe.addIngredients(I);
}
Log.d(TAG, "Ingredients size: " + ingredients.size());
updateIngredientText();
}
public void updateIngredientText(){
if(recipe.getIngredients() != null) {
Button bIng = (Button) getView().findViewById(R.id.bAddIngredientsToRecipe);
bIng.setText("Ingredients (" + recipe.getIngredients().size() + ")");
}
}
NOTE I am getting the log with expected results. But the button text does not change at all. I am getting no errors.
I have tried running this in a runOnUiThread, I have tried running it in onAttach and onResume. The button id is correct, because I use bIng to open the other fragment.
Does anyone know why this is not changing my text of my button?
Update
I think it has something to do with this. This is the method called to go back to the fragment with the button that needs changed:
public interface OnIngredientChangedListener {
public void onIngredientAdded(ArrayList<Ingredient> i);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mCallback = (OnIngredientChangedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnIngredientChangedListener");
}
}
save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//save button clicked
//notify AddRecipeActivity that ingredients have been added
mCallback.onIngredientAdded(selectedArray);
end();
}
});
private void end() {
//fragment Transaction here
AddRecipe addRecipe = new AddRecipe();
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.replace(R.id.main_fragment_frame, addRecipe).commit();
}
I think the problem is I am creating a new instance of my fragment.

onClickListener is called only after soft-keyboard press

I write an android app
I set an editText.setOnClickListener(...)
but i see that when the user clicks, the soft-keyboard is opened and only
when the user clicks on a keyboard key - the onClick() is called.
how to catch the click before the soft keyboard is opened?
I want to avoid the keyboard opening.
here is my code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.phone_login);
initMembers();
setOnClickListeners();
initFieldsTexts();
setKeyboardVisibilityListener();
}
private void setOnClickListeners() {
mPhoneNumberField.setInputTextOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
setResult(RESULT_CANCELED);
finish();
}
});
}
and:
public class PhoneLoginFillInField extends LinearLayout {
..
public void setInputTextOnClickListener(OnClickListener onClickListener)
{
mInputText.setOnClickListener(onClickListener);
}
during debugging i see this line is called twice
mPhoneNumberField.setInputTextOnClickListener(new OnClickListener() {
though it's called only from onCreate and there setOnClickListeners(); is called once
You mean EditText should not gain focus; it needs to respond only to click events. Do this:
editText.setFocusableInTouchMode(false);
And then carry on:
editText.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
// Your code...
}
}
Set an onTouchListener to the EditView. Remember to return true to avoid the event propagation.

Only the original thread that created a view hierarchy can touch its views - FATAL EXCEPTION

I am trying to use setContentView method to bring on my views to the front but on doing this i am getting this error.
From searching here Similar questions I found this error usually results when trying to get/set a value of layout view object for e.g. without instantiating it but that's not the case here, i am not even able to set the view.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ticker);
Thread tmr = new Thread() {
public void run() {
try {
sleep(1000);
} catch (InterruptedException iEx) {
iEx.printStackTrace();
} finally {
User usrObj = new User();
if (usrObj.authenticateUser()) {
Intent mainActivity = new Intent(
"android.intent.action.Homeview");
startActivity(mainActivity);
} else {
setContentView(R.layout.login); // <- ERROR
activateLogin();
}
}
}
};
tmr.start();
}
You need to call runOnUiThread to change your a layout from a thread.
runOnUiThread(new Runnable() {
#Override
public void run() {
User usrObj = new User();
if (usrObj.authenticateUser()) {
Intent mainActivity = new Intent("android.intent.action.Homeview");
startActivity(mainActivity);
} else {
setContentView(R.layout.login); // <- ERROR
activateLogin();
}
}
});
As a side note, make sure you don't hardcode strings, in order to avoid typo issues.-
Intent mainActivity = new Intent(YourActivity.this, android.intent.action.Homeview.class);
You're calling setContentView(...) from non-UI thread. Either move it to the main (UI) thread or wrap that single call in:
runOnUIThread(new Runnable() {
#Override
public void run() {
setContentView(R.layout.login);
}
});

Categories

Resources