Как имитировать стиль поднятой кнопки "Material-design", даже для pre-Lollipop (минус специальные эффекты)?

Google показал несколько хороших способов, что кнопки отображаются на Lollipop здесь.

Я говорю о поднятых и плоских кнопках.

Как я могу имитировать их в версиях до Lollipop, кроме специальных эффектов (рябь и т.д.)?

Я говорю о this и this.

Конечно, на Lollipop и выше, я хотел бы использовать специальные эффекты.

Я знаю, что уже есть несколько (и даже много) сообщений об этом, но я не вижу никаких попыток имитировать его полностью.

Ответ 1

Обновленный ответ: Рекомендуется, чтобы вы полагались на библиотеку Google appcompat для поддержки стилей дизайна материалов для вашего приложения. Кажется, что он больше не обращает внимание на поднятую кнопку (вместо этого использует плоские кнопки), но все же адекватно поддерживает кнопку, соответствующую стилю дизайна материала. Это моя рекомендация, что вы идете с этим подходом.

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

Чтобы настроить библиотеку appcompat с официальным официальным обращением к материалам Google:

compile "com.android.support:appcompat-v7:+"

Затем вам нужно настроить тему приложения в файле styles.xml.

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

И в вашем AndroidManifest.xml убедитесь, что тема выше установлена ​​правильно:

<application
    android:allowBackup="false"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="false"
    android:theme="@style/AppTheme">

После вышеуказанной настройки убедитесь, что все ваши Activity простираются от AppCompatActivity, и оттуда все ваши Button будут завышены с помощью стиля Material Design.

Если вы используете пользовательскую реализацию Button в своем проекте, убедитесь, что вместо расширения Button продолжите AppCompatButton. Это относится к большинству ваших пользовательских View s: AppCompatTextView, AppCompatEditText и т.д.

Как это работает? Все ваши xml-макеты Android раздуты, используя что-то, называемое LayoutInflater. LayoutInflater предоставляется Activity и имеет возможность предоставления LayoutInflaterFactory, предоставляемого ему, чтобы вы могли переопределять стандартные реализации стандартных виджетов Android, таких как Button и TextView. Когда вы используете AppCompatActivity, он предоставляет вам нестандартный LayoutInflater, который раздувает специальные экземпляры виджетов, которые поддерживают Material Design!

-------------------------------------------- ----- Старый ответ: ----------------------------------------------- -

Итак, Android дал нам CardView, чтобы воспроизвести такое поведение. Он обеспечивает просмотр с закругленными углами, который применяет тень. Вероятно, вы также захотите посмотреть на метод # setCardElevation().

Вы можете добавить библиотеку CardView в свой проект Gradle:

compile 'com.android.support:cardview-v7:+'

CardView будет использовать реализацию Lollipop, чтобы сделать это, если он доступен (поскольку тени Lollipops лучше), иначе он будет реплицировать его как можно лучше.

Вот пример:

<android.support.v7.widget.CardView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:card_view="http://schemas.android.com/apk/res-auto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        card_view:cardBackgroundColor="#ffd9d9d9"
        card_view:cardCornerRadius="2dp"
        android:layout_margin="6dp"
        card_view:cardElevation="6dp">

    <TextView android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingTop="8.5dp"
            android:paddingBottom="8.5dp"
            android:paddingLeft="12dp"
            android:paddingRight="12dp"
            android:textColor="#de000000"
            android:fontFamily="sans-serif-medium"
            android:text="NORMAL" />

</android.support.v7.widget.CardView>

Приведенный выше код работает на 5.0: CardView Button on 5.0

Вышеприведенный код работает в 4.4.4: CardView Button on 4.4.4

Похоже, что существует расхождение в шрифтах, так как в sans-serif-media имеет другой размер шрифта или не поддерживается в 4.4.4, но его можно легко устранить, включив последнюю версию Roboto и переопределение шрифтов в TextViews.

В документации к материалу вы указываете "Повышенная кнопка". CardView - это то, как мы делаем что-то "повышенное".

Ответ 2

Добавьте в приложение совместимую библиотеку. (Самая последняя версия может быть найдена здесь.) Сделайте это, добавив зависимость в файл build.gradle:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'
}

Объявите свою apptheme в файле styles.xml, расположенном в каталоге значений:

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/theme_primary</item>
        <item name="colorAccent">@color/theme_accent_1</item>
        <item name="actionMenuTextColor">@color/theme_text</item>
    </style>
</resources>

Задайте объявленный стиль как тот, который будет использоваться для вашего приложения в файле manifest.xml:

<application
    android:icon="@drawable/ic_launcher"
    android:theme="@style/AppTheme"/>

В ваших макетах объявите поднятую кнопку следующим образом

<Button
    android:id="@+id/addButton"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:text="@string/title_add" />

Объявите стиль плоской кнопки следующим образом:

<Button
    android:id="@+id/okbutton"
    style="?android:attr/borderlessButtonStyle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@android:string/ok" />

Результат как для телефона 4.4 (телефон), так и для планшета 5.0:

Tablet with 5.0

Phone 4.4

Подробности можно найти в официальной документации: http://developer.android.com/training/material/theme.html

Ответ 3

Я получаю тот же эффект, используя

  android:background="@android:drawable/dialog_holo_light_frame"

Мой тестовый результат:

enter image description here

Ответ 4

Этот хакерский в соответствии с Yigit (google dev on cardview), но выполняет спуск.

Вы можете использовать отрицательные числа, чтобы избавиться от отступов и полей внутри CardView.

Проверено на эмуляторах api 15 nexus one и nexus 4. Это решение будет работать на pre lollipop.

<android.support.v7.widget.CardView
    android:id="@+id/elevated_button_card"
    card_view:cardElevation="2dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    card_view:cardMaxElevation="8dp"
    card_view:contentPadding="-2dp"
    android:layout_marginBottom="-2dp"
    card_view:cardCornerRadius="0dp">
    <Button
        android:id="@+id/elevated_button"
        style="?android:attr/borderlessButtonStyle"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Add New Exercise"/
</android.support.v7.widget.CardView>

код:

        final CardView cardView = (CardView) rootView.findViewById(R.id.elevated_button_card);
        final Button button = (Button) rootView.findViewById(R.id.elevated_button);
        button.setOnTouchListener(new View.OnTouchListener() {
            ObjectAnimator o1 = ObjectAnimator.ofFloat(cardView, "cardElevation", 2, 8)
                    .setDuration
                            (80);
            ObjectAnimator o2 = ObjectAnimator.ofFloat(cardView, "cardElevation", 8, 2)
                    .setDuration
                            (80);

            @Override
            public boolean onTouch(View v, MotionEvent event) {

                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        o1.start();
                        break;
                    case MotionEvent.ACTION_CANCEL:
                    case MotionEvent.ACTION_UP:
                        o2.start();
                        break;
                }
                return false;
            }
        });

Ответ 5

Я работаю над библиотекой совместимости материалов. Я написал свой собственный класс Button с материалоподобными стилями, анимированными тенями и эффектом касания. Хотя это еще не все, вы можете попробовать здесь.

Ответ 6

В дополнение к ответу @spierce7 я немного улучшил этот макет. Итак, теперь у него есть относительный макет, который устанавливает наш пользовательский TextView точно в центре CardView. Так вот оно.

<android.support.v7.widget.CardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        card_view:cardBackgroundColor="@color/colorPrimary"
        card_view:cardCornerRadius="1dp"
        card_view:cardElevation="3dp"
        android:longClickable="false"
        android:id="@+id/button">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="48dp"> //just my custom height

        <com.example.admin.lanet_contactwork.MyTextView //for below 5.0
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            PipBoy:fontName="Roboto-Medium.ttf" //custom font
            android:text="@string/enter"
            android:textColor="@android:color/white"
            android:textSize="14sp"
            android:layout_centerInParent="true"
            />
        </RelativeLayout>

    </android.support.v7.widget.CardView>

Ответ 7

См. мой ответ для решения, сохраняющего границу и повышенный эффект на pre-lollipop, сохраняя эффект пульсации на леденец без недостатка здесь