Android CardView全解析(一)

本文详述了Android CardView的工作原理,并通过创建自定义的RoundView来模仿其功能,包括圆角设置和阴影效果。文章介绍了如何通过IRoundView、RoundRectDrawableWithShadow和IRoundViewDelegate实现圆角和阴影,以及在不同Android版本中优化性能的策略。

**前言:前面写了一博客 Android订单流程view(超简单!)
其中用到了(CardView),之前也用过,很爽!!所以对于CardView其实很早就想去研究一下它了,于是就有了这篇博客了,写这篇博客的目的呢,主要是属性一下google的工程师们是怎么封装一个控件的,整个过程下来,还是学习到了挺多的知识的,于是打算把我学到的一些东西分享出来,算是当作学习笔记了。**

那么CardView是干什么的呢?
想必有些小伙伴对于它也并不陌生。CardView是v7包中的组件(ViewGroup),主要用来设置布局的边框为圆角、z轴的偏移量(这个是5.0以后才有的概念,也就是阴影的效果)。看一下它的效果:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.yasin.round.MainActivity"
    android:orientation="vertical"
    >

    <com.yasin.round.card.RoundView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:backgroundColor="#ff00"
        app:conerRadius="10dp"
        app:shadowSize="10dp"
        app:shadowStartColor="#33000000"
        app:shadowEndColor="#22000000"
        >
        <RelativeLayout
            android:layout_gravity="center"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            >
            <TextView
                android:layout_centerInParent="true"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="RoundView"
                />
        </RelativeLayout>
    </com.yasin.round.card.RoundView>
    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_margin="10dp"
        app:cardBackgroundColor="#ff00"
        app:cardElevation="10dp"
        app:cardCornerRadius="10dp"
        >
        <TextView
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="v7(CardView)"
            />
    </android.support.v7.widget.CardView>
</LinearLayout>

上面的RoundView是我们照着CardView实现出来的。

运行效果:

这里写图片描述

当然,系统的CardView是没办法修改阴影的颜色的,我们实现的RoundView对它进行了一些小小的修改,使其能支持颜色修改,当然,我也就实现了大体的部分,本篇roundview只是做演示的demo,小伙伴可不要直接拖到项目中用啊~~

废话不多说,我们要开撸了~~~小伙伴跟紧啦!

首先明确下我们的目标:

1、可以实现圆角功能
2、可以设置阴影(z轴的偏移)

看起来很简单,但是我们的代码还是比较多的,不过没关系,我们重点看一下大神们到底是咋写代码的。

首先我们定义一下我们需要用到的属性:

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="RoundView">
        <!--背景颜色-->
        <attr name="backgroundColor" format="color"></attr>
        <!--圆角的半径-->
        <attr name="conerRadius" format="dimension"></attr>
        <!--z轴的偏移量,(阴影的大小)-->
        <attr name="shadowSize" format="dimension"></attr>
        <!--阴影的起始颜色-->
        <attr name="shadowStartColor" format="color"></attr>
        <!--阴影的结束颜色-->
        <attr name="shadowEndColor" format="color"></attr>
    </declare-styleable>
</resources>

定义好了我们的自定义属性后,我们接下来创建一个view叫RoundView去继承FrameLayout,然后初始化我们的控件获取我们的自定义属性:

public class RoundView extends FrameLayout {
   
   
    /**
     * 阴影的起始颜色
     */
    private int mShadowStartColor;
    /**
     * 阴影的结束颜色
     */
    private int mShadowEndColor;
    /**
     * 圆角半径
     */
    private float mRadius;
    /**
     * 阴影的起始颜色
     */
    private float mElevation;
    /**
     * 控件背景颜色
     */
    private ColorStateList mBackgroundColor;
    public RoundView(Context context) {
        super(context);
        initialize(context, null, 0);
    }

    public RoundView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initialize(context, attrs, 0);
    }

    public RoundView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initialize(context, attrs, defStyleAttr);
    }
        private void initialize(Context context, AttributeSet attrs, int defStyleAttr) {

    }
}

然后去获取我们的自定义属性:

private void initialize(Context context, AttributeSet attrs, int defStyleAttr) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundView, defStyleAttr, 0);
        //判断是否有背景颜色
        if (a.hasValue(R.styleable.RoundView_backgroundColor)) {
            mBackgroundColor = a.getColorStateList(R.styleable.RoundView_backgroundColor);
        } else {
            //获取系统的背景颜色
            TypedArray aa = context.obtainStyledAttributes(new int[]{android.R.attr.colorBackground});
            //获取系统的背景颜色
            int themeBackgroundColor = aa.getColor(0, 0);
            //获取背景颜色的hvs值(h色彩、s饱和度、v颜色值)
            float[] hsv = new float[3];
            Color.colorToHSV(themeBackgroundColor, hsv);
            //当饱和度>0.5的时候,我们获取自定义的cardview_dark_background颜色
            if (hsv[2] > 0.5) {
                mBackgroundColor = ColorStateList.valueOf(getResources().getColor(R.color.cardview_dark_background));
            } else {
                mBackgroundColor = ColorStateList.valueOf(getResources().getColor(R.color.cardview_dark_background));
            }
            aa.recycle();
        }
        mRadius = a.getDimensionPixelSize(R.styleable.RoundView_conerRadius, 0);
        mElevation = a.getDimensionPixelSize(R.styleable.RoundView_shadowSize, 0);
        mShadowStartColor = a.getColor(R.styleable.RoundView_shadowStartColor, getResources().getColor(R.color.cardview_shadow_start_color));
        mShadowEndColor = a.getColor(R.styleable.RoundView_shadowEndColor, getResources().getColor(R.color.cardview_shadow_end_color));
        a.recycle();

好啦!写到这里我们才完成了最基本的部分,接下来我们需要考虑(兼容android不同版本、提高性能、代码上的高内聚低耦合)等一系列因素了。

考虑到不同的android版本实现圆角、阴影的方式不同的因素,我们应该把具体实现跟我们的roundview分离开来(整个下来有点mvp模式的感觉,你也可以理解为mvp模式吧)。

我们代码中分为三个部分:

  1. 创建IRoundView来处理roundview的业务逻辑
  2. RoundRectDrawableWithShadow(drawable)实现具体的功能
  3. IRoundViewDelegate(相当于roundview的代表)负责IRoundView跟drawable之间的通信。

drawable实现好相关功能->给IRoundView->IRoundView通过IRoundViewDelegate代表类修改roundview的相关属性。

好啦!!知道了大体的框架后,我们就开动了。

首先创建一个IRoundView类:
IRoundView

package com.yasin.round.card;

/**
 * Created by leo on 17/3/31.
 */

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值