we are currently testing sinch sdk for android (v3.12.3) and experiencing following issue: the local view is always placed above other views even if it comes first in view hierarchy and should be beneath views that come later - we want to show local video fullscreen and remotevideo as picture-in-picturue - in this case local fullscreen video covers the pip-view. Consider simple layout
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/black">
<FrameLayout android:id="#+id/fullscreen_video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<FrameLayout
android:id="#+id/pip_video_view"
android:layout_width="150dp"
android:layout_height="112dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginTop="16dp"
android:layout_marginRight="16dp"/>
Pip-View comes last and should be usually above Fullscreen-View. But if we add local video to Fullscreen-View - it covers the Pip-View. Adding local video to Pip works as expected - Pip is above Fullscreen. The Problem is reproducible both on Android Emulator with Android 6.0 and on real device (Samsung Tablet with Android 4.4)
I've made a screenshot to explain the problem
I've found a workaround for the problem. I cannot call it a real solution since it relies on certain type of view being returned from VideoController
View remoteView = vc.getRemoteView();
if (remoteView instanceof SurfaceView) {
((SurfaceView) remoteView).setZOrderOnTop(true);
}
as long as remote view is of type SurfaceView (it is actuall GLSurfaceView), we can make it appear above all windows with setZOrderOnTop. I cannot call it real solution since there is no guarantee that the view returned from getRemoteView will always be SurfaceView (or will provide access to surfaceview). For instance getLocalView returns a wrapper view around surfaceview so there is no legal access to it. I think the possible solution would be to return a "special" view that allows setZOrderOnTop and/or setZOrderMediaOverlay calls on it (you can name the methods different to explain their meaning more clear)
I can confirm that that is the case, it will be adressed in a future release.
Related
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.
I have a simple View composed of an input, button, and recyclerview. User inputs a search string, hits button, recyclerview populates, and then the user clicks on a returned item for a context menu. This all works fine and dandy on iOS, but I'm running into a problem I can't find anything about on android.
ViewModel command
public IMvxCommand<Item> ShowItemMenuCommand
{
get => new MvxCommand<Item>(ShowItemMenu);
}
Layout
</LinearLayout>
<MvvmCross.Droid.Support.V7.RecyclerView.MvxRecyclerView
android:id="#+id/recyclerView_items"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#color/window_background"
app:MvxItemTemplate="#layout/listitemreturnbasic"
app:MvxBind="ItemsSource ReturnedList; ItemClick ShowItemMenuCommand" />
Everything works up until I go to click on a returned item. The command is not ran, the app just closes without a Trace, and debugging stops, if I look through the logs the last thing that appears is this:
[Mono] Assembly Ref addref Xamarin.iOS[0xa85b8d40] -> System[0x857d3240]: 18
[] Assembly used for native types '/storage/emulated/0/Android/data/com.myapp.myapp/files/.__override__/Xamarin.iOS.dll' doesn't match this runtime, nfloat is mapped to double, expecting single.
I can't find any information on the error, and I'm not sure what is causing it as the command is never run in the first place.
I'm looking for a technique to determine in Java if the Android Wear device screen is round or rectangular. Note that this isn't just about layouts; my code actually needs to know which shape it's working with, because they're handled differently.
As far as I can see from code samples online, two different approaches should be possible - but I've been unable to get either of them to work. I'll include them here to eliminate them from the running, or for possible troubleshooting (if anyone can see the problem with them). Please don't refer me to another SO post that just reiterates the solutions that aren't working for me here.
Note that all code here is running on the watch. Also, I'm still using Eclipse, FWIW.
The most straightforward method I've seen involves adding an onApplyWindowInsets() listener to a view in my layout. So I created a listener that looks like this:
#Override
public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
if (insets.isRound()) {
displayShape = "round";
} else {
displayShape = "rectangular";
}
return null;
}
and added it to the root view of my layout with code like this:
view.setOnApplyWindowInsetsListener(this);
in my onCreate() method. Looks OK as far as it goes - but the listener never gets called. I also found advice saying that I needed to invoke it manually, as such:
view.requestApplyInsets();
but that didn't seem to make any difference. I've experimented with putting it on different views, in different lifecycle methods, and so forth, but never once saw it actually get called in my app. This is running on my LG G Watch, BTW.
The second approach is something of a hack, and is based on the published WatchViewStub helper class. I jumped through the hoops to get the wearable support library imported into an Eclipse project, then added the following to my root layout:
<android.support.wearable.view.WatchViewStub
android:id="#+id/watch_view_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:rectLayout="#layout/rect"
app:roundLayout="#layout/round"
/>
and created rect.xml as such:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/layout_type"
android:text="rectangular"
/>
and round.xml like this:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/layout_type"
android:text="round"
/>
Finally, in my onCreate() I added the following Java code:
final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
#Override
public void onLayoutInflated(WatchViewStub stub) {
TextView layoutType = (TextView) findViewById(R.id.layout_type);
displayShape = layoutType.getText().toString();
}
});
It's a long way around the block, but it should work, right? Not so much... displayShape is always set to "rectangular", indicating that it's always rect.xml that gets used, even when running on a round emulator. [I don't have round-screened hardware to try it on just yet.]
So does anyone see where I've gone wrong with either of these two approaches? Or can you suggest a third way which actually works?
After several days spent chasing false leads, I've finally found the answer. It turns out that it's the android:theme of the application in the manifest that makes the difference.
In order for WatchViewStub to use the correct rect/round layouts, it appears that your application must use #android:style/Theme.DeviceDefault as its theme. Here's an example:
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.DeviceDefault">
I expect it would also work if you used a theme that inherited from DeviceDefault, though I haven't tested that. But it appears that if you use any other custom theme, WatchViewStub will not function correctly.
#WaynePiekarski, it'd be nice if this was documented somehere.
Also, here are a couple of other tips that I learned along the way:
The rectangular layout always inflates before the round layout; IOW, on a round device, you'll get two onLayoutInflated() callbacks. This is kind of a pain if you're using the layout inflation to get the screen shape into your Java code, and that turns out to be necessary, because...
Calling setOnApplyWindowInsetsListener() on WatchViewStub prevents the round layout from loading at all (at least in my testing). So if you try to use this callback to determine the screen shape, round devices will still get the square layout.
Finally, a bonus question: Is there any good reason why Android Wear doesn't just report its screen shape as a resource qualifier? You know, like -land, -large, and so on. Why on earth do we need to mess around with WatchViewStub at all?
I'm not sure why it's necessary in your case to employ a callback, but an answer the general question of screen shape is here: Is there any way to detect if the clock is round?
That is, to acquire the current context, and test
context.getResources().getConfiguration().isScreenRound()
In CanvasWatchFaceService.Engine their is a overide method available setOnApplyWindowInsets you can check whether insets is round or square
#Override
public void onApplyWindowInsets(WindowInsets insets) {
super.onApplyWindowInsets(insets);
if(insets.isRound()){
//round
}
else{
//square
}
}
https://plus.google.com/+NicolasPomepuy/posts/ZJ3KZK6uu2e#+NicolasPomepuy/posts/ZJ3KZK6uu2e
and from https://github.com/PomepuyN/WatchviewStubIssue/blob/bcad0de7fa473c757dc27f9dfe65e31561c6097f/wear/src/main/java/com/example/watchviewstubissue/ViewService.java
mainView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
51 #Override
52 public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
53 if (insets.isRound()) {
54 Log.d("ViewService", "Round");
55 } else {
56 Log.d("ViewService", "Square");
57 }
58 return insets;
59 }
60 });
The diff between your code and his is that you are returning null and he is returning insets.
Back when I did LUA i used to run dofile("..."); to load other lua files and such. Later to find out that this is a very bad practice and can lead to applications breaks.
Now that I am on my way to developing a WebOs application, i want to make sure I am properly changing scene before i pick up bad programming habit.
At the moment this is what I use:
label2Tap: function(inSender, event) {
Mojo.Controller.stageController.popScene();
Mojo.Controller.stageController.swapScene("LogicAndArithmetic");
},
Which works great to get to my LogicAndArithmetic scene, is this the best practice to do such?
Thanks.
The scene model in the Mojo framework of webOS works like a stack. When the app starts you call pushScene to display your main scene. Normally, you then make additional pushScene calls to add scenes to the stack on top, and then when you are done with them they are popped, typically when the user performs the 'back gesture', bringing back the previous scene. Eventually you will be back at your main scene.
The swapScene call is equivalent to calling popScene and then pushScene for a different scene. In your case you are calling popScene then swapScene, so that is the equivalent of popping two scenes from the stack and then pushing back one. It probably works because you have only one scene, but if you had more it would not work correctly.
BTW, why are you working with Mojo and not Enyo?
While this is technically correct, it is most likely not how the user would expect your app to behave. In general, when a user presses a button that opens a new scene, it is placed on the stack, as Miguel said. The user will expect to be able to go back and pop the scene off of the stack. This happens automatically, you do not need to listen for this input. You do this by calling Mojo.Controller.pushScene("sceneName");. While there are some applications where swapScene makes sense, your app can probably be conceptualized as a stack of scenes, with a logical "back" scene.
I would reccommend playing around with some existing apps to get a feel for how they behave. Also, while Miguel suggested moving to Enyo, it is worth noting that Enyo apps are not officially supposed to work on webOS 2 devices (phones), only on the touchpad. It is possible to run them on webOS 2 devices, but I do believe that they will be rejected from the app catalog.
I'm porting a windows forms program to run on Windows Phone 7.
Part of the windows program is a wizard style series of steps with Next and Prev buttons along with Save and Cancel. The screens are generates from metadata stored in a database. Some screens are optional and are only created after certain conditions are met.
My question is - how is this best implemented in WP7?
My initial idea was to use a pivot but then I read Tim Heuer's guide to Panaroma vs Pivot where he specifically states "don’t use pivot/pano for wizard-based UI".
I have a number of ideas - I could make each screen a page (not too keen on this due to back stack issues) or I could use one page with a tab control - but am up against it time wise and can't afford to waste days heading the wrong way.
Any ideas? My WP7 app is being built using MVVM via Caliburn Micro.
I could make each screen a page (not too keen on this due to back stack issues)
The Nonlinear Navigation Service may help you with the back button.
I could use one page with a tab control
I did one wizard-like app in WPF using restyled Tab control. Was a bit messy, works well though.
You need to design it first and consider a few scenarios. What happen when user clicks the back button, starts button or someone calls the user? (when app is tombstoned and user presses back button OS brings back the last page). Is the navigation very complex (decision tree)?
Make just one page with a grid with 3 grids/stack panels inside. Place them horizontally with margins 0; 480; 960. The only one internal grid can be shown at the time. You can see an example here (I made a joke for friends :P ).
I have used stack panels with composite transform.
<StackPanel Name="questionPanel" Grid.Row="0" HorizontalAlignment="Center">
<StackPanel.RenderTransform>
<CompositeTransform TranslateX="480"></CompositeTransform>
</StackPanel.RenderTransform>
with an animation
<UserControl.Resources>
<Storyboard x:Name="centerPanelIn">
<DoubleAnimation Duration="0:0:0.3" BeginTime="0:0:0.6" To="0"
Storyboard.TargetName="centerPanel"
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)">
<DoubleAnimation.EasingFunction>
<ExponentialEase Exponent="6.0" EasingMode="EaseOut"></ExponentialEase>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
When user presses the button, Completed event is added.
private void Button_Click(object sender, RoutedEventArgs e)
{
centerPanelOut.Begin();
centerPanelOut.Completed += new EventHandler(centerPanelOut_Completed);
}
This approach has an advantage, because everything is on one page and animations give the nice UX. For more complex wizard consider making you own UserControl.
My initial thought is to not do this and redesign the process. Without a greater understanding of your situation and app though, it is hard to advise appropriately.
If you're in a hurry and really must do this I'd recommend using a single page and updating the view model to create the appearance of multiple pages.
Alternatively you could use a series of pages and the Non-Linear Navigation Service.
This may have issues with how it integrates with the rest of the application though.
Have you tried using grids and toggling their visibility using a back and next button on the app bar? The back button would then act as a cancel button.