Android Support Library 23.2的初体验

来源:互联网 发布:德旭交规软件 编辑:程序博客网 时间:2024/05/17 06:20

上个月Android Support Library 23.2发布,提供了一些新的功能,其中最实用的我觉得就是夜间模式了,现在主流的app基本都会提供夜间模式这样一个东西,传统的方式就是切换主题然后调用activity的recreate方法嘛。而Android Support Library 23.2的发布,为我们提供了一个官方的实现方法,当然Android Support Library 23.2也包含了其他的一些内容,比如支持矢量图和bottomsheet。如果英文好的话建议直接异步官网博客Android官方博客
下面我将分别介绍这三个新特性,想要使用Android Support Library 23.2 首先要在gradle文件中加入

compile 'com.android.support:support-v4:23.2.0'

矢量图

那什么是矢量图呢,它和我们平常用的bitmap又有什么区别呢?我们都知道我们平时拍的照片什么的都是由像素组成的,像素越高的摄像头拍出的图片质量也就越高,但是矢量图并不是由像素构成的,矢量图使用直线和曲线来描述图形,这些图形的元素是一些点、线、矩形、多边形、圆和弧线等等,它们都是通过数学公式计算获得的。所以矢量图形文件一般较小。矢量图形的优点是无论放大、缩小或旋转等都不会失真;缺点是难以表现色彩层次丰富的逼真图像效果。由于适量图的这些特性,是的它非常适合做Android的图标文件。
想要在Android Studio中使用矢量图,还需要做一些配置,如果你的gradle版本是2.0以上,那只需要在gradle文件中加入

android {     defaultConfig {       vectorDrawables.useSupportLibrary = true      }   } 

如果你的gradle版本是1.5的,那需要加入

// Gradle Plugin 1.5   android {     defaultConfig {       generatedDensities = []    }    // This is handled for you by the 2.0+ Gradle Plugin    aaptOptions {      additionalParameters "--no-version-vectors"    }   } 

那去哪儿找矢量图呢?当然如果有能力的人可以自己做,想我这种菜就只能网上找现成的了。我给大家推荐了一个非常好的网站Material Design Icons,里面有很多Material Design风格的图标,而且可以选择下载的格式,位图或者矢量图。这里我就随便下载了一个

这里写图片描述

下载完成后是一个xml文件,我们可以打开看一下

<!-- drawable/alarm.xml --><vector xmlns:android="http://schemas.android.com/apk/res/android"    android:height="24dp"    android:width="24dp"    android:viewportWidth="24"    android:viewportHeight="24">    <path android:fillColor="#000" android:pathData="M12,20A7,7 0 0,1 5,13A7,7 0 0,1 12,6A7,7 0 0,1 19,13A7,7 0 0,1 12,20M12,4A9,9 0 0,0 3,13A9,9 0 0,0 12,22A9,9 0 0,0 21,13A9,9 0 0,0 12,4M12.5,8H11V14L15.75,16.85L16.5,15.62L12.5,13.25V8M7.88,3.39L6.6,1.86L2,5.71L3.29,7.24L7.88,3.39M22,5.72L17.4,1.86L16.11,3.39L20.71,7.25L22,5.72Z" /></vector>

接下来我们就把这个图标显示出来,首先把它放到drawable文件夹下,然后在布局文件中添加一个imageview

<?xml version="1.0" encoding="utf-8"?><RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.example.hao.newfeature.MainActivity">    <ImageView        android:id="@+id/image"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        app:srcCompat="@drawable/alarm"        android:layout_centerInParent="true"        /></RelativeLayout>

srcCompat就是为Imageview设置矢量图的方式,不过Android Studio会提示找不到app这个前缀,不用管它,直接运行就可以看到效果了

这里写图片描述

很简单吧,但是这个图标太小了,我们想要个更大的图标怎么办,直接在xml里面增加他的高度和宽度属性就可以了,我把它的宽和高都放大十倍看一下效果

这里写图片描述

夜间模式

Android Support Library 23.2提供了一个主题Theme.AppCompat.DayNight,想要实现夜间模式,先让我们的应用换成这个主题

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

有了主题后我们还需要一个切换主题的方法,默认情况下,是否是页面模式取决于一个系统值,这个值可以通过 UiModeManager.getNightMode()获取到。我们也可以通过 AppCompatDelegate.setDefaultNightMode()来设置是否是页面模式。这里可以分两种情况,如果你想要把整个应用都变成夜间模式呢,可以用AppCompatDelegate.setDefaultNightMode()。如果你只想让当前页面变成页面模式则可以用etDelegate() and use setLocalNightMode()这个方法。下面我们来实际操作一遍。
首先增加两个按钮用来切换夜间模式和普通模式,再设置一个Textview来显示当前的状态。

<?xml version="1.0" encoding="utf-8"?><RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.example.hao.newfeature.MainActivity">    <ImageView        android:id="@+id/image"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        app:srcCompat="@drawable/alarm"        android:layout_centerInParent="true"        />    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="match_parent">        <TextView            android:id="@+id/textView"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_centerHorizontal="true"            android:layout_alignParentBottom="true"            android:text=""            android:textSize="50sp"            android:textStyle="bold" />        <LinearLayout            android:id="@+id/linearlayout"            android:layout_width="match_parent"            android:layout_height="wrap_content">            <Button                android:id="@+id/day_mode"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_weight="1"                android:text="DayMode" />            <Button                android:id="@+id/night_mode"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_weight="1"                android:text="NightMode" />        </LinearLayout>    </RelativeLayout></RelativeLayout>

然后在Activity中添加监听事件

@Override    public void onClick(View v) {        switch (v.getId()) {            case R.id.day_mode:                getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_NO);                recreate();                break;            case R.id.night_mode:                getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES);                recreate();                break;        }    }

setLocalNightMode有三种模式:MODE_NIGHT_YES,MODE_NIGHT_NO和MODE_NIGHT_AUTO,最后一种的意思是根据时间自适应。在设置完模式后,记得调用recreate方法,不然是不会切换的。
下面是运行效果

这里写图片描述

这里写图片描述

Bottom Sheet

这篇文章写于3月份,后来由于工作上的事情就给忘了,今天翻草稿箱的时候偶然发现。。。如今Android Suppot Library都到了23.4了,虽然现在补上有点晚,但还是聊胜于无嘛
Bottom Sheet其实一直都在material design中,各类的第三方实现也是层出不穷,这次的Support Library则给出了官方的实现,但个人感觉这个控件在国内还是很难推广开来啊,虽然google费尽心机的想要推广material design,但是国内的产品和设计都是用mac,iPhone的。根本对Android的改变毫不关心好吧,更加重要的就是领导也是都用iPhone的。。
别的不多说了,我们还是先从一个例子才看一下Bottom Sheet吧

<?xml version="1.0" encoding="utf-8"?><android.support.design.widget.CoordinatorLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:id="@+id/main_content"    android:layout_width="match_parent"    android:layout_height="match_parent">    <Button        android:id="@+id/button"        android:text="button"        android:layout_width="match_parent"        android:layout_height="wrap_content" />    <FrameLayout        android:id="@+id/bottom_sheet"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:clipToPadding="true"        android:background="#99000000"        app:layout_behavior="android.support.design.widget.BottomSheetBehavior"        >        <LinearLayout            android:orientation="vertical"            android:layout_width="match_parent"            android:layout_gravity="bottom"            android:background="#ffffffff"            android:layout_height="wrap_content">            <TextView                android:text="拍照"                android:gravity="center"                android:layout_width="match_parent"                android:layout_height="50dp" />            <TextView                android:text="从相册选择"                android:gravity="center"                android:layout_width="match_parent"                android:layout_height="50dp" />            <TextView                android:id="@+id/cancel"                android:layout_marginTop="10dp"                android:text="取消"                android:gravity="center"                android:layout_width="match_parent"                android:layout_height="50dp" />        </LinearLayout>    </FrameLayout></android.support.design.widget.CoordinatorLayout>

Activity代码

public class MainActivity extends AppCompatActivity implements View.OnClickListener{    private BottomSheetBehavior mBottomSheetBehavior;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        CoordinatorLayout mainContent = (CoordinatorLayout) findViewById(R.id.main_content);        View bottomSheet = mainContent != null ? mainContent.findViewById(R.id.bottom_sheet) : null;        Button button = (Button) findViewById( R.id.button );        mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);        button.setOnClickListener(this);        TextView tv= (TextView) bottomSheet.findViewById(R.id.cancel);        tv.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if(!mBottomSheetBehavior.isHideable()){                    mBottomSheetBehavior.setHideable(true);                   mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);                }            }        });    }    @Override    public void onClick(View v) {        switch (v.getId()){            case R.id.button:                mBottomSheetBehavior.setHideable(false);                mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);                break;        }    }}

这个例子的实现效果就如下图所示

这里写图片描述

是不是很类似ios底部的对话框,这是我能想到的Bottom Sheet最有可能的用途。
上面的代码有几点需要注意的,首先就是Bottom Sheet必须配合CoordinatorLayout一起使用,否则就没有效果,然后就是记得在xml文件中加上behaviour

app:layout_behavior="android.support.design.widget.BottomSheetBehavior"

最后一点就是在显示和隐藏Bottom Sheet的时候setHideable方法是必须的,否则将不起作用或者出错。
上述例子中我将state设置成了BottomSheetBehavior.STATE_EXPANDED和BottomSheetBehavior.STATE_HIDDEN,这个两个状态是什么意思呢?我们可以参考官方文档

  • STATE_COLLAPSED: this collapsed state is the default and shows just a portion of the layout along the bottom. The height can be controlled with the app:behavior_peekHeight attribute (defaults to 0)
    折叠状态。可通过app:behavior_peekHeight来设置默认显示的高度
  • STATE_DRAGGING: the intermediate state while the user is directly dragging the bottom sheet up or down
    拖拽状态
  • STATE_SETTLING: that brief time between when the View is released and settling into its final position
    拖拽松开之后到达终点位置(collapsed or expanded)前的状态。
  • STATE_EXPANDED: the fully expanded state of the bottom sheet, where either the whole bottom sheet is visible (if its height is less than the containing CoordinatorLayout) or the entire CoordinatorLayout is filled
    完全展开的状态。
  • STATE_HIDDEN: disabled by default (and enabled with the app:behavior_hideable attribute), enabling this allows users to swipe down on the bottom sheet to completely hide the bottom sheet
    隐藏状态。默认是false,可通过app:behavior_hideable属性设置。

下面我们来看Bottom Sheet的另一种用法,这也是谷歌官方使用的方法,具体可参考谷歌地图

<?xml version="1.0" encoding="utf-8"?><android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:id="@+id/main_content"    android:layout_width="match_parent"    android:layout_height="match_parent">    <Button        android:id="@+id/button"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="button" />    <FrameLayout        android:id="@+id/bottom_sheet"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:background="#ffffff"        android:clipToPadding="true"        app:behavior_peekHeight="50dp"        app:layout_behavior="android.support.design.widget.BottomSheetBehavior">        <LinearLayout            android:orientation="vertical"            android:layout_width="match_parent"            android:layout_height="wrap_content">            <TextView                android:layout_width="match_parent"                android:layout_height="50dp"                android:gravity="center"                android:text="拉我" />            <ListView                android:id="@+id/list_view"                android:layout_width="match_parent"                android:layout_height="wrap_content" />        </LinearLayout>    </FrameLayout></android.support.design.widget.CoordinatorLayout>

activity代码

public class MainActivity extends AppCompatActivity implements View.OnClickListener{    private BottomSheetBehavior mBottomSheetBehavior;    private StringAdapter adapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        CoordinatorLayout mainContent = (CoordinatorLayout) findViewById(R.id.main_content);        View bottomSheet = mainContent != null ? mainContent.findViewById(R.id.bottom_sheet) : null;        Button button = (Button) findViewById( R.id.button );        mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);        mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);        button.setOnClickListener(this);        ListView lv= (ListView) bottomSheet.findViewById(R.id.list_view);        lv.setAdapter(adapter=new StringAdapter(this));        adapter.setData(getData());    }    private ArrayList<String> getData() {        ArrayList<String> list=new ArrayList<>();        for(int i=0;i<5;i++){            list.add("item"+i);        }        return list;    }    @Override    public void onClick(View v) {        switch (v.getId()){            case R.id.button://                mBottomSheetBehavior.setHideable(false);//                mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);                break;        }    }}

运行效果如图所示

这里写图片描述

当用手向上拉时,底下的listview就会被拉出来。

Bottom Sheet Dialog

除了最基础的Bottom Sheet,还有两个现成的控件可是使用,Bottom Sheet Dialog和Bottom Sheet Dialog Fragment。这两个的用法差别不大,这里就简单说下Bottom Sheet Dialog吧,还是实现底部选择拍照,从相册选择的对话框

dialog布局如下所示

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <TextView        android:text="拍照"        android:gravity="center"        android:layout_width="match_parent"        android:layout_height="50dp" />    <TextView        android:text="从相册选取"        android:gravity="center"        android:layout_width="match_parent"        android:layout_height="50dp" />    <TextView        android:text="取消"        android:gravity="center"        android:layout_width="match_parent"        android:layout_height="50dp" /></LinearLayout>

然后在Activity中初始化对话框

 public void initDialog(){        dialog=new BottomSheetDialog(this);        View view=View.inflate(this,R.layout.dialog_bottom_sheet,null);        dialog.setContentView(view);    }

运行效果如图所示

这里写图片描述

和第一个例子基本没啥区别,但是第一例子中的对话框背景是我自己加的,所以在取消对话框的时候有明显的过渡效果,而BottomSheetDialog则没有,所以如果要实现类似ios的底部对话框的话,BottomSheetDialog和BottomSheetDialogFragment是最合适的

0 0
原创粉丝点击