FloatingActionButton

Na stronie Android material design principles, jeden z przykładów pokazuje bajkę rozszerzającą się na nowy Pełny ekran. (Pod "Pełny Ekran")

Http://www.google.com/design/spec/components/buttons-floating-action-button.html#buttons-floating-action-button-transitions

Próbowałem zaimplementować ten sam efekt w mojej aplikacji, ale z niewielkim sukcesem.
Udało mi się stworzyć FAB, który rozszerza się do widoku, używając tego kodu jako odniesienia: https://gist.github.com/chris95x8/882b5c5d0aa2096236ba .

Zadziałało, ale zastanawiałem się, czy mogę zastosować ten sam efekt do przejścia aktywności. Próbowałem go szukać i bawić się nim sam, ale nie mogłem znaleźć niczego, co mogłoby zadziałać.

Wiem, że mógłbym sprawić, by bajka rozwinęła się w Fragment , a nie zupełnie nową aktywność, ale nie jestem pewien, czy tak się robi i czy jest to optymalne, czy nie.

I tak moje pytanie brzmi, czy jest sposób na zaimplementowanie rozszerzającego się efektu ujawnienia jako przejścia aktywności, czy ma on po prostu ujawnić nowy fragment?

Author: Asaf, 2015-07-25

3 answers

Rozwijam aplikację, która rozszerza FloatingActionButton do nowego Activity. Nie jestem pewien, czy podoba Ci się moja realizacja, ale proszę zobaczyć zdjęcia na początku:

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

Więc pierwsze zdjęcie pokazuje MainActivity, a ostatnie pokazuje SecondActivity, które jest "rozszerzone" z FAB.

Chcę wspomnieć, że nie jestem rozszerzenie bajka na nowąActivity, ale mogę pozwolić użytkownikowi poczuć, że nowa strona jest rozszerzona z tego bajka , I myślę, że to wystarczy zarówno dla programistów, jak i użytkowników.

Oto implementacja:

Przygotowanie:

  1. A FloatingActionButton oczywiście,
  2. wizyta https://github.com/kyze8439690/RevealLayout i zaimportuj tę bibliotekę do swojego projektu. Służy do odtwarzania animacji reveal. Posiada własny BakedBezierInterpolator do sterowania animacją i zrób to materiałowo-stylizowane.

Kroki:

  1. Utwórz activity_main.xml jak ten:

    <FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <!--Your main content here-->
    
        <RevealLayout
            android:id="@+id/reveal_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="invisible">
    
            <View
                android:id="@+id/reveal_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:visibility="invisible"/>
    
        </RevealLayout>
    
    </FrameLayout>
    
  2. Znajdź Odsłony:

    mRevealLayout = (RevealLayout) findViewById(R.id.reveal_layout);
    mRevealView = findViewById(R.id.reveal_view);
    
  3. Rozwiń gdy użytkownik kliknie FAB:

    mFab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mFab.setClickable(false); // Avoid naughty guys clicking FAB again and again...
            int[] location = new int[2];
            mFab.getLocationOnScreen(location);
            location[0] += mFab.getWidth() / 2;
            location[1] += mFab.getHeight() / 2;
    
            final Intent intent = new Intent(MainActivity.this, SecondActivity.class);
    
            mRevealView.setVisibility(View.VISIBLE);
            mRevealLayout.setVisibility(View.VISIBLE);
    
            mRevealLayout.show(location[0], location[1]); // Expand from center of FAB. Actually, it just plays reveal animation.
            mFab.postDelayed(new Runnable() {
                @Override
                public void run() {
                    startActivity(intent);
                    /**
                     * Without using R.anim.hold, the screen will flash because of transition
                     * of Activities.
                     */
                    overridePendingTransition(0, R.anim.hold);
                }
            }, 600); // 600 is default duration of reveal animation in RevealLayout
            mFab.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mFab.setClickable(true);
                    mRevealLayout.setVisibility(View.INVISIBLE);
                    mViewToReveal.setVisibility(View.INVISIBLE);
                }
            }, 960); // Or some numbers larger than 600.
        }
    });
    

    A tu trzymaj.xml w res / anim:

    <set
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:shareInterpolator="false">
    
        <translate
            android:duration="960" <!-- Enough-large time is OK -->
            android:fromXDelta="0%"
            android:fromYDelta="0%"
            android:toXDelta="0%"
            android:toYDelta="0%"/>
    
    </set>
    
To wszystko.

Ulepszenia:

  1. RevealLayout ma błąd (odtwarza prostokątną zamiast okrągłej animacji) dla urządzeń pod API 17 (Android 4.2), można dodać te linie w konstruktorze it:

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }
    
  2. Jeśli twoja SecondActivity zawiera skomplikowaną zawartość, prosta View używana jako reveal_view w układzie.xml to za mało / perfect. Możesz dołączyć drugi układ wewnątrz RevealLayout reveal_layout. Wydaje się to marnotrawne i trudne do kontrolowania, jeśli drugi układ nie będzie wyglądał tak samo za każdym razem. Ale dla mnie tak. Możesz więc wprowadzić inne ulepszenia, jeśli powinieneś.

  3. Jeśli chcesz wdrożyć całkowicie ta sama animacja pokazana w Material Design Guide, możesz ustawić layout_height RevealLayout na konkretną liczbę zamiast match_parent. Po zakończeniu rozwijania animacji (lub jakiś czas po odtworzeniu animacji, co powinno sprawić, że cały proces animacji będzie płynny), można animować translacje. Ważne jest to, że po prostu oszukuj użytkowników wizualnie, kontrolując czas trwania animacji.

W końcu to moje własne doświadczenie/próba i jestem początkujący w tworzenie aplikacji na Androida. jeśli są jakieś błędy / dalsze ulepszenia, proszę zostawić komentarze / edytuj moją odpowiedź . Dziękuję.

 28
Author: ywwynm,
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-04-14 16:39:33

Zrobiłem niestandardowe działanie, na podstawie tego pytania Circular reveal transition for new activity , które obsługuje CircularRevealAnimation i jego odwrotny efekt po zakończeniu aktywności:

public class RevealActivity extends AppCompatActivity {

private View revealView;

public static final String REVEAL_X="REVEAL_X";
public static final String REVEAL_Y="REVEAL_Y";

public void showRevealEffect(Bundle savedInstanceState, final View rootView) {

    revealView=rootView;

    if (savedInstanceState == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        rootView.setVisibility(View.INVISIBLE);

        ViewTreeObserver viewTreeObserver = rootView.getViewTreeObserver();

        if(viewTreeObserver.isAlive()) {
            viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {

                    circularRevealActivity(rootView);

                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                        rootView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    } else {
                        rootView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    }

                }
            });
        }

    }
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void circularRevealActivity(View rootView) {

    int cx = getIntent().getIntExtra(REVEAL_X, 0);
    int cy = getIntent().getIntExtra(REVEAL_Y, 0);

    float finalRadius = Math.max(rootView.getWidth(), rootView.getHeight());

    // create the animator for this view (the start radius is zero)
    Animator circularReveal = ViewAnimationUtils.createCircularReveal(rootView, cx, cy, 0, finalRadius);
    circularReveal.setDuration(400);

    // make the view visible and start the animation
    rootView.setVisibility(View.VISIBLE);
    circularReveal.start();
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

switch (item.getItemId()) {

case android.R.id.home: onBackPressed();break;
return super.onOptionsItemSelected(item);

}    

}

@Override
public void onBackPressed() {
    destroyActivity(revealView);
}

private void destroyActivity(View rootView) {
    if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP)
        destroyCircularRevealActivity(rootView);
    else
        finish();
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void destroyCircularRevealActivity(final View rootView) {
    int cx = getIntent().getIntExtra(REVEAL_X, 0);
    int cy = getIntent().getIntExtra(REVEAL_Y, 0);

    float finalRadius = Math.max(rootView.getWidth(), rootView.getHeight());

    // create the animator for this view (the start radius is zero)
    Animator circularReveal = ViewAnimationUtils.createCircularReveal(rootView, cx, cy, finalRadius, 0);
    circularReveal.setDuration(400);

    circularReveal.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animator) {

        }

        @Override
        public void onAnimationEnd(Animator animator) {
            rootView.setVisibility(View.INVISIBLE);
            finishAfterTransition();
        }

        @Override
        public void onAnimationCancel(Animator animator) {

        }

        @Override
        public void onAnimationRepeat(Animator animator) {

        }
    });

    // make the view visible and start the animation
    rootView.setVisibility(View.VISIBLE);
    circularReveal.start();
}
}

Możesz to rozszerzyć o własną aktywność i wywołać w onCreate metodę 'showRevealEffect' w następujący sposób:

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

    //your code

    View root= findViewById(R.id.your_root_id);
    showRevealEffect(savedInstanceState, root);

}

Musisz również użyć przezroczystego motywu, takiego jak ten:

<style name="Theme.Transparent" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="colorControlNormal">@android:color/white</item>
</style>

W końcu, aby uruchomić tę aktywność należy przejść przez dodatkowe współrzędne miejsca rozpoczęcia animacji:

int[] location = new int[2];

    fab.getLocationOnScreen(location);

    Intent intent = new Intent(this, YourRevealActivity.class);

    intent.putExtra(SearchActivity.REVEAL_X, location[0]);
    intent.putExtra(SearchActivity.REVEAL_Y, location[1]);

    startActivity(intent);
 6
Author: Bronx,
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:10:37

Możesz użyć tej lib [ https://github.com/sergiocasero/RevealFAB][1]

[1]: https://github.com/sergiocasero/RevealFAB 3rd party jest łatwy i prosty w użyciu

Dodaj do swojego layoutu

<RelativeLayout...>

    <android.support.design.widget.CoordinatorLayout...>
        <!-- YOUR CONTENT -->
    </android.support.design.widget.CoordinatorLayout>

    <com.sergiocasero.revealfab.RevealFAB
        android:id="@+id/reveal_fab"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:fab_color="@color/colorAccent"
        app:fab_icon="@drawable/ic_add_white_24dp"
        app:reveal_color="@color/colorAccent" />
</RelativeLayout>

Ważne: ten komponent przekracza zawartość. Możesz użyć Coordinator, LinearLayout... lub inny układ względny jeśli chcesz:)

Jak widać, masz 3 niestandardowe atrybuty do dostosowywania kolorów i ikony

Ustawianie informacji o intencja:

revealFAB = (RevealFAB) findViewById(R.id.reveal_fab);
Intent intent = new Intent(MainActivity.this, DetailActivity.class);
revealFAB.setIntent(intent);

revealFAB.setOnClickListener(new RevealFAB.OnClickListener() {
    @Override
    public void onClick(RevealFAB button, View v) {
        button.startActivityWithAnimation();
    }
});

Nie zapomnij o metodzie call onResume ()!

@Override
protected void onResume() {
    super.onResume();
    revealFAB.onResume();
}
 -1
Author: Samuel Moshie,
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-06-23 12:31:52