I want my gluon application to be able to change orientation from Landscape to portrait in run time. I have check the Gluon Charmdown SDK, It seem that it have only getOrientation and don't have an option to set an orientation in runtime. I don't want to set fixed orientation in Manifest
问题:
回答1:
Charm Down has an OrientationService, but as you have mentioned, it is "read only", it just listens to orientation changes and gives you the current orientation at any time. But so far you can set the orientation programatically.
To include this feature there are two options: clone Charm Down, modify the Orientation Service, build and use your custom build, or directly create a new service, like ExtendedOrientationService
, that you can include in your project directly.
Assuming the latter, this is a very basic implementation of a service that allows setting the orientation programmatically:
ExtendedOrientationService.java
package com.gluonhq.charm.down.plugins;
import javafx.geometry.Orientation;
public interface ExtendedOrientationService {
void coerceOrientation(Orientation orientation);
void releaseOrientation();
}
ExtendedOrientationServiceFactory.java
package com.gluonhq.charm.down.plugins;
import com.gluonhq.charm.down.DefaultServiceFactory;
public class ExtendedOrientationServiceFactory extends DefaultServiceFactory<ExtendedOrientationService> {
public ExtendedOrientationServiceFactory() {
super(ExtendedOrientationService.class);
}
}
For Android:
AndroidExtendedOrientationService.java
package com.gluonhq.charm.down.plugins.android;
import android.content.pm.ActivityInfo;
import com.gluonhq.charm.down.plugins.ExtendedOrientationService;
import javafx.geometry.Orientation;
import javafxports.android.FXActivity;
public class AndroidExtendedOrientationService implements ExtendedOrientationService {
private final FXActivity instance = FXActivity.getInstance();
@Override
public void coerceOrientation(Orientation orientation) {
if (orientation.equals(Orientation.HORIZONTAL)) {
instance.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else if (orientation.equals(Orientation.VERTICAL)) {
instance.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
instance.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
}
@Override
public void releaseOrientation() {
instance.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
}
On iOS:
ExtendedOrientation.h
#import <UIKit/UIKit.h>
#include "jni.h"
@interface ExtendedOrientation : UIViewController {}
@property (nonatomic, assign) BOOL shouldAutoRotate;
- (void) setOrientation:(NSString *)orientation;
- (void) release;
@end
ExtendedOrientation.m
#include "ExtendedOrientation.h"
extern JNIEnv *jEnv;
#define GET_MAIN_JENV \
if (jEnv == NULL) NSLog(@"ERROR: Java has been detached already, but someone is still trying to use it at %s:%s:%d\n", __FUNCTION__, __FILE__, __LINE__);\
JNIEnv *env = jEnv;
JNIEXPORT jint JNICALL
JNI_OnLoad_ExtendedOrientation(JavaVM *vm, void *reserved)
{
#ifdef JNI_VERSION_1_8
//min. returned JNI_VERSION required by JDK8 for builtin libraries
JNIEnv *env;
if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_8) != JNI_OK) {
return JNI_VERSION_1_4;
}
return JNI_VERSION_1_8;
#else
return JNI_VERSION_1_4;
#endif
}
static int ExtendedOrientationInited = 0;
// ExtendedOrientation
ExtendedOrientation *_extendedOrientation;
JNIEXPORT void JNICALL Java_com_gluonhq_charm_down_plugins_ios_IOSExtendedOrientationService_initOrientation
(JNIEnv *env, jclass jClass)
{
if (ExtendedOrientationInited)
{
return;
}
ExtendedOrientationInited = 1;
_extendedOrientation = [[ExtendedOrientation alloc] init];
}
JNIEXPORT void JNICALL Java_com_gluonhq_charm_down_plugins_ios_IOSExtendedOrientationService_setOrientation
(JNIEnv *env, jclass jClass, jstring jOrientation)
{
const jchar *charsOrientation = (*env)->GetStringChars(env, jOrientation, NULL);
NSString *orientation = [NSString stringWithCharacters:(UniChar *)charsOrientation length:(*env)->GetStringLength(env, jOrientation)];
(*env)->ReleaseStringChars(env, jOrientation, charsOrientation);
[_extendedOrientation setOrientation:orientation];
}
JNIEXPORT void JNICALL Java_com_gluonhq_charm_down_plugins_ios_IOSExtendedOrientationService_release
(JNIEnv *env, jclass jClass)
{
[_extendedOrientation release];
}
@implementation ExtendedOrientation
-(void) setOrientation:(NSString*)orientation
{
_shouldAutoRotate = YES;
NSLog(@"Set orientation: %@", orientation);
if ([orientation isEqualToString:@"HORIZONTAL"])
{
[[UIDevice currentDevice] setValue:[NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft] forKey:@"orientation"];
} else
{
[[UIDevice currentDevice] setValue:[NSNumber numberWithInt:UIInterfaceOrientationPortrait] forKey:@"orientation"];
}
}
- (void) release
{
_shouldAutoRotate = NO;
}
- (BOOL)shouldAutorotate
{
return _shouldAutoRotate;
}
@end
IOSExtendedOrientationService.java
package com.gluonhq.charm.down.plugins.ios;
import com.gluonhq.charm.down.plugins.ExtendedOrientationService;
import javafx.geometry.Orientation;
public class IOSExtendedOrientationService implements ExtendedOrientationService {
static {
System.loadLibrary("ExtendedOrientation");
initOrientation();
}
@Override
public void coerceOrientation(Orientation orientation) {
setOrientation(orientation.toString());
}
@Override
public void releaseOrientation() {
release();
}
// native
private static native void initOrientation();
private static native void setOrientation(String orientation);
private static native void release();
}
Now add the ios-gradle.build
file from this sample.
Finally we need to build and include the native library:
build.gradle
apply from: 'ios-build.gradle'
task xcodebuild {
doLast {
xcodebuildIOS("$project.buildDir","$project.projectDir", "ExtendedOrientation")
}
}
task installNativeLib (type:Copy, dependsOn: xcodebuild) {
from("$project.buildDir/native")
into("src/ios/jniLibs")
include("*.a")
}
You can build and add the library to the project with:
./gradlew installNativeLib
SAMPLE
This snippet shows how to use this service: If the orientation is vertical it will force horizontal orientation, else it will release the orientation:
Services.get(ExtendedOrientationService.class).ifPresent(o -> {
Orientation orientation = Services.get(OrientationService.class)
.flatMap(OrientationService::getOrientation)
.orElse(Orientation.HORIZONTAL);
if (orientation == Orientation.VERTICAL) {
o.coerceOrientation(Orientation.HORIZONTAL);
} else {
o.releaseOrientation();
}
});