Jak obracać widoki przy zmianie orientacji bez odtwarzania układu?

To pytanie zostało już zadane tutaj ale jego odpowiedź jest błędna. Chciałbym obrócić niektóre widoki na zmianę orientacji ekranu, ale chcę zachować układ bez zmian. Należy je obracać o 90, 180, 270 lub 360 stopni zgodnie z aktualną orientacją (SCREEN_ORIENTATION_LANDSCAPE, SCREEN_ORIENTATION_PORTRAIT, SCREEN_ORIENTATION_REVERSE_LANDSCAPE, SCREEN_ORIENTATION_REVERSE_PORTRAIT).

Oto, co chcę osiągnąć:

LayoutExample

Odpowiedź w linku, o którym wspomniałem, stwierdzała, że powinienem stworzyć nowy inny układ w layout-land. Najwyraźniej nie tego chcę. Nie chcę odtwarzać aktywności ani zmieniać orientacji układu. Chcę tylko obrócić niektóre widoki i zachować inne widoki bez zmian przy zmianie orientacji.

Istnieje ogromna różnica między obracaniem konkretnych widoków a zmienianiem lub odtwarzaniem całego układu (oba przy zmianie orientacji).

Używając odpowiedzi w tym linku , będę mógł uzyskać bieżącą orientację ekranu z tą metodą:

public static int getScreenOrientation(Context context) {
    WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    int rotation = windowManager.getDefaultDisplay().getRotation();
    DisplayMetrics dm = new DisplayMetrics();
    windowManager.getDefaultDisplay().getMetrics(dm);
    int width = dm.widthPixels;
    int height = dm.heightPixels;
    int orientation;
    // if the device's natural orientation is portrait:
    if ((rotation == Surface.ROTATION_0
            || rotation == Surface.ROTATION_180) && height > width ||
            (rotation == Surface.ROTATION_90
                    || rotation == Surface.ROTATION_270) && width > height) {
        switch (rotation) {
            case Surface.ROTATION_0:
                orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
                break;
            case Surface.ROTATION_90:
                orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
                break;
            case Surface.ROTATION_180:
                orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
                break;
            case Surface.ROTATION_270:
                orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
                break;
            default:
                Log.e("ScreenOrientation", "Unknown screen orientation. Defaulting to " + "portrait.");
                orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
                break;
        }
    }
    // if the device's natural orientation is landscape or if the device
    // is square:
    else {
        switch (rotation) {
            case Surface.ROTATION_0:
                orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
                break;
            case Surface.ROTATION_90:
                orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
                break;
            case Surface.ROTATION_180:
                orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
                break;
            case Surface.ROTATION_270:
                orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
                break;
            default:
                Log.e("ScreenOrientation", "Unknown screen orientation. Defaulting to " + "landscape.");
                orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
                break;
        }
    }

    return orientation;
}

W sprawie zmiany orientacji, chciałbym zrobić coś prostego jak to:

RotateAnimation rotateAnimation = new RotateAnimation(0, getScreenOrientation(getContext()));
rotateAnimation.setDuration(2000);

for (int i = 0; i < 63; i++) {
    Button button = (Button) rootView.findViewById(i);
    button.startAnimation(rotateAnimation);
}

Innym sposobem wyrażenia mojego pytania byłoby " czy jest jakiś sposób, aby wykryć zmianę orientacji w metodzie onConfigurationChanged() bez zmiany układu?". Problem polega na tym, że nie będzie w stanie wykryć żadnej zmiany orientacji, jeśli już wyłączę zmianę orientacji układu.

Ktoś wie jak to się robi? Mogłem całkowicie przejść przez złe kroki i myślę, że będę musiał aby użyć czujnika akcelerometru lub czegoś podobnego, aby osiągnąć to, co chcę, więc proszę mnie poprowadzić.
Author: Community, 2016-01-22

2 answers

Spróbuj użyć OrientationEventListener. Nie musisz używać onConfigurationChanged i android:configChanges="orientation|keyboardHidden|screenSize".

musisz ustawić android:screenOrientation="portrait" dla aktywności w AndroidManifest.xml. Oto moje rozwiązanie z OrientationEventListener:

public class MyActivity extends Activity{

private ImageButton menuButton;

private Animation toLandAnim, toPortAnim;
private OrientationListener orientationListener;

@Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.layout_image_ruler);

    menuButton=(ImageButton)findViewById(R.id.menu_button);
    toLandAnim= AnimationUtils.loadAnimation(this, R.anim.menubutton_to_landscape);
    toPortAnim= AnimationUtils.loadAnimation(this, R.anim.menubutton_to_portrait);

    orientationListener = new OrientationListener(this);
}

@Override protected void onStart() {
    orientationListener.enable();
    super.onStart();
}

@Override protected void onStop() {
    orientationListener.disable();
    super.onStop();
}

private class OrientationListener extends OrientationEventListener{
    final int ROTATION_O    = 1;
    final int ROTATION_90   = 2;
    final int ROTATION_180  = 3;
    final int ROTATION_270  = 4;

    private int rotation = 0;
    public OrientationListener(Context context) { super(context); }

    @Override public void onOrientationChanged(int orientation) {
        if( (orientation < 35 || orientation > 325) && rotation!= ROTATION_O){ // PORTRAIT
            rotation = ROTATION_O;
            menuButton.startAnimation(toPortAnim);
        }
        else if( orientation > 145 && orientation < 215 && rotation!=ROTATION_180){ // REVERSE PORTRAIT
            rotation = ROTATION_180;
            menuButton.startAnimation(toPortAnim);
        }
        else if(orientation > 55 && orientation < 125 && rotation!=ROTATION_270){ // REVERSE LANDSCAPE
            rotation = ROTATION_270;
            menuButton.startAnimation(toLandAnim);
        }
        else if(orientation > 235 && orientation < 305 && rotation!=ROTATION_90){ //LANDSCAPE
            rotation = ROTATION_90;
            menuButton.startAnimation(toLandAnim);
        }
    }
}
}

Zapobiega to również zbyt częstym rotacjom, gdy orientation wynosi około 45, 135... itd. Mam nadzieję, że to pomoże.

 16
Author: mirekkomis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-24 10:26:14

Podstawy są o wiele łatwiejsze. Spójrz na Obsługa zmian środowiska wykonawczego .

Po pierwsze, przez ustawienie

android:configChanges="orientation|keyboardHidden|screenSize"

W swoim manifeście na znaczniku aktywności możesz samodzielnie poradzić sobie ze zmianą orientacji. (orientation powinno wystarczyć, ale czasami są problemy, w których zdarzenie nie wystrzeliwuje tylko z tym.)

Następnie pomiń onCreate i zamiast onConfigurationChanged zostanie wywołany. Zastąp tę metodę i zastosuj zmiany układu tutaj. Czy zmienisz swój orientacja linearLayouts tutaj lub własny układ obsługi widoków dla różnych ekranów zależy od Ciebie i zależy od twojej implementacji.

Animowanie będzie nieco trudniejsze, jeśli jest w ogóle możliwe. Szybkie wyszukiwanie mówi to nie jest .

Update dla komentarza "chcę tylko obracać niektóre widoki zamiast obracać układ"

W teorii istnieje możliwość stworzenia własnego układu i obsługi rysunku dziecka widoki. Po prostu próbowałem, ale nie mogłem uzyskać żadnych rezultatów w odpowiednim czasie, ale co trzeba zrobić: {]}

  • zachowaj Ostatnie zmierzone wartości użyj znaczników w widoku lub podobnych podejściach, aby zachować ostatnie pomiary i układy, aby po zmianie orientacji można było odróżnić
  • waiting orientation change : trigger obrócony rysunek - obraca obszar roboczy, układa widoki z poprzednimi wymiarami i rysuje potomka widoki, gdzie by były przed i
  • Uruchom animację Interpoluj od last do new wartości, obracając obszar roboczy od ostatniego do nowego układu
Tak bym to zrobił.
 1
Author: David Medenjak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:23