Получить ориентацию телефона, но исправить ориентацию экрана в портретном
Я хочу получить ориентацию телефона, но сохранить ориентацию экрана в портретном. Поэтому, независимо от того, поворачивает ли пользователь телефон в альбомную или портретную ориентацию, вид остается неизменным, но я могу определить, установлен ли он в альбомную или портретную ориентацию.
Установка активности на Android:screenOrientation="Portrait" исправит оба, но я не смог бы определить ориентацию телефона через
public void onConfigurationChanged(Configuration newConfig) {
switch (newConfig.orientation) {
case Configuration.ORIENTATION_PORTRAIT:
Toast.makeText(this, "Portrait", Toast.LENGTH_SHORT).show();
break;
case Configuration.ORIENTATION_LANDSCAPE:
Toast.makeText(this, "Landscape", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
Кто-нибудь знает, как это исправить?
6 ответов
Не могли бы вы удовлетворить ваши требования с помощью акселерометра? Если так, возможно, что-то вроде этого (непроверенного) фрагмента подойдет вашим целям.
SensorManager sensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE);
sensorManager.registerListener(new SensorEventListener() {
int orientation=-1;;
@Override
public void onSensorChanged(SensorEvent event) {
if (event.values[1]<6.5 && event.values[1]>-6.5) {
if (orientation!=1) {
Log.d("Sensor", "Landscape");
}
orientation=1;
} else {
if (orientation!=0) {
Log.d("Sensor", "Portrait");
}
orientation=0;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
}, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_GAME);
Вот универсальный класс для простого управления изменениями ориентации экрана:
public class OrientationManager extends OrientationEventListener {
public enum ScreenOrientation {
REVERSED_LANDSCAPE, LANDSCAPE, PORTRAIT, REVERSED_PORTRAIT
}
public ScreenOrientation screenOrientation;
private OrientationListener listener;
public OrientationManager(Context context, int rate, OrientationListener listener) {
super(context, rate);
setListener(listener);
}
public OrientationManager(Context context, int rate) {
super(context, rate);
}
public OrientationManager(Context context) {
super(context);
}
@Override
public void onOrientationChanged(int orientation) {
if (orientation == -1){
return;
}
ScreenOrientation newOrientation;
if (orientation >= 60 && orientation <= 140){
newOrientation = ScreenOrientation.REVERSED_LANDSCAPE;
} else if (orientation >= 140 && orientation <= 220) {
newOrientation = ScreenOrientation.REVERSED_PORTRAIT;
} else if (orientation >= 220 && orientation <= 300) {
newOrientation = ScreenOrientation.LANDSCAPE;
} else {
newOrientation = ScreenOrientation.PORTRAIT;
}
if(newOrientation != screenOrientation){
screenOrientation = newOrientation;
if(listener != null){
listener.onOrientationChange(screenOrientation);
}
}
}
public void setListener(OrientationListener listener){
this.listener = listener;
}
public ScreenOrientation getScreenOrientation(){
return screenOrientation;
}
public interface OrientationListener {
public void onOrientationChange(ScreenOrientation screenOrientation);
}
}
Это намного проще, многократно используется, и вы также можете получить ориентации REVERSE_LANDSCAPE и REVERSE_PORTRAIT.
Вы должны реализовать OrientationListener, чтобы получать уведомления только при изменении ориентации.
Не забывайте вызывать Ориентация Manager.enable(), чтобы начать отслеживание ориентации, а затем вызывать Ориентация Manager.disable() (эти два метода наследуются от класса OrientationEventListener)
ОБНОВЛЕНИЕ: пример использования
MyFragment extends Fragment implements OrientationListener {
...
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
orientationManager = new OrientationManager(getActivity(), SensorManager.SENSOR_DELAY_NORMAL, this);
orientationManager.enable();
}
@Override
public void onOrientationChange(ScreenOrientation screenOrientation) {
switch(screenOrientation){
case PORTRAIT:
case REVERSED_PORTRAIT:
MainActivityBase.getInstance().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
case REVERSED_LANDSCAPE:
MainActivityBase.getInstance().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
break;
case LANDSCAPE:
MainActivityBase.getInstance().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
}
}
}
Мне нужно решение, которое дало бы мне ориентацию только по требованию. Этот работал для меня:
public class SensorOrientationChecker {
public final String TAG = getClass().getSimpleName();
int mOrientation = 0;
private SensorEventListener mSensorEventListener;
private SensorManager mSensorManager;
private static SensorOrientationChecker mInstance;
public static SensorOrientationChecker getInstance() {
if (mInstance == null)
mInstance = new SensorOrientationChecker();
return mInstance;
}
private SensorOrientationChecker() {
mSensorEventListener = new Listener();
Context applicationContext = GlobalData.getInstance().getContext();
mSensorManager = (SensorManager) applicationContext.getSystemService(Context.SENSOR_SERVICE);
}
/**
* Call on activity onResume()
*/
public void onResume() {
mSensorManager.registerListener(mSensorEventListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
}
/**
* Call on activity onPause()
*/
public void onPause() {
mSensorManager.unregisterListener(mSensorEventListener);
}
private class Listener implements SensorEventListener {
@Override
public void onSensorChanged(SensorEvent event) {
float x = event.values[0];
float y = event.values[1];
if (x<5 && x>-5 && y > 5)
mOrientation = 0;
else if (x<-5 && y<5 && y>-5)
mOrientation = 90;
else if (x<5 && x>-5 && y<-5)
mOrientation = 180;
else if (x>5 && y<5 && y>-5)
mOrientation = 270;
//Log.e(TAG,"mOrientation="+mOrientation+" ["+event.values[0]+","+event.values[1]+","+event.values[2]+"]");
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
public int getOrientation(){
return mOrientation;
}
}
Если вы отключите изменение ориентации экрана, то, очевидно, onConfigurationChanged никогда не будет вызываться...
Я думаю, что единственный способ использовать датчик акселерометра, проверьте эту ссылку.
Это намного проще, чем писать целый новый класс:
final OrientationEventListener orientationEventListener = new OrientationEventListener( getApplicationContext() ) {
@Override
public void onOrientationChanged( final int orientation ) {
Log.i("", "orientation = " + orientation );
}
};
orientationEventListener.enable();
Чтобы попасть в это, вы хотите установить в файле манифеста в этой деятельности
android:configChanges="orientation|keyboardHidden"
Затем, когда пользователь повернет телефон, он станет общедоступным методом onConfigurationChanged(). Также удалите
android:screenOrientation="portrait"
от той же деятельности.
В случае, если кто-то ищет решение Webview/javascript для вопроса, ниже может сделать это.
Это вызовет пользовательские события "перевернуть" в окне с "дополнительными параметрами", как они есть в jquery. Он также устанавливает window.flip, аналогично window.orientation:
$(window).on('flip',function(ev,angle,orientation) {
console.log(angle,orientation);
alert(window.flip);
});
if (window.DeviceOrientationEvent) {
jQuery.flip = {
debug : false,
interval : 1000,
checked : false,
betaflat : 25,
gammaflat : 45,
orientation : 'portrait-primary',
angles : {
'portrait-primary' : 0,
'portrait-secondary' : 0,
'landscape-primary' : 90,
'landscape-secondary' : -90
},
timer : null,
check : function(ev) {
if (!this.checked) {
var trigger=false;
if (this.debug) console.log([ev.alpha,ev.beta,ev.gamma]);
if (ev.beta>this.betaflat) {
// if beta is big its portrait
if (this.debug) console.log('beta portrait pri');
if (this.orientation!='portrait-primary') {
this.orientation='portrait-primary';
trigger=true;
}
} else if (ev.beta<-this.betaflat) {
// if beta is big its portrait
if (this.debug) console.log('beta portrait sec');
if (this.orientation!='portrait-secondary') {
this.orientation='portrait-secondary';
trigger=true;
}
} else if (ev.gamma>this.gammaflat) {
// else if gamma is big its landscape
if (this.debug) console.log('gamma landscape pri');
if (this.orientation!='landscape-primary') {
this.orientation='landscape-primary';
trigger=true;
}
} else if (ev.gamma<-this.gammaflat) {
// else if gamma is big its landscape
if (this.debug) console.log('gamma landscape sec');
if (this.orientation!='landscape-secondary') {
this.orientation='landscape-secondary';
trigger=true;
}
}
if (trigger) {
if (this.debug) console.log('trigger flip');
window.flip = this.angles[this.orientation];
$(window).trigger('flip',[window.flip,this.orientation]);
this.checked=true;
}
}
}
}
$(document).ready(function() {
setInterval(function() {jQuery.flip.checked=false},jQuery.flip.interval);
$(window).on('deviceorientation',function(ev) { jQuery.flip.check(ev.originalEvent) });
});
} else {
if (this.debug) console.log('DeviceOrientationEvent not supported');
}
Jquery на самом деле не нужен. В любом случае это было необходимо.