Android控件点击圆形阴影反馈解决方案

时间:2024-04-09 15:37:01

Android控件点击圆形阴影反馈解决方案

愿景

对于手机App而言,没有反馈效果的按钮使用体验是不舒服的。最近在深入学习Material Design,对其中的ripple效果比较感兴趣。我想着尝试给可点击的图形按钮一个简单的触摸动态反馈效果,这样不至于太生硬。

想实现的效果如下:

Android控件点击圆形阴影反馈解决方案

动态图片如下:


Android控件点击圆形阴影反馈解决方案

实现

经过查找相关资料和自己实践,发现了一个简单的方式,链接如下:

https://yq.aliyun.com/articles/12407

波纹效果(Ripple):

当你使用了Material主题后,波纹动画会自动应用在所有的控件上,我们当然可以来设置其属性来调整到我们需要的效果。

可以通过如下代码设置波纹的背景:

android:background="?android:attr/selectableItemBackground"波纹有边界

android:background="?android:attr/selectableItemBackgroundBorderless"波纹超出边界

使用效果如下:

B1是不设任何背景的按钮

B2设置了?android:attr/selectableItemBackground

B3设置了?android:attr/selectableItemBackgroundBorderless

详情可以点击上面的链接看看。

问题

我个人觉得这样的反馈效果还是比较OK的,可是试验之后发现了这个属性在5.0以上系统运行一切正常,但在5.0以下系统运行是会导致程序崩溃的,对的,即使在布局的xml中对控件添加tools:targetApi="LOLLIPOP",在4.1系统的模拟器中运行也还是会崩溃的!!!真机没有测试。

 

<ImageView

        android:layout_width="30dp"

        android:layout_height="30dp"

        android:background="?android:selectableItemBackgroundBorderless"

        android:clickable="true"

        android:src="@mipmap/ic_launcher_round"

        tools:targetApi="LOLLIPOP" />

错误如下:

android.view.InflateException: Binary XMLfile line #0: Error inflating class ImageView

应该是5.0以下系统的主题中没有这个属性,导致xml解析出错。

 

为解决这个问题,我想着在代码中动态添加该属性,可以解决这个问题,只不过在5.0以下系统会没有触摸反馈(反正现在大部分Android手机都是5.0以上系统的)。

解决

解决方案如下:

activity_main.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    tools:context="cn.gov.hnmtdz.www.circledemo.MainActivity"
>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary"
        android:elevation="4dp"
        tools:targetApi="LOLLIPOP"
>

        <ImageView
            android:id="@+id/iv_menu"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_centerVertical="true"
            android:layout_marginLeft="16dp"
            android:padding="2dp"
            android:src="@drawable/ic_menu"
/>

        <ImageView
            android:id="@+id/iv_split_screen"
            android:layout_width="28dp"
            android:layout_height="28dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="70dp"
            android:padding="2dp"
            android:src="@drawable/ic_split_screen"
/>

        <ImageView
            android:id="@+id/iv_settings"
            android:layout_width="26dp"
            android:layout_height="26dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="16dp"
            android:src="@drawable/ic_settings"
/>


    </RelativeLayout>

</RelativeLayout>

 

 

MainActivity.java代码如下:

package cn.gov.hnmtdz.www.circledemo;

import android.content.res.TypedArray;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private ImageView iv_menu;
    private ImageView iv_split_screen;
    private ImageView iv_settings;

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

    private void initView() {
        iv_menu = (ImageView) findViewById(R.id.iv_menu);
        iv_split_screen = (ImageView) findViewById(R.id.iv_split_screen);
        iv_settings = (ImageView) findViewById(R.id.iv_settings);

//        动态添加属性
       
if (Build.VERSION.SDK_INT >= 21) {//5.0以上系统判断
           
int[] attrs = {android.R.attr.selectableItemBackgroundBorderless};
            TypedArray typedArray = getTheme().obtainStyledAttributes(attrs);
            int resourceId = typedArray.getResourceId(0, 0);
            iv_menu.setBackgroundResource(resourceId);
//            如果图片设置了点击事件,就可以不用setClickable(true)
//            iv_menu.setClickable(true);
           
iv_split_screen.setBackgroundResource(resourceId);
//            如果图片设置了点击事件,就可以不用setClickable(true)
//            iv_split_screen.setClickable(true);
           
iv_settings.setBackgroundResource(resourceId);
//            如果图片设置了点击事件,就可以不用setClickable(true)
//            iv_settings.setClickable(true);
       
}

        iv_menu.setOnClickListener(this);
        iv_split_screen.setOnClickListener(this);
        iv_settings.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.iv_menu:
                ToastUtils.showToast("点击了菜单");
                break;
            case R.id.iv_split_screen:
                ToastUtils.showToast("点击了分屏");
                break;
            case R.id.iv_settings:
                ToastUtils.showToast("点击了设置");
                break;
        }
    }
}

 

总结

开发中遇到的问题,在此记录一下,关键代码如下:

//        动态添加属性
       
if (Build.VERSION.SDK_INT >= 21) {//5.0以上系统判断
            
int[] attrs = {android.R.attr.selectableItemBackgroundBorderless};
            TypedArray typedArray = getTheme().obtainStyledAttributes(attrs);
            int resourceId = typedArray.getResourceId(0, 0);
            iv_menu.setBackgroundResource(resourceId);
//            如果图片设置了点击事件,就可以不用setClickable(true)
//            iv_menu.setClickable(true);
           
iv_split_screen.setBackgroundResource(resourceId);
//            如果图片设置了点击事件,就可以不用setClickable(true)
//            iv_split_screen.setClickable(true);
           
iv_settings.setBackgroundResource(resourceId);
//            如果图片设置了点击事件,就可以不用setClickable(true)
//            iv_settings.setClickable(true);
       
}

        iv_menu.setOnClickListener(this);
        iv_split_screen.setOnClickListener(this);
        iv_settings.setOnClickListener(this);