I have toggle(Switch) buttons inside my fragment.After coming on the fragment I am reading BLE values and setting the toggle buttons.
#Override
public void sosStatus(boolean sosvalue, BluetoothGattCharacteristic sosCharac) {
if (sosvalue) {
byte[] charValue = sosCharac.getValue();
String valueOfCharInstring = StringUtils.byteToHex(charValue[0]);
Log.d("+++++SosStatus",""+sosCharac.getUuid().toString() + " " + valueOfCharInstring);
if (sosCharac.getUuid().toString().equalsIgnoreCase(BLEConstants._BUTTON_CHARACTERISTIC)) {
if (valueOfCharInstring.equalsIgnoreCase(BLEConstants.EnableCharacInString)) {
setButtonStatus(touchButton,R.id.switch_btn_device_touch,"Enabled");
// touchButton.setChecked(true);
// tvTouchButtonAction.setText("Enabled");
} else if (valueOfCharInstring.equalsIgnoreCase(BLEConstants.DisableCharacInString)) {
setButtonStatus(touchButton,R.id.switch_btn_device_touch,"Disabled");
// touchButton.setChecked(false);
// tvTouchButtonAction.setText("Disabled");
}
}
if (characList.size() > 0) {
gattclientCallBack.readCharacteristicMain(UUID.fromString(characList.remove(characList.size() - 1)));
} else {
useOnCheckedChangeMethod = true;
showProgress(false);
}
} else {
useOnCheckedChangeMethod = true;
showProgress(false);
HandleCharacListData(true,false,"");
}
}
Now since Switch widget is used, what is happening is that when I read the values programatically for first time, it works fine.but when I toggle the button with touch, onCheckChanged is repeatedly getting called as if I set some value, it keeps on calling itself in infinite loop. This is my oncheckchanged code.
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
try {
if (useOnCheckedChangeMethod) {
switch (compoundButton.getId()) {
case R.id.switch_btn_device_touch:
touchButton.setOnCheckedChangeListener(null);
//showProgress(true);
HandleCharacListData(true,false,"");
HandleCharacListData(false,false,BLEConstants.TOUCH_BUTTON_CHARACTERISTIC);
if(characList!=null && characList.size()>0) {
if(b) {
gattclientCallBack.writeCharacteristic(characList.remove(characList.size() - 1), BLEConstants.DisableCharac);
}
else {
gattclientCallBack.writeCharacteristic(characList.remove(characList.size() - 1), BLEConstants.EnableCharac);
}
}
Log.d("Touch++++", "+++");
break;
}
So it continuously keep on toggling as on and off due to the check if(b). :)
what can I do to ensure that the onCheckChange methos only gets called once after the value is set ?
Things that I have also tried
1) Use onClick listener and disable call in oncheckchanged and enable on click.
2) Use onTouch
Thank you :)
That interesting, because inside of setChecked() it actually checks to see if it's in the middle of broadcasting and returns...
public void setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
// Avoid infinite recursions if setChecked() is called from a listener
if (mBroadcasting) {
return;
}
mBroadcasting = true;
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
}
if (mOnCheckedChangeWidgetListener != null) {
mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);
}
mBroadcasting = false;
}
}
The only solution I know of is un-registering the callback before calling setChecked() and register the callback again after your call returns. This works because the callback isn't called asynchronously but instead, called immediately inside of setChecked().
Hey I got my answer in the link below to a question framed little differently . Thanks to this guy :)
onCheckedChanged called automatically
Related
I want to check that Rectangle was tapped. This mehod does the job and it works almost how I want:
private bool CheckRectangleTouch(Rectangle target)
{
var touchCollection = TouchPanel.GetState();
if (touchCollection.Count > 0)
{
foreach (var touch in touchCollection)
{
if (target.Contains(touch.Position))
{
return true;
}
}
}
return false;
}
Problem I have is that after I've tapped rectangle it keeps returning true until I release it (it can register 10-30 times for one tap) and I want it to return true just once - for the first touch.
I've tried this (replace code inside foreach):
var isFirstTouch = !touch.TryGetPreviousLocation(out _);
if (target.Contains(touch.Position) && isFirstTouch)
{
return true;
}
And this (bad one, I don't really want it to register after release):
if (target.Contains(touch.Position) && touch.State == TouchLocationState.Released)
{
return true;
}
But nothing is does it. Either logic is not consistent or doesn't work at all.
So how do I check for tap?
Update: this works but it's very hacky, has delay and gives me random phantom taps:
try
{
var tap = TouchPanel.ReadGesture(); // falls each time when no input
return tap.GestureType == GestureType.Tap && target.Contains(tap.Position);
}
catch { }
return false;
Here's what I ended up doing:
I have singleton to hold my game state (many different props updated as needed). I added to it:
public TouchCollection TouchCollection { get; set; }
Prop to hold TouchPanel.GetState result. I fill it in Games Update method once per frame, as #craftworkgames suggested:
State.TouchCollection = TouchPanel.GetState();
Also I added this prop to my game state:
public bool TouchActive { get; set; }
And this is the method to check for rectangle tap. It returns true only for the first contact in tap:
private bool CheckRectangleTap(Rectangle target)
{
if (State.TouchCollection.Count == 0)
{ // if no input
return State.TouchActive = false;
}
var targetTouched = false;
foreach (var touch in State.TouchCollection)
{
if (target.Contains(touch.Position))
{
targetTouched = true;
}
}
if (targetTouched && !State.TouchActive)
{ // if target is touched and it's first contact
return State.TouchActive = true;
}
return false;
}
It doesn't seem ideal but it works for my case.
I have a switch button for setting the sound of the app On and OFF, although it works normally but when I close the app then open it again.. the switch becomes false automatically..!?
I've tried to save the last state via Shared Preference library Hawk , but it not clear to me how to do it right.!?
That's when I've tried to use Hawk
// ....
bool soundON = Hawk.get("sound"); // NPE !!!
if (soundON) {
soundSwitch.setChecked(true);
soundSwitch.setSelected(true);
} else {
soundSwitch.setChecked(false);
soundSwitch.setSelected(false);
}
soundSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
isSoundEnabled = true;
Hawk.put("sound", true);
} else {
isSoundEnabled = false;
}
Log.i("is checked sound", isChecked + "");
}});
UPDATE - Solution
I used #Shrikant answer, but with just a small change.! I used Boolean instead boolean so I can check for null values which Boolean allows you to do since it can be true or false or null unlike boolean which can be either true or false.
Here's the code
Boolean isSound = Hawk.get("sound");
if (isSound == null) {
// I want the sound to be ON by default so I set it to true
soundSwitch.setChecked(true);
soundSwitch.setSelected(true);
} else {
soundSwitch.setChecked(isSound);
soundSwitch.setSelected(isSound);
Log.i("Sound State > ", isSound + "");
}
Try this
In onCreate() init that Hawk
Hawk.init(context).build();
after this get your sound value from Hawk and set it to switch
boolean isSound = Hawk.get("some",false);
soundSwitch.setChecked(isSound);
soundSwitch.setSelected(isSound);
there is not to check boolean by if else
soundSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Log.i("is checked sound", isChecked + "");
Hawk.put("sound", isChecked);
}
});
I have used 2.0.1 version of Hawk.
In onCreate() method you have to check isSoundEnabled from shared preference whether you checked it from your local variable.
try this:
bool soundValue = Hawk.get("sound");
if (soundValue) {
soundSwitch.setChecked(true);
soundSwitch.setSelected(true);
} else {
soundSwitch.setChecked(false);
soundSwitch.setSelected(false);
}
instead of :
if (isSoundEnabled) {
soundSwitch.setChecked(true);
soundSwitch.setSelected(true);
} else {
soundSwitch.setChecked(false);
soundSwitch.setSelected(false);
}
in onCreate()
You should save the check state at the time of the setOnCheckedChangeListener call. And get the check state at the time of the onCreate call.
I've had a look everywhere on here and nothing is related to my problem. Basically I've implemented a feature which changes the reading direction of my app (1 or -1) now I can get it to initially change direction and it works really well but when I get it to change back (using the same code but changing the direction) it just doesn't update. Just seems like notifyDataSetChanged(); doesn't want to work the second time...?
My code is as as follows:
private void flip() {
if (!isFlipped) {
mData.getItems().removeAll(mData.getItems());
mAdapter.notifyDataSetChanged();
isFlipped = true;
loadData(false, -1);
closeMenu();
} else {
mData.getItems().removeAll(mData.getItems());
mAdapter.notifyDataSetChanged();
isFlipped = false;
loadData(false, 1);
closeMenu();
}
}
What am I doing wrong?
Again, thanks in advance :)
Implement a public method in your RecyclerView code, e.g:
public void clearAll(){
mData.clear();
this.notifyDataSetChanged();
}
And then call that function from your activity (or Fragment):
private void flip() {
if (!isFlipped) {
mAdapter.clearAll();
isFlipped = true;
loadData(false, -1);
closeMenu();
} else {
mAdapter.clearAll();
isFlipped = false;
loadData(false, 1);
closeMenu();
}
}
I am building a firmware for visually disabled people. I have to disable touch screen as and when the external key board is connected. And toggle it with Alt + T . For this I have a static volatile flag in View class called misTouchScreenEnabled. Upon plug in of external keyboard I return false from dispatchTouchEvent(). In View Class :
/*
* A register to hold the status of touch screen
*
*{#hide}
*/
public static volatile boolean misTouchScreenEnabled = false;
public boolean dispatchTouchEvent(MotionEvent event) {
if(event == null)
{
return false;
}
Log.d ("CnxsTA","View :: Into dispatchTouchEvent");
// Added by Harsh Vardhan 05102013
Configuration config = getResources().getConfiguration();
if (config.keyboard != Configuration.KEYBOARD_NOKEYS)
{
// And if the device has a hard keyboard, even if it is
// currently hidden, don't pass the touch events to the view
if(!mIsTouchScreenEnabled)
{
Log.d ("CnxsTA","View :: Into dispatchTouchEvent :: Returning False");
return false;
}
}
// Added By Harsh Vardhan
// Some Other Code...
}
In Launcher I catch the ALT + T in dispatchTouchEvent() and toggle the flag using reflection:
case KeyEvent.KEYCODE_T:
{
//Added By Harsh Vardhan 31052013
Log.d ("CnxsTA","Launcher :: onKeyDown :: T pressed");
if ((event.getMetaState() & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON)
{
Object s;
try
{
Log.d ("CnxsTA","Launcher :: In onKeyDown :: In isAltPressed");
s = ToogleTouchScreen(Class.forName("android.view.View"), "mIsTouchScreenEnabled");
if (s instanceof Boolean)
{
boolean v = ((Boolean) s).booleanValue();
//do something
Log.d ("CnxsTA","Launcher :: onKeyDown :: In isAltPressed :: Toggling touchscreen enable flag :: " + v);
if (accessibilityEnabled)
{
if (mTts != null)
{
if (v)
mTts.speak("Touch Screen enabled", TextToSpeech.QUEUE_FLUSH, null);
else
mTts.speak("Touch Screen disabled", TextToSpeech.QUEUE_FLUSH, null);
}
}
}
else if (s == null)
{
//do something
Log.d ("CnxsTA","Launcher :: onKeyDown :: S is Null");
}
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
//return super.dispatchKeyEvent(event);
return true;
//break;
//Added By Harsh Vardhan 31052013
}
This works well for the Launcher and its workspace, ie. the touch gets enabled and disabled when ALT + T is pressed. But the Panel in the bottom containing the back, home, recent apps and notifications remains unresponsive on touch and so is the UI in the application; though in Exploration Mode the Icons names are spoken on touch but the touch is not implemented. And it all retains to normal sate once the external keyboard is removed.
I think the reason behind this could be that the StatusBar Class and Other Classes extending the View which are taking the flag to be false only has cached the whole class or the variables and methods and is not referring to main memory where the flags have been toggled. I am aware that I have made the flag volatile.
I know that my flag gets toggle as I could confirm this from logcat. Please suggest me the direction I could solve this. Thanking in advance.
I have problems when using a CheckBox in an else if statement. I have a CheckBox list like:
cbapel, cbmangga, cbjeruk, cbbelimbing.
when I tick the checkBoxes cbapel, cbmangga, and cbjeruk the result is "2" instead of "4". What's the solution?
if(MainActivity.cbapel.isChecked() && MainActivity.cbbelimbing.isChecked()) {
tx.setText("1");}
else if(MainActivity.cbapel.isChecked() && MainActivity.cbjeruk.isChecked()) {
tx.setText("2");}
else if(MainActivity.cbapel.isChecked() && MainActivity.cbmangga.isChecked()) {
tx.setText("3");}
else if(MainActivity.cbapel.isChecked() && MainActivity.cbmangga.isChecked() && MainActivity.cbjeruk.isChecked()) {
tx.setText("4");}
else {
tx.setText("NOT FOUND");
}
You are really overlooking the simple solution here, by far (assuming you are just counting the number of checked boxes)
int checked = 0;
if (MainActivity.cbapel.isChecked()) {
checked++;
}
if (MainActivity.cbbelimbing.isChecked()) {
checked++;
}
if (MainActivity.cbmangga.isChecked()) {
checked++;
}
if (MainActivity.cbjeruk.isChecked()) {
checked++;
}
if (checked == 0) {
tx.setText("NOT FOUND");
} else {
tx.setText(String.valueOf(checked));
}
If you aren't looking to count the checkboxes, then I think this follows the same logic as what you tried in your question, but accounts for one condition ever being entered.
String value = "";
boolean bool1 = MainActivity.cbapel.isChecked();
boolean bool2 = MainActivity.cbbelimbing.isChecked();
boolean bool3 = MainActivity.cbmangga.isChecked();
boolean bool4 = MainActivity.cbjeruk.isChecked();
if (bool1) {
if (bool3 && bool4) {
value = "4";
} else if (bool3 && !bool4) {
value = "3";
} else if (!bool3 && bool4) {
value = "2";
}
if (value.isEmpty() && bool2) {
value = "1";
}
} else {
value = "NOT FOUND";
}
tx.setText(value.isEmpty() ? "NOT FOUND" : value);
else if(MainActivity.cbapel.isChecked() && MainActivity.cbjeruk.isChecked()) {
Let's look at this...
Is MainActivity.cbapel.isChecked()? Yes
Is MainActivity.cbjeruk.isChecked()? Yes
So this evaluates to true and so it won't check any of the other conditional statements.
There are many different ways for this logic to flow. But, to know what is best for your situation, depends on what these variables actually mean and what you are doing.
The best advice I could give you from what you have provided is to check the most filtered situation first. So...
if(MainActivity.cbapel.isChecked() && MainActivity.cbmangga.isChecked()
&& MainActivity.cbjeruk.isChecked()) {
tx.setText("4");
}
then add the else ifs after that for the other checks.
Also, cricket has a good suggestion in his comment you are checking the same condition every time so you can remove that and wrap it all in one if to remove some duplication.
Use this listener to each check box and set your conditions accordingly
class CheckboxListeners implements CompoundButton.OnCheckedChangeListener {
private CheckBox checkbox;
CheckboxListeners(CheckBox checkbox) {
this.checkbox = checkbox;
}
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
checkbox.setChecked(isChecked);
}
}