How to indicate currently selected control in Xamarin? - xamarin

The Android device I am using does not have any touchscreen. All it has is a touch pad that can generate KEYCODE_DPAD_UP, KEYCODE_DPAD_DOWN, etc. However, I am not sure if my Xamarin app is responding to these events. Is there any setting that one can enable to identify current selection among a group of controls.
When I go the device's home screen and use the DPad keys to move around, I see a thin square around the icon that is currently selected. I am hoping there is a similar setting within Xamarin app to turn on this behavior. Regards.

You can simply use CurrentFocus of the activity to get the current focused control. But first of all, when control is focused, it will be highlighted, usually we can modify the control's background to a drawable state list resource for example:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="#drawable/button_pressed" /> <!-- pressed -->
<item android:state_focused="true"
android:drawable="#drawable/button_focused" /> <!-- focused -->
<item android:state_hovered="true"
android:drawable="#drawable/button_focused" /> <!-- hovered -->
<item android:drawable="#drawable/button_normal" /> <!-- default -->
</selector>
This visual behavior is for a button to indicate that user has navigated to the control.
When I go the device's home screen and use the DPad keys to move around, I see a thin square around the icon that is currently selected. I am hoping there is a similar setting within Xamarin app to turn on this behavior.
So this thin square can be the designed background for focused state.
I don't know if there is any setting for it, but if you want to do it in code behind to indicate which control is currently focused, as I said at the beginning, you can use CurrentFocus of the activity. For example:
public override bool DispatchKeyEvent(KeyEvent e)
{
if (e.Action == KeyEventActions.Up)
{
if (e.KeyCode == Keycode.DpadDown || e.KeyCode == Keycode.DpadUp
|| e.KeyCode == Keycode.DpadLeft || e.KeyCode == Keycode.DpadRight)
{
var view = this.CurrentFocus;
view.SetBackgroundDrawable(...);
}
}
return base.DispatchKeyEvent(e);
}
Forget to say, if you want to do it in code behind, don't forget to change the background back to its old state when a new control is focused. Emmm, seems the state list resource is the best choice here.

Related

WIN32: Duplicate Standard Button Control (disabled Icon / hotkey underline) in Owner Draw Button?

So for the simple feat of wanting to put an icon on the right side of button text instead of the left resulted in having to use owner draw buttons (but someone here said Custom Draw is actually available if using visual themes). Okay, fine, but now I'm finding you can't really duplicate what Windows standard buttons do when it's not in owner draw mode.
For a normal enabled button I can get the look correct by checking if visual styles are available or not and then using either the DrawThemeBackground() / DrawThemeText() or DrawFrameControl() / DrawText(). However the hot key underline character is shown even when alt key is not pressed, the default buttons don't show it until alt pressed.
For a disabled button, I can't duplicate the disabled look of the icon placed on the button. I tried DrawState() over DrawIconEx() but that looks like the old Windows 3.1 type grey graphic not the visual style dimmed graphic. I see there is a DrawThemeIcon() for an image list, I guess I could try that (I'd have to test non visual style mode to see if DrawState() matches when not using visual styles).
Also, as you hover over the button, the state doesn't change, I understand that if using owner draw, that doesn't occur, maybe it would still work with Custom Draw?
So the two main questions are:
1 - Is there something built-in to the button / owner draw to handle the underlined hotkey only when alt was pressed?
Update to Question 1: I found DT_HIDEPREFIX in DrawText() and using Custom Draw there is the CDIS_SHOWKEYBOARDCUES flag. However with Owner Draw I'm not sure if there is a flag someplace?
2 - How do you draw an icon for a button that is disabled to match what default buttons do?
TIA!!
For shortcut underline you can use WM_QUERYUISTATE to ask if it should be hidden or visible
DWORD draw_text_flags = ...;
if ( SendMessage( control_hwnd, WM_QUERYUISTATE, 0, 0 ) & UISF_HIDEACCEL ) != 0 )
{
// hide prefix
draw_text_flags |= DT_HIDEPREFIX;
}
// some combination of PBS_DEFAULTED, PBS_DISABLED, PBS_HOT, PBS_NORMAL, PBS_PRESSED;
int state = ...;
DrawThemeText( theme, hdc, BP_PUSHBUTTON, state, text, text_len, draw_text_flags, 0, rect );
Answer to Q2: If you create an HIMAGELIST using ILC_COLOR32 | ILC_MASK, and use ILD_NORMAL|ILD_BLEND25 on ImageList_Draw() it gives the same look as windows default buttons for a disabled button.
Based on responses from #Remy-Lebeau and #Daniel-Sęk and reviewing various projects on CodeProject, I create an easy to use class to handle this. It can be found at CodeProject. Thanks Guys.

How to add bezel to WearOS simulator

Samsung started using WearOS in their latest smartwatches, e.g. in Galaxy 4 watch, and I need to test bezel functionality since the latter model does have it. However I didn't find any WearOS devices in AVD supporting bezel.
I've also tried creating a new h/w profile, but didn't find a bezel option there either. All navigation options they have are below. None of them is related to bezel.
I've also tried to find a skin for Galaxy 4, but with no luck so far. The code that doesn't work according to a Galaxy4 owner is below. You can suggest how to fix the code of course, but I still want to know how to test it without buying a watch
view.setOnGenericMotionListener { v, ev ->
if (ev.action == MotionEvent.ACTION_SCROLL &&
ev.isFromSource(InputDeviceCompat.SOURCE_ROTARY_ENCODER)
) {
val delta = -ev.getAxisValue(MotionEventCompat.AXIS_SCROLL) *
ViewConfigurationCompat.getScaledVerticalScrollFactor(
ViewConfiguration.get(this), this
)
if (Math.abs(delta) > 2f) {
val np = if (delta > 0) Util.nextAccount(mAccount) else Util.prevAccount(mAccount)
Util.d(TAG, mAccount + np.toString())
switchAccount(np)
}
true
} else {
false
}
}
nextAccount and prevAccount are some custom functions that switch the view. None of them is called according to a user.
Here is a Tizen Studio emulator with a bezel that can be rotated by dragging the white dot:
I've finally fixed the problem. In a view's layout that is supposed to process the rotary event I've added requestFocus tag:
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:scrollbars="vertical"
android:fadeScrollbars="false"
android:id="#+id/token_scroll"
>
<requestFocus />
...
To test the bezel, I've used menu on the right of the emulator as shown on the picture below. Bezel events are processed correctly at least in the emulator. I'll let you know if it works in real Galaxy 4 smartwatch when hear from the user.
UPDATE
A Galaxy 4 smartwatch user has just confirmed that bezel works after the fix. It confirms that both the fix and the testing method were correct and achieved their goals.

Fade in/out CButton (set transparency)

In a dialog I have an options button. But I don't want it to be visible all the time, only when the cursor is over the dialog, and have a nice fade in/out.
I've tried several things to make the CButton transparent to it fade in/out, but not successful.
For example, I have tried SetLayeredWindowAttributes and UpdateLayeredWindow but I can't get them to work, probably since the CButton is a child.
Any tips how to set the transparency of a CButton?
I have tried SetLayeredWindowAttributes and UpdateLayeredWindow but I
can't get them to work, probably since the CButton is a child.
Layered child windows are supported since Windows 8:
In order to use layered child windows, the application has to declare
itself Windows 8-aware in the manifest.
To do this, add a manifest section like this to your application through project properties > Manifest Tool > Input and output > Additional manifest files:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
</application>
</compatibility>
</assembly>
You propably want to declare support for other Windows versions too.
With the manifest in place, we can now turn a button into a layered window and set the desired transparency (alpha) level:
if( CWnd* pButton = GetDlgItem( IDC_OPTIONS ) )
{
pButton->ModifyStyleEx( 0, WS_EX_LAYERED );
pButton->SetLayeredWindowAttributes( 0, 96, LWA_ALPHA );
}
Adding this code in my overridden CDialog::OnInitDialog(), I got the following result under Win 10:
Note that the button looks like disabled, but this is just coincidence.
To make the button completely opaque again, remove the WS_EX_LAYERED bit:
pButton->ModifyStyleEx( WS_EX_LAYERED, 0 );
If you need to support older OS than Windows 8, you would have to use more involved techniques to achieve the same effect. Just some ideas that come to mind:
Create an owner-drawn or custom-drawn button to have complete control over the appearance of the button, with the ability to fake transparency.
Create an initially hidden button. Create a snapshot of the button as it would look like when visible by sending it a WM_PRINTCLIENT message. Draw the snapshot in place of the actual button with the desired transparency. Show the button once you have reached an alpha value of 255. This is similar to how AnimateWindow() works.

Handsontable edit on mobile device

i know that handsontable is not mobile friendly but is there a workaround that we can edit on mobile devices with the newest version?
Regards
I use Handsontable version 0.25.1, but I imagine the situation is still the same at the very latest release.
My experience is only with iPad device (iOS 9); I cannot speak about all mobile devices.
I found the rendering acceptable. But if you tap a cell to edit nothing happens, which is rather limiting! I made just two small changes to rectify:
Tracing all of this right down in handsontable.full.js, the logic in onCellMouseDown() is testing for event.button === 0 (i.e. left mouse button) to start setting up for recognising the double click to activate the mobile text editor. On a touch device, they are explicitly calling their onMouseDown/Move/Up() from their onTouchStart/Move/End(), passing the mouse events the event structure received for the touch event. However, touch events' event structure does not have a button member, so that is undefined, causing bad behaviour.
Directly setting passed-in event.button = 0 before passing to mouse event handlers solves this. Put in line:
event.button = 0; // set as left mouse button
into onTouchStart() [prior to call to onMouseDown(event), around line 1326] & onTouchEnd() [prior to call to onMouseUp(event), around line 1368].
Now tapping into a cell correctly allows editing. It brings up their MobileTextEditor. Which I did not like for a number of reasons, including the fact that often it appears behind the on-screen keyboard so the user does not even know it is there! I changed their Handsontable.TextCell [around line 4346] so that the editor: line now reads:
editor: (isMobileBrowser() && Handsontable.useMobileEditor) ? getEditorConstructor('mobile') : getEditorConstructor('text'), // only use mobile editor if explicitly called for
So it uses the standard in-place text editor, which I prefer, unless you go hot.updateSettings({useMobileEditor: true}).

Push In/Out Animation Between Activities

I am working on an application that consists of many activities that represent stages. So there is the Stage1Activity, Stage2Activity, Stage3Activity, etc. Each activity has a button (or more buttons) that, once clicked, take the user to the next activity. What I wanted to do was animate the transition between those activities.
I have added two XML files to the res/anim folder. The push_left_in.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="100%p" android:toXDelta="0" android:duration="300"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" />
</set>
And the push_left_out.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0" android:toXDelta="-100%p" android:duration="300"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="300" />
</set>
In the main activity, Stage1Activity I have:
public class Stage1Activity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stage1);
overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event){
if (keyCode == KeyEvent.KEYCODE_BACK){
finish();
overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);
return true;
}
return super.onKeyDown(keyCode, event);
}
}
Now, when I move through activities the transition works as it should. The new activity pushes the old one out of view from the right to the left. I wanted a reverse effect for when the user presses the back button on their device, however the same transition animation plays out. I've played with the android:fromXDelta tag and achieved some pretty weird results but I just don't know how to set it so that upon pressing the back button on the device, the new activity (actually old one newly called with an intent) pushes out the old one from the left to the right.
Basically I want to make it appear like you are moving to the right when progressing through the stages, but when you press back it is supposed to look like you went back (to the left). Apologies if this is a dumb question but I really got confused and I need help :/
Kinda dumb to answer my own question I suppose... But I guess it's only fitting that I clean up my own mess. I've done some more extensive research and played around with the code and I'm proud to say that I've solved the problem. Here's the solution below for reference of anyone else who might need it.
Four animations were needed for this application. First, upon clicking the button on Stage1Activity I wanted to slide and fade out that activity to the left, while sliding in Stage2Activity from the right to the left. This required two XML files:
push_left_in.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="100%" android:toXDelta="0" android:duration="500"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="500" />
</set>
push_left_out.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0" android:toXDelta="-100%" android:duration="500"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="500" />
</set>
These two files are called in the overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out); command placed in the onCreate, right below setContentView. One pushes the old activity out, the other one pushes the new activity in. Now I just needed the opposite effect for when the Back button is pressed on the device. This required a whole new animation (something that I didn't get right away).
So I add two more XML files:
push_right_in.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0" android:toXDelta="100%" android:duration="500"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="500" />
</set>
push_right_out.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="-100%" android:toXDelta="0" android:duration="500"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="500" />
</set>
These other two files are called in the overridePendingTransition(R.anim.push_right_in, R.anim.push_right_out); placed in the onKeyDown method for the Back button response. One slides the old activity out, the other one slides the new activity in - but in reversed direction when compared to the previous animation. Don't forget to change the alpha values as well, because that happened to me lol
Anyway this question is now closed. Sorry for the trouble! Or not, since I at least got the Tumbleweed achievement for it XD

Resources