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
Related
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.
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.
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.
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.
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.