1

Я читал раздел «Выбор» в руководстве по дизайну материалов (https://material.io/guidelines/patterns/selection.html), и одним эффектом, который я хотел добавить в свое приложение, была круговая анимация раскрытия при переключении между приложением бар и ActionMode? Другая панель инструментов?Material Design: Добавить круговую анимацию при переключении между панелями инструментов

Вот пример из принципов: https://storage.googleapis.com/material-design/publish/material_v_10/assets/0Bwp7jtSjaW36RGF3eUFsRkdqU1U/patterns_selection_item_controlling_desktop_click.webm

я не нашел каких-либо объяснений о том, как сделать это. Я даже не знаю, используют ли они ActionMode или что-то еще ...

Есть ли кто-нибудь, кто мог бы дать мне хорошее направление?

редактировать: minSdk 21

редактировать 2: взгляд на строку состояния, которая также изменяет себя ...

Благодаря Франсуа

ответ

2

ОК, наконец, я нашел решение.

Это не очень хороший ... но у меня нет другой идеи использовать что-то еще, поэтому, если у вас есть еще несколько советов, чтобы поделиться ... вы можете!

Вот конечный результат и код ниже:

Step 0

Step 1

Step 2

Образец проекта на GitHub

https://github.com/fbourlieux/android-material-circular_reveal_animation

Цель & идея

Переключение с панели инструментов на другой с помощью «гладкой» круговой показал анимации. Для этой анимации необходимо обновить панель приложений и строку состояния.

Для этого сначала необходимо принудительно отобразить это содержимое в строке состояния, используя свойство android:fitsSystemWindows=false на основном контейнере макета и <item name="android:windowTranslucentStatus">true</item> в теме приложения. Исходя из этого, мы создадим не только Toolbar, но и представление, которое будет отображаться под статусомBar, juste, чтобы нарисовать хороший фон во время анимации. Вот точка, которую мне не нравится в моем примере, но я не нашел другого решения.

Давайте посмотрим код

styles.xml

<!-- Base application theme. --> 
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> 
    <!-- Customize your theme here. --> 
    <item name="colorPrimary">@color/colorPrimary</item> 
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item> 
    <item name="colorAccent">@color/colorAccent</item> 
    <item name="android:windowTranslucentStatus">true</item> 
</style> 

мы просто добавили android:windowTranslucentStatus собственность.

app_bar_main.xml

<android.support.design.widget.CoordinatorLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:fitsSystemWindows="false" 
    tools:context="sample.test.fbo.circularrevealanimation.MainActivity"> 

    <android.support.design.widget.AppBarLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:theme="@style/AppTheme.AppBarOverlay"> 

     <!-- used to force the two toolbars to display above each other --> 
     <RelativeLayout 
      android:layout_width="match_parent" 
      android:layout_height="match_parent"> 

      <!-- initial toolbar layout with the status bar 
      and the original toolbar. That layout need to have a 
      background to show the elevation even if it will never 
      be visible (because of inner component backgrounds) --> 
      <LinearLayout 
       android:layout_width="match_parent" 
       android:layout_height="wrap_content" 
       android:background="@color/colorPrimary" 
       android:elevation="4dp" 
       android:orientation="vertical"> 

       <!-- status bar background: height of 24dp 
       and initial color darker than the toolbar color --> 
       <View 
        android:layout_width="match_parent" 
        android:layout_height="24dp" 
        android:background="@color/colorPrimaryDark" /> 

       <!-- main toolbar. A very basic one.--> 
       <android.support.v7.widget.Toolbar 
        android:id="@+id/toolbar" 
        android:layout_width="match_parent" 
        android:layout_height="?attr/actionBarSize" 
        android:background="?attr/colorPrimary" 
        app:popupTheme="@style/AppTheme.PopupOverlay" /> 

      </LinearLayout> 

      <!-- reveal section layout. Here is our second toolbar 
      section which will be animated. It contains a view to 
      fake the status bar background and the second toolbar 
      to display. --> 
      <LinearLayout 
       android:id="@+id/revealedToolBar" 
       android:layout_width="match_parent" 
       android:layout_height="wrap_content" 
       android:background="@color/colorAccentDark" 
       android:elevation="4dp" 
       android:orientation="vertical" 
       android:visibility="invisible"> 

       <!-- revealed status bar. Just to change it background. --> 
       <View 
        android:id="@+id/revealBackgroundStatus" 
        android:layout_width="match_parent" 
        android:layout_height="24dp" 
        android:background="@color/colorAccentDark" /> 

       <!-- revealed toolbar. The second one with in our case 
       a simple button and text inside. --> 
       <android.support.v7.widget.Toolbar 
        android:id="@+id/toolbar2" 
        android:layout_width="match_parent" 
        android:layout_height="?attr/actionBarSize" 
        android:background="@color/colorAccent" 
        app:popupTheme="@style/AppTheme.PopupOverlay"> 

        <!-- a click on that button will trigger 
         the animation close event --> 
        <ImageButton 
         android:id="@+id/toolbar_arrow" 
         android:layout_width="48dp" 
         android:layout_height="48dp" 
         android:background="@android:color/transparent" 
         android:src="@drawable/arrow_left" /> 

        <TextView 
         android:layout_width="match_parent" 
         android:layout_height="match_parent" 
         android:layout_marginLeft="24dp" 
         android:fontFamily="sans-serif-regular" 
         android:gravity="center_vertical" 
         android:text="Foo Bar Baz" 
         android:textColor="@android:color/white" 
         android:textSize="18sp" 
         android:textStyle="bold" 
         tools:text="Foo Bar Baz" /> 
       </android.support.v7.widget.Toolbar> 
      </LinearLayout> 

     </RelativeLayout> 
    </android.support.design.widget.AppBarLayout> 

    <!-- content_main just contains a ToggleButton to trigger 
    the animation--> 
    <include layout="@layout/content_main" /> 

</android.support.design.widget.CoordinatorLayout> 

Создать 2 перекрывается макет, содержащий окно, чтобы нарисовать строку состояния и вид рисовать панель инструментов. По умолчанию макет для анимации устанавливается невидимым.

MainActivity.java

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, View.OnClickListener { 

    private final static int ANIMATION_DURATION = 400; 
    private ToggleButton mActionButton; 
    private View mRevealedToolBar; 
    private ImageButton mArrowButton; 
    private boolean mIsHidden = true; 

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

     // main toolbar 
     final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(toolbar); 

     final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
     final ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); 
     drawer.setDrawerListener(toggle); 
     toggle.syncState(); 

     final NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); 
     navigationView.setNavigationItemSelectedListener(this); 

     // trigger circular reveal animation 
     mActionButton = (ToggleButton) findViewById(R.id.actionButton); 
     mActionButton.setOnClickListener(this); 

     // toolbar view to reveal. Inivisible by default 
     mRevealedToolBar = findViewById(R.id.revealedToolBar); 
     mRevealedToolBar.setVisibility(View.INVISIBLE); 

     // button in revealed toolbar to dismiss it 
     mArrowButton = (ImageButton) findViewById(R.id.toolbar_arrow); 
     mArrowButton.setOnClickListener(this); 
    } 

    @Override 
    public void onBackPressed() { 
     final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
     if (drawer.isDrawerOpen(GravityCompat.START)) { 
      drawer.closeDrawer(GravityCompat.START); 
     } else { 
      super.onBackPressed(); 
     } 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     getMenuInflater().inflate(R.menu.main, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(final MenuItem item) { 
     if (item.getItemId() == R.id.action_settings) { 
      return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 

    @SuppressWarnings("StatementWithEmptyBody") 
    @Override 
    public boolean onNavigationItemSelected(final MenuItem item) { 
     DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
     drawer.closeDrawer(GravityCompat.START); 
     return true; 
    } 



    @Override 
    public void onClick(final View view) { 

     if (view == mActionButton || view == mArrowButton) { 


      // compute started X and Y co-ordinates for the animation + radius 
      int x = mRevealedToolBar.getLeft(); 
      int y = mRevealedToolBar.getBottom(); 
      int startRadius = 0; 
      int endRadius = Math.max(mRevealedToolBar.getWidth(), mRevealedToolBar.getHeight()); 
      int reverseStartRadius = endRadius; 
      int reverseEndRadius = startRadius; 



      if (mIsHidden) { 

       // show secondary toolbar 
       // performing circular reveal when icon will be tapped 
       Animator animator = ViewAnimationUtils.createCircularReveal(mRevealedToolBar, x, y, startRadius, endRadius); 
       animator.setInterpolator(new AccelerateDecelerateInterpolator()); 
       animator.setDuration(ANIMATION_DURATION); 

       mRevealedToolBar.setVisibility(View.VISIBLE); 
       animator.start(); 
       mIsHidden = false; 


      } else { 

       // dismiss secondary toolbar 
       // performing circular reveal for reverse animation 
       Animator animate = ViewAnimationUtils.createCircularReveal(mRevealedToolBar, x, y, reverseStartRadius, reverseEndRadius); 
       animate.setInterpolator(new AccelerateDecelerateInterpolator()); 
       animate.setDuration(ANIMATION_DURATION); 

       // to hide layout on animation end 
       animate.addListener(new AnimatorListenerAdapter() { 
        @Override 
        public void onAnimationEnd(Animator animation) { 
         super.onAnimationEnd(animation); 
         mRevealedToolBar.setVisibility(View.INVISIBLE); 
         mIsHidden = true; 
        } 
       }); 

       mRevealedToolBar.setVisibility(View.VISIBLE); 
       animate.start(); 
      } 
     } 
    } 
} 

Так в MainActivity, после того, как слушать событие OnClick моего ToggleButton, я запустить анимацию моей второй панели инструментов группы (просмотр состояния + панель инструментов) с помощью ViewAnimationUtils.createCircularReveal методов. Первый аргумент - это вид анимации, за которым следует начальная координата анимации и последующий радиус.

В методе onClick я также запускаю анимацию reverse, когда я нажимаю стрелку или второй раз на своем ToggleButton.

И, наконец, это довольно простое решение, даже если нам нужно подделать фон состояния.

Надеюсь, что мое решение может помочь кому-то.

Франсуа

Полезные ссылки:

0

Вы можете использовать пользовательские пульсация библиотеки для такой анимации. Он может быть найден here.

Тогда, чтобы иметь тот же эффект, ваша панель инструментов будет находиться в rippleview, как указано в инструкциях пользовательской библиотеки. Вам нужно иметь координаты, из которых должен начинаться эффект пульсации, для вашего случая эта координата является центром кнопки плавающего действия с символом плюс. Затем, при выборе элемента, запустите эту волну пульсации и затухайте в плавающей кнопке действия, вы получите тот же эффект.

Некоторые аналогичные примеры можно увидеть на вышеупомянутой странице библиотеки.

Надеюсь, это поможет!