Android6.0-新控件(一)

[转载请注明出处:http://blog.csdn.net/listeners_Gao/article/details/52886162 —By ListenerGao]

前言

谷歌在2015年I/O大会上发布了Android M的新版本.在这次的I/O大会上,谷歌对Android并没有做很大的改变,主要完善之前的Android L版本.不过这次谷歌在继Material Design风格之后,做了很多风格上的兼容,并推出了Android Design Support Library库,全面支持Material Design设计风格的UI效果.该库包含了FloatingActionButton,TextInputLayout,Snackbar,TabLayout,NavigationView,CoordinatorLayout,AppBarLayout,CollapsingToolbarLayout八个新控件.由于篇幅的原因,我们先来学习一下前四个的使用.后续会继续完成其余控件的使用.

使用

需要导入Android Design Support Library库,该库支持Android 2.1以上设备.在build.gradle(moudle:app)中添加依赖:compile 'com.android.support:design:24.2.1' 版本号可自己匹配.

FloatingActionButton

效果图:

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|right"
    android:src="@drawable/ic_favorite"
    android:layout_margin="10dp"
    app:backgroundTint="@color/colorPrimary"
    app:elevation="4dp"
    app:pressedTranslationZ="8dp"
    app:fabSize="normal"
    app:rippleColor="@color/colorPrimaryDark"
    app:useCompatPadding="false" />

注意:

设置FloatingActionButton的背景颜色时使用:app:backgroundTint,默认为 Theme 主题中的 “colorAccent”的颜色;如果使用android:backgroundTint运行时,则会报解析Xml异常.

设置FloatingActionButton的大小,通过app:fabSize属性来设置,有三种格式:auto(基于窗口的大小而自动适应),normal(正常大小的按钮),mini(迷你大小的按钮).这里设置layout_width和layout_height貌似没有什么效果,FloatingActionButton的大小由fabSize属性来决定.可当你把宽和高设置成match_parent时,FloatingActionButton的大小会充满父窗体,大小虽然改变了,但这样的设置在开发中貌似没一点卵用.

app:elevation :设置 FloatingActionButton 阴影的深度,默认有阴影.

app:pressedTranslationZ :设置 FloatingActionButton 点击时阴影的大小.

app:rippleColor :设置 FloatingActionButton 点击时的颜色,也就是设置上面属性后,阴影的颜色.

app:useCompatPadding :设置是否启用compat的填充.

src - 设置FAB的图标,Google建议符合Design设计的该图标大小为24dp.

app:layout_anchor - 设置FAB的锚点,即以哪个控件为参照点设置位置.

app:layout_anchorGravity - 设置FAB相对锚点的位置,值有 bottom、center、right、left、top等.

以上在Xml布局中设置的属性,在代码中同样可以设置.

Snackbar

  • 简介: Snackbar用于展示一条简短的消息给用户,该消息在很多的时间内会消失.该消息只是给用户一个提示,用户不需要去操作.例如:当我们发送一条Email时,告诉用户该Email发送的状态.Snackbar和Toast很像,只不过Toast是在屏幕中心弹出,而Snackbar是在屏幕底部弹出.

  • 使用:代码中使用

    //得到Snackbar对象
    final Snackbar snackbar = Snackbar.make(coordinatorLayout, "我是Snackbar...", Snackbar.LENGTH_LONG);
    //设置Snackbar背景
    snackbar.getView().setBackgroundResource(R.color.colorPrimary);
    snackbar.show();
    //显示带Action的Snackbar
    snackbar.setAction("取消", new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //关闭Snackbar
            snackbar.dismiss();
        }
    });
    
  • 常用方法:

    • make() 方法,生成Snackbar消息对象,第一个参数为View对象,Snackbar 会试着寻找一个父 View 来 hold 这个 View。Snackbar 将遍历整个 View tree 来寻找一个合适的父 View,它可能是一个 coordinatorLayout 也可能是 window decor’s content view,随便哪一个都行.后面的两个参数和Toast一致.
    • setDuration() 方法:设置显示持续时间.
    • setAction() 方法:设置 Action,第一个参数会作为按钮(Actiong)的文本,第二个参数是按钮的点击事件.
    • setCallback() 方法:Snackbar 的显示和消失会回调 Snackbar.Callback的 onDismissed()和 onShown()方法.
    • getView():获取 Snackbar 的 View,进而可以定制Snackbar.
  • 注意:

    • 谷歌其实更建议在CoordinatorLayout(不要着急,后面会细说)布局中使用Snackbar(make()方法中传入的View),当用户滑动屏幕时,可以使Snackbar消失.
    • 当然,如果你只是想在底部弹出提示消息,那么make()方法中传入的任意的View即可.
    • 还有就是当你点击FloatingActionButton时,想弹出Snackbar,同时又想避免Snackbar遮盖住FloatingActionButton,这时,你应该使用CoordinatorLayout来协调各个View之间的动画效果.

效果图:设置点击FloatingActionButton的点击事件,点击弹出Snackbar.

TextInputLayout

  • 简介: TextInputLayout的出现是Google为EditText提供的浮动标签,使其更符合Material Design的风格.TextInputLayout继承LinearLayout,它只是一个容器,不过该容器下只接收一个元素,子元素就是一个EditText元素.这样就为EditText提供了一个带有动画效果的提示标签,同时也可以处理错误信息,将错误信息提示在EditText的下方.

  • 使用:

    • 布局:

      <android.support.design.widget.TextInputLayout
              android:id="@+id/til_username"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:layout_marginLeft="30dp"
              android:layout_marginRight="30dp"
              android:layout_marginTop="20dp">
          <!--这里可以直接使用EditText-->
          <android.support.design.widget.TextInputEditText
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:hint="Username" />
      </android.support.design.widget.TextInputLayout>
      
      <android.support.design.widget.TextInputLayout
          android:id="@+id/til_password"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:layout_marginLeft="30dp"
          android:layout_marginRight="30dp"
          android:layout_marginTop="10dp">
      
              <android.support.design.widget.TextInputEditText
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:hint="Password"
                  android:inputType="textPassword" />
      </android.support.design.widget.TextInputLayout>
      
    • 代码:

      //初始化TextInputLayout(代码中我使用了ButterKnife注解,这里就不贴出来了)
      //得到EditText对象
      final EditText userEditText = tilUsername.getEditText();
      final EditText pwdEditText = tilPassword.getEditText();
      //设置hint提示,也可直接在xml中设置(个人感觉如果在布局中已经设置了hint,代码中就不必在设置了.)
      //userEditText.setHint("Username");
      //pwdEditText.setHint("Password");
      
      
      //EditText添加文本变化监听
      userEditText.addTextChangedListener(new TextWatcher() {
          @Override
          public void beforeTextChanged(CharSequence s, int start, int count, int after) {
              Log.d(TAG, "beforeTextChanged执行了....s = " + s + "---start = " + start + "---count = " + count + "---after = " + after);
          }
      
          @Override
          public void onTextChanged(CharSequence s, int start, int before, int count) {
              Log.d(TAG, "onTextChanged执行了....s = " + s + "---start = " + start + "---count = " + count + "---before = " + before);
              if (s.length() > 7) {
                  tilUsername.setErrorEnabled(true);//设置是否打开错误提示
                  tilUsername.setError("用户名长度不能超过8个");//设置错误提示的信息
              } else {
                  tilUsername.setErrorEnabled(false);
              }
          }
      
          @Override
          public void afterTextChanged(Editable s) {
              Log.d(TAG, "afterTextChanged执行了....s = " + s);
          }
          });
      
      pwdEditText.addTextChangedListener(new TextWatcher() {
          @Override
          public void beforeTextChanged(CharSequence s, int start, int count, int after) {
      
          }
      
          @Override
          public void onTextChanged(CharSequence s, int start, int before, int count) {
              if (s.length() < 6) {
                  tilPassword.setErrorEnabled(true);
                  tilPassword.setError("密码长度不能小于6个");
              } else {
                  tilPassword.setErrorEnabled(false);
              }
          }
      
          @Override
          public void afterTextChanged(Editable s) {
      
          }
      });
      
  • 注意:代码里注释已经很详细了,相信你一看就能明白.这里提一点:就是浮动标签字体的颜色默认是你设置主题时的颜色.

    设置主题的颜色就是EditText浮动标签提示信息的颜色:<item name="colorAccent">@color/colorAccent</item>

效果图:这里模拟登录界面。并对用户名长度是否超过8个,密码长度是否小于6个做了判断。

TabLayout

  • 简介: TabLayout提供了一个水平布局显示标签,主要用来做选显卡切换这一类效果的控件。例如:网易新闻客户端的Tab。Github上也有很多类似效果的开源控件,只是这次谷歌把它官方化了,更方便开发者使用。
  • 简单TabLayout效果图:

  • 使用:

    • xml:

      <android.support.design.widget.TabLayout
          android:id="@+id/tab_layout"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          app:tabIndicatorColor="@android:color/holo_blue_bright"     //Tab指示器下标的颜色
          app:tabSelectedTextColor="@android:color/holo_blue_bright"  //Tab被选中字体的颜色
          app:tabTextColor="@android:color/black">                    //Tab未被选中字体的颜色
      
      </android.support.design.widget.TabLayout>
      
    • 代码:

      //添加8个Tab标签,并设置第一个Tab标签为选中状态.
      tabLayout.addTab(tabLayout.newTab().setText("Tab 1"),true);
      tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
      tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));
      tabLayout.addTab(tabLayout.newTab().setText("Tab 4"));
      tabLayout.addTab(tabLayout.newTab().setText("Tab 5"));
      tabLayout.addTab(tabLayout.newTab().setText("Tab 6"));
      tabLayout.addTab(tabLayout.newTab().setText("Tab 7"));
      tabLayout.addTab(tabLayout.newTab().setText("Tab 8"));
      //设置Tab的模式为可滑动,当tab标签超过屏幕宽度时,可以滑动.
      tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
      

    这里只是简单使用TabLayout完成Tabs选项卡,一般情况下TabLayout+ViewPager相结合使用,这样的使用场景会更多一点,也能发挥出TabLayout的优势。接下来使用TabLayout+ViewPager完成一个小Demo。

  • 效果图:(自定义TabLayout样式+ViewPager使用)

  • 使用:首先我们在Style中自定义TabLayout的样式,在布局中使用时引入自定义的TabLayout样式.添加ViewPager,每个页面是一个Fragment,并且实现联动效果,下面直接看代码:

    • 自定义TabLayout样式:

      <!-- 自定义 TabLayout 样式 -->
      <style name="CustomTabLayout" parent="Widget.Design.TabLayout">
          <item name="paddingEnd">10dp</item>
          <item name="paddingStart">10dp</item>
          <item name="tabBackground">@color/colorPrimary</item>
          <item name="tabContentStart">10dp</item>
          <item name="tabGravity">center</item>
          <item name="tabIndicatorColor">#999900</item>
          <item name="tabIndicatorHeight">6dp</item>
          <item name="tabMaxWidth">@dimen/tab_max_width</item>
          <item name="tabMinWidth">@dimen/tab_min_width</item>
          <item name="tabMode">scrollable</item>
          <item name="tabPaddingBottom">2dp</item>
          <item name="tabPaddingEnd">10dp</item>
          <item name="tabPaddingStart">10dp</item>
          <item name="tabPaddingTop">15dp</item>
          <item name="tabSelectedTextColor">#ffcc00</item>
          <item name="tabTextAppearance">@style/CustomTabTextAppearance</item>
          <item name="tabTextColor">#000066</item>
      </style>
      <!-- 自定义 TabText 的外观 -->
      <style name="CustomTabTextAppearance" parent="TextAppearance.Design.Tab">
          <item name="android:textSize">14sp</item>
          <item name="android:textColor">#006600</item>
          <item name="textAllCaps">false</item>
      </style>
      
    • 页面布局:

      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          android:id="@+id/activity_tab_layout_view_pager"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical"
          tools:context="com.listenergao.mytest.activity.TabLayoutViewPagerActivity">
      
          <include layout="@layout/toolbar_layout" />
      
          <android.support.design.widget.TabLayout
              android:id="@+id/tab_layout"
              style="@style/CustomTabLayout"
              android:layout_width="match_parent"
              android:layout_height="wrap_content">
      
          </android.support.design.widget.TabLayout>
      
          <android.support.v4.view.ViewPager
              android:id="@+id/viewpager"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
      
          </android.support.v4.view.ViewPager>
      </LinearLayout>
      
    • 页面代码:(Activity页面)

      package com.listenergao.mytest.activity;
      
      import android.os.Bundle;
      import android.support.design.widget.TabLayout;
      import android.support.v4.app.Fragment;
      import android.support.v4.view.ViewPager;
      import android.support.v7.widget.Toolbar;
      import android.widget.LinearLayout;
      
      import com.listenergao.mytest.R;
      import com.listenergao.mytest.data.TabFragmentAdapter;
      import com.listenergao.mytest.fragment.TabFragment;
      
      import java.util.ArrayList;
      import java.util.List;
      
      import butterknife.BindView;
      import butterknife.ButterKnife;
      
      /**
       * TabLayout+ViewPager示例
       *
       * @author By ListenerGao
       *         create at 2016/10/14 18:52
       */
      public class TabLayoutViewPagerActivity extends BaseActivity {
      
          @BindView(R.id.toolbar)
          Toolbar toolbar;
          @BindView(R.id.tab_layout)
          TabLayout tabLayout;
          @BindView(R.id.viewpager)
          ViewPager viewpager;
          @BindView(R.id.activity_tab_layout_view_pager)
          LinearLayout activityTabLayoutViewPager;
          private List<String> mTabList;
          private List<Fragment> mTabFragments;
      
          @Override
          protected int getLayoutResId() {
              return R.layout.activity_tab_layout_view_pager;
          }
      
          @Override
          protected void initView() {
              ButterKnife.bind(this);
      
              toolbar.setTitle("TabLayout+ViewPager");
              setSupportActionBar(toolbar);
              getSupportActionBar().setDisplayHomeAsUpEnabled(true);
      
          }
      
          @Override
          protected void initData() {
              mTabList = initTabList();
              initTabLayout(mTabList);
              mTabFragments = initFragments(mTabList);
      
              TabFragmentAdapter adapter = new TabFragmentAdapter(getSupportFragmentManager(),mTabFragments,mTabList);
              viewpager.setAdapter(adapter);
              //将TabLayout与ViewPager关联起来(注意:该行代码需在ViewPager设置Adapter之后调用)
              tabLayout.setupWithViewPager(viewpager);
              //为Tabs设置适配器
              tabLayout.setTabsFromPagerAdapter(adapter);
          }
      
          /**
           * 初始化Tab标签数据
           *
           * @return
           */
          private List<String> initTabList() {
              List<String> tabList = new ArrayList<>();
              for (int i = 0; i < 8; i++) {
                  tabList.add("TAB " + i);
              }
              return tabList;
          }
      
          /**
           * 初始化TabLayout
           *
           * @param list
           */
          private void initTabLayout(List<String> list) {
              for (int i = 0; i < list.size(); i++) {
                  if (i == 0)
                      tabLayout.addTab(tabLayout.newTab().setText(list.get(i)), true);
                  else
                      tabLayout.addTab(tabLayout.newTab().setText(list.get(i)));
              }
              //设置TabLayout的模式为可滑动
              tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
          }
      
          /**
           * 初始化Tab标签对应的Fragment
           *
           * @param list 标签集合数据
           * @return
           */
          public List<Fragment> initFragments(List<String> list) {
              List<Fragment> mTabFragments = new ArrayList<>();
              for (int i = 0; i < list.size(); i++) {
                  Fragment tabFragment = new TabFragment();
                  Bundle bundle = new Bundle();
                  bundle.putString("Content", list.get(i));
                  tabFragment.setArguments(bundle);
                  mTabFragments.add(tabFragment);
              }
              return mTabFragments;
          }
      
      }
      
    • Viewpager适配器:(这里继承的是FragmentStatePagerAdapter,因为可能有很多个Tab标签页面(Fragment).这里不细说,可以自行google.)

      package com.listenergao.mytest.data;
      
      import android.support.v4.app.Fragment;
      import android.support.v4.app.FragmentManager;
      import android.support.v4.app.FragmentStatePagerAdapter;
      
      import java.util.List;
      
      
      /**
       * ViewPager的适配器
       *
       * @author By ListenerGao
       *         Create at 2016/10/15 16:36
       */
      public class TabFragmentAdapter extends FragmentStatePagerAdapter {
          private List<Fragment> mFragments;
          private List<String> mTabTitles;
          public TabFragmentAdapter(FragmentManager fm, List<Fragment> fragments,List<String> tabTitles) {
              super(fm);
              this.mFragments = fragments;
              this.mTabTitles = tabTitles;
          }
      
          @Override
          public Fragment getItem(int position) {
              return mFragments.get(position);
          }
      
          @Override
          public int getCount() {
              return mFragments.size();
          }
          //注意:需要重写此方法,从标签集合中获取到title,否则标签上的title则不会显示.
          @Override
          public CharSequence getPageTitle(int position) {
              return mTabTitles.get(position);
          }
      }
      
    • Tab标签对应的Fragment页面:

      package com.listenergao.mytest.fragment;
      
      import android.os.Bundle;
      import android.support.annotation.Nullable;
      import android.support.v4.app.Fragment;
      import android.view.LayoutInflater;
      import android.view.View;
      import android.view.ViewGroup;
      import android.widget.TextView;
      
      import com.listenergao.mytest.R;
      
      import butterknife.BindView;
      import butterknife.ButterKnife;
      
      
      /**
       * Tab标签对应的页面
       *
       * @author By ListenerGao
       *         Create at 2016/10/15 16:53
       */
      public class TabFragment extends Fragment {
          @BindView(R.id.tv_content)
          TextView tvContent;
          private View view;
          private String content;
      
          @Override
          public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              if (getArguments() != null) {
                  Bundle bundle = getArguments();
                  content = bundle.getString("Content");
              }
          }
      
          @Override
          public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                   Bundle savedInstanceState) {
              // Inflate the layout for this fragment
              view = inflater.inflate(R.layout.fragment_tab, container, false);
              ButterKnife.bind(this, view);
              return view;
          }
      
          @Override
          public void onActivityCreated(@Nullable Bundle savedInstanceState) {
              super.onActivityCreated(savedInstanceState);
              tvContent.setText(content);
          }
      }
      
  • 常用方法:

    • 1,addTab(TabLayout.Tab tab, int position, boolean setSelected) 增加选项卡到 layout中,这是一个重载方法.第一个参数是Tab对象,通过Tablayout.newTab()创建;第二个参数是插入Tab的位置;最后一个参数是当前Tab是否为选中状态.
    • 2,newTab() 新建个 tab.
    • 3,setTabMode(),设置 Mode,有两种值:TabLayout.MODE_SCROLLABLE和TabLayout.MODE_FIXED分别表示当tab的内容超过屏幕宽度是否支持横向水平滑动,第一种支持滑动,第二种不支持,默认不支持水平滑动.如果你添加的Tab很少的话,你应该把Tab的mode设置成MODE_FIXED,否则可能会出现Tab标签不会占满屏幕的宽度.
    • 4,setOnTabSelectedListener(TabLayout.OnTabSelectedListener onTabSelectedListener) 为每个 tab 增加选择监听器.
    • 5,setScrollPosition(int position, float positionOffset, boolean updateSelectedText) 设置Tab滚动到的位置.
    • 6,setTabGravity(int gravity) 设置 Gravity.
    • 7,setTabTextColors(ColorStateList textColor) 设置 tab 中文本的颜色.
    • 8,setTabTextColors(int normalColor, int selectedColor) 设置 tab 中文本的颜色 默认 选中的颜色.
    • 9,setTabsFromPagerAdapter(PagerAdapter adapter) 将TabLayout与ViewPager关联,当PageAdapter更新时,TabLayout会自动更新.(注意:该方法已过时)
    • 10,setupWithViewPager(ViewPager viewPager) 设置Tablayout和ViewPager实现联动效果.
    • 11,getTabAt(int index) 得到选项卡.
    • 12,getTabCount() 得到选项卡的总个数.
    • 13,getTabGravity() 得到 tab 的 Gravity.
    • 14,getTabMode() 得到 tab 的模式.
    • 15,getTabTextColors() 得到 tab 中文本的颜色.

由于篇幅原因,NavigationView,CoordinatorLayout,AppBarLayout,CollapsingToolbarLayout会在下篇文章中介绍.

源码地址:(该功能是在我一个练手项目中写的)

https://github.com/ListenerGao/MyTest/blob/master/app/src/main/java/com/listenergao/mytest/activity/Android6NewWidget.java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值