安卓实战开发之CardView的selector及GrideView的item按下状态保留selector(state_activated)的实现

android的selector对于android开发者而言再熟悉不过了,只要定义一个drawable目录下定义一个selector的xml文件,在布局文件中background引用这个xml文件或者在代码中setBackgroundDrawable的时候使用此xml就可以实现控件按下或有焦点或激活状态等不同状态的效果。你真的对selector的使用全了解吗?

前言

项目中确实用到了像多个标签,然后选中规格要给文字的边框加点颜色,对于长度和个数不确定的情况呢我们通常可以在代码中通过数据的长度动态的new一个控件然后给他们加点击事件,并且给每个控件设置背景是可以实现的,但是使用grideView的话还是不好实现,所以呢就搜了下发现state_activated能够完美的实现此功能。

效果如下

安卓4.4下效果:

安卓5.1效果

selector属性介绍

selector 的根节点必须是item、可以包含一个或多个item元素

xmlns:android String、必须、定义XML的命名空间、必须是 “http://schemas.android.com/apk/res/android

android:state_pressed

Boolean、“true”表示按下状态使用(例如按钮按下)、“false”表示非按下状态使用

android:state_focused

Boolean、“true”表示聚焦状态使用(例如使用聚焦Button);“false”表示非聚焦状态使用

android:state_selected

Boolean、“true”表示选中状态使用(例如Tab 打开);“false” 表示非选中状态使用

android:state_enabled设置是否响应事件,指所有事件

哈哈,上面的属性你是否经常使用,因为我们的需求一般都是有无焦点有无按下来改变图片的文字和背景颜色,然后呢,比如listView和grideView点击后状态保留你可能不一定使用过。

android:state_checkable

Boolean、“true”表示可勾选状态时使用;“false”表示非可 勾选状态使用、(只对能切换可勾选—非可勾选的构件有用)

android:state_hovered

这个是api14以上才有的,这个是当光标移动到某一个组件之上的时候的状态,到目前为止,还没有看见过哪个手机设备带有鼠标之类的东西,可能这个专门是为平板电脑设置的或者以后可能出现带有鼠标之类的设备而准备的吧,文档中说,一般这个值设置为与focused这个值一样。

android:state_window_focused

这个是是否对当前界面是否得到焦点的两种状态的设置,所以呢一般我们都是用不到的

android:state_activated

表示当前控件被激活的状态,这个呢或许很多安卓开发者都没有用过,然后呢它可以保留被按下的状态

详细的请看官方的API,那里写的更详细http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList

selector的实例使用

一般selector的作用呢就是给view控件设置背景前景等,因为selector本意呢根据状态的不同为同一个图形更换不同的图片。然后呢使用StateListDrawable来代替普通的drawable,具体的drawable的绘制你可以参考Android的各种Drawable讲解,所以呢drawable可以是color,shape,img,今天的重点不是要去绘制drawable而是去使用selector。

给cardView设置selector(state_pressed使用)

我相信很多人使用过CardView,现在呢我们给它加一个前景selector

 <android.support.v7.widget.CardView
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:foreground="@drawable/card_foreground"
        android:id="@+id/cv_item"
        android:elevation="2dp"
        app:cardCornerRadius="4dp"
        app:cardBackgroundColor="@android:color/white"
        app:cardPreventCornerOverlap="false"
        app:cardUseCompatPadding="true"
        android:clickable="true">

        <TextView
            android:id="@+id/text_view"
            android:padding="20dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="selector 按下松开效果"/>
    </android.support.v7.widget.CardView>

要设置selector的前提呢,我们得准备drawable,然后cardView我们给它设置selector就得区分5.0之前和之后的效果,我们都知道5.0后点击会有水波纹效果(ripple ),然后之前我们并没有此效果。

然后我们怎么去设置呢:

drawable文件下适配

card_foreground.xml

<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/card_foreground_selector"
    android:insetLeft="2dp"
    android:insetRight="2dp"
    android:insetTop="4dp"
    android:insetBottom="4dp"/>

card_foreground_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <solid android:color="#e0F5AD6E"/>
            <corners android:radius="@dimen/card_radius" />
        </shape>
    </item>
    <item android:state_focused="true" android:state_enabled="true">
        <shape android:shape="rectangle">
            <solid android:color="#0f000000"/>
            <corners android:radius="@dimen/card_radius" />
        </shape>
    </item>
</selector>

drawable-v21文件下适配

card_foreground.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="#F5AD6E"
    android:drawable="@drawable/card_foreground_selector" />

card_foreground_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <solid android:color="#F5AD6E"/>
        </shape>
    </item>
    <item android:state_focused="true" android:state_enabled="true">
        <shape android:shape="rectangle">
            <solid android:color="#0f000000"/>
        </shape>
    </item>
</selector>

什么ripple和inset 并不是重点,重点是我们如何去写selector文件,其实呢特别简单,你有多少个状态就用item分开好了,接着为各种状态下配置drawable好了,这里呢我直接把shape作为drawable使用了。

grideView的item按下状态保留(state_activated)

其实没有碰到这种情况的时候我也没有去注意state_activated使用,哈哈,确实给开发带来了很大的方便。

当我们发现selector中的state_selected不起作用:注意state_activated状态,作用是激活view后状态一直到保留,除非激活状态被取消,所以必须指定android:state_activated为true或者false。

gride_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">  

    <item  android:state_activated="false">
        <shape xmlns:android="http://schemas.android.com/apk/res/android" >

            <!-- 线的宽度,颜色灰色 -->
            <stroke android:width="1dp" android:color="#A3A3A3"></stroke>
            <!-- 矩形的圆角半径 -->
            <corners android:radius="4dp" />
        </shape>
    </item>
    <item  android:state_pressed="true">
        <shape xmlns:android="http://schemas.android.com/apk/res/android" >
            <!-- 线的宽度,颜色灰色 -->
            <stroke android:width="1dp" android:color="#ffea5514"></stroke>
            <!-- 矩形的圆角半径 -->
            <corners android:radius="4dp" />
        </shape>
    </item>
    <item  android:state_activated="true">
        <shape xmlns:android="http://schemas.android.com/apk/res/android" >
            <!-- 线的宽度,颜色灰色 -->
            <stroke android:width="1dp" android:color="#ffea5514"></stroke>
            <!-- 矩形的圆角半径 -->
            <corners android:radius="4dp" />
        </shape>
    </item>
</selector>

哈哈写完了,我们就可以加到grideView的item布局里面,具体的是加在根布局下还是具体的控件下都是可以的。

好了,我们来看看activity的代码:

package com.losileeya.selectmaster;

import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;

import com.losileeya.selectmaster.adapter.TagAdapter;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.gridview)
    GridView gridview;
    private TagAdapter mAdapter;
    private List<String>mDatas;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        initData();
        doEvent();
    }
    private void initData() {
        mDatas=new ArrayList<>();
        mDatas.add("东方财富?理财");
        mDatas.add("58 同 城");
        mDatas.add("搜 房 网");
        mDatas.add("携程旅行网");
        mDatas.add("百度地图");
        mDatas.add("12306?旅游");
        mDatas.add("世纪佳缘");
        mDatas.add("赶 集 网");
        mDatas.add("易 车 网");
        mDatas.add("去哪儿网");
        mDatas.add("唯 品 会");
    }
    private void doEvent() {
        gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {
                Snackbar.make(gridview,mDatas.get(position), Snackbar.LENGTH_SHORT)
                        .show();

            }
        });
    gridview.setChoiceMode(GridView.CHOICE_MODE_SINGLE);// 单选模式
        // 默认第一个item被选中
        mAdapter = new TagAdapter(MainActivity.this, mDatas, 0);
        gridview.setAdapter(mAdapter);
        gridview.post(new Runnable() {
            @Override
            public void run() {
                gridview.setItemChecked(0, true);
                gridview.setSelected(true);
                gridview.setSelection(0);
            }
        });
    }
}

看上面的代码可知:大体实现步骤

1.GridView中的图标在drawable中写出selector,该selector文件中列出了android:state_pressed的图片资源、state_selected的图片资源。

2.gridview.setChoiceMode(GridView.CHOICE_MODE_SINGLE);// 单选模式

3.GridView的onItemClickedListener监听里,针对当前选择的view,调用view.selected(true)

4.gridview.setItemChecked(0, true);gridview.setSelection(0);默认选中第一个

注意事项

selector.xml中的state_activated状态属性必须在androidAPI-11及以上版本使用。

写到这里就写完了,基本上都是项目中能够用到的(check这里没讲,使用差不多不多讲)不知道对你有什么帮助,虽然很简单是不是对selector的理解更进一步。

demo传送门:SelectMaster.rar

时间: 2024-11-05 21:38:46

安卓实战开发之CardView的selector及GrideView的item按下状态保留selector(state_activated)的实现的相关文章

安卓实战开发之JNI入门及高效的配置(android studio一键生成.h,so及方法签名)

前言 以前也讲过NDK开发,但是开始是抱着好玩的感觉去开始的,然后呢会helloWord就觉得大大的满足,现在静下来想这NDK开发到底是干什么呢? NDK开发,其实是为了项目需要调用底层的一些C/C++的一些东西:另外就是为了效率更加高效些但是在java与C相互调用时平白又增大了开销(其实效率不见得有所提高),然后呢,基于安全性的考虑也是为了防止代码被反编译我们为了安全起见,使用C语言来编写这些重要的部分来增大系统的安全性,最后呢生成so库便于给人提供方便. 好了,我们来看一下qq的结构,我们就

安卓实战开发之SQLite从简单使用crud

前言 最近项目忙,然后呢很久没有更新博客了,react-native也是没有时间学习,然后项目里面用到了数据持久化(数据存储),Android系统中主要提供了三种数据持久化方式:文件存储.SharedPreference存储.数据库存储.说实在的毕竟app这种轻量级的使用数据库还是不多,然后呢要使用数据库也是在特定场合,这也导致了很多的移动端开发(对数据库操作不多)对数据库使用不太熟练. 应用场景 一般我们都不使用数据库的,基本上使用SharedPreference就能处理大部分问题,然后在特定

安卓实战开发之JNI再深入了解

JNI重新认识 头文件: 1.头文件中存放的是对某个库中所定义的函数.宏(define).类型.全局变量等进行声明,它类似于一份仓库清单.若用户程序中需要使用某个库中的函数,则只需要将该库所对应的头文件include到程序中即可. 2.头文件中定义的是库中所有函数的函数原型.而函数的具体实现则是在库文件中. 3.在连接器连接程序时,会依据用户程序中导入的头文件,将对应的库函数导入到程序中.头文件以.h为后缀名. 头文件是给编译器用的,库文件是给连接器用的 函数库: 1.动态库:在编译用户程序时不

安卓开发之Kotlin和java双实现仿qq空间下拉图片拉伸

先不扯淡看今天要实现的效果: 话说使用Kotlin实现安卓功能,那我们还是要做一点准备工作,so,你得加一点插件到eclipse或android studio.然并卵,你现在还在使用eclipse开发的话我只能提供地址Kotlin Plugin for Eclipse,然后我使用的还是死丢丢. 死丢丢(android studio)集成kotlin安卓开发 要使用android studio开发kotlin的安卓app,那么你必须有开发kotlin的环境: Kotlin插件.打开Android

安卓实践开发之MVP一步步实现到高级封装

在上家干了快2年辞职后在家休息了快一个月了,说实在的不上班的感觉爽(睡觉睡到自然醒,游戏玩到手抽筋).哈哈,又是快到一年过中秋的时候了,好久没有更新博客了,今天顺便撸一篇. 前言 话说MVP的模式已经问世好几年了,为什么很多公司还是不愿意接受呢?说实在的我就还是喜欢自己的mvc,不喜欢看见mvp庞大的架构,所以前公司的项目呢也不曾使用过mvp(同事也不接受这种模式),毕竟项目架构不是特别复杂的话使用mvp显示不出他的优势,相反给人的感觉是实现一个界面多出了很多的代码. 然而现在最火的应该是mvv

安卓混合开发之Cordova,NativeWebView两种实现

转载请注明出处:王亟亟的大牛之路 如今混合开发已经不是新鲜词了,虽然作为源生的死忠我不怎么愿意去用H5实现我的功能,但是需求说了算...还是屈服了...然后就去了解了下,也抠了点Demo在这里分享给大家(也许网上有类似的,但是我这个肯定是可以run并且实现方式是不同的) 上内容之前,先说下纯H5 混合 纯native的各种区别,不了解的可以看下下面的简单描述(扣来的) 一.原生应用 优点 可访问手机所有功能(GPS.摄像头): 速度更快.性能高.整体用户体验不错: 可线下使用(因为是在跟Web相

iOS开发之Socket通信实战--Request请求数据包编码模块

实际上在iOS很多应用开发中,大部分用的网络通信都是http/https协议,除非有特殊的需求会用到Socket网络协议进行网络数 据传输,这时候在iOS客户端就需要很好的第三方CocoaAsyncSocket来进行长连接连接和传输数据,该第三方地 址:https://github.com/robbiehanson/CocoaAsyncSocket,读者可以自行google或者baidu搜索 这个库的用法,网上有很多资料,而且用法不难. 在一些对Socket通信使用需求不是很高的应用中,比如需要

Android快速开发之appBase——实战《购物车》

Android快速开发之appBase--实战<购物车> 最近将appBase实战于各种项目中,也发现了不少问题,并优化了很多功能.今天带给大家一个实战–<购物车>.购物车,在商城app中是必不可少的一部分,也是使用的比较多的,这里简单的做一个效果. 先来看看效果图 1.创建项目 第一种.引用appBase项目即可 第二种.将appBase的jar文件copy到libs下 我用的第二种,如上图所示. 2.代码生成 通过代码生成器生成Activity.Presenter.Adapte

浅谈Android样式开发之selector

引言 上一篇Android UI中文章我们详细介绍了Android中shape标签的使用.通过shape标签我们可以定义矩形.椭圆.环形.直线等效果.不过shape只能定义单一的形状,在实际开发中,我们经常需要有一些交互性的体验.例如,按钮按下时的效果,ListView中Item被选中时的样式.这些固然可以通过写Java逻辑代码来实现,但是Android系统为我们定义了selector标签来实现这些功能.这样一方面我们少写了些Java代码,同时selector定义在XML文件中,可维护性相比写在