Android M新控件知识整理
Posted 奴才快来护驾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android M新控件知识整理相关的知识,希望对你有一定的参考价值。
前言:
Google官方在14年Google I/O上推出了全新的设计语言——Material Design。一并推出了一系列实现Material Design效果的控件库——android Design Support Library。其中有TabLayout, NavigationView,Floating labels for editing text,Floating Action Button,Snackbar, CoordinatorLayout, CollapsingToolbarLayout等等控件。
最近刚好空闲,也就整理了些,当然这里参考了很多大大的博客,在此谢过,文末也会贴出相关的链接,不过有些忘记了,很是惭愧…
Android Studio获得Android Design Support Library库
‘compile’com.android.support:design:22.2.1’
(一): TabLayout
Tablayout的作用一般是配合ViewPager结合Fragment一起使用,实现如下图效果
下面就上代码咯~
activity_xml代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FF00AEFF"
app:tabIndicatorColor="#ffffff"
app:tabMode="fixed"
app:tabSelectedTextColor="#FFFF5500"
app:tabTextColor="#ffffff" />
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#ffffff" />
</LinearLayout>
这里对其中的一些属性进行说明
app:tabIndicatorColor=”@color/white”// 下方滚动的下划线颜色
app:tabSelectedTextColor=”@color/gray”// tab被选中后,文字的颜色
app:tabTextColor=”@color/white” // tab默认的文字颜色
app:tabMode=”fixed”//tab较少时均分整个屏幕
app:tabMode=”scrollable” //tab较多时,支持滑动
当然这些属性也可以在代码中设置:
tabLayout.setTabMode(TabLayout.MODE_FIXED);
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
tabLayout.setSelectedTabIndicatorColor();
tabLayout.setTabTextColors(,);注意:这里有两个参数分别是未选中,和选中的时候tab标签的颜色
接着是activity代码:
public class MainActivity extends AppCompatActivity {
private TabLayout tabLayout;
private ViewPager viewPager;
private SimpleFragmentPagerAdapter pagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
//setupWithViewPager必须在ViewPager.setAdapter()之后调用
/**
也可以通过TabLayout的addTab()方法添加新构建的Tab实例到TabLayout中:
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabLayout);;
tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));
*/
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
viewPager = (ViewPager) findViewById(R.id.viewPager);
pagerAdapter = new SimpleFragmentPagerAdapter(getSupportFragmentManager(), this);
viewPager.setAdapter(pagerAdapter);
tabLayout.setupWithViewPager(viewPager);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setNavigationIcon(R.mipmap.ic_launcher);//设置导航栏图标
toolbar.setLogo(R.mipmap.ic_launcher);//设置app logo
toolbar.setTitle("Title");//设置主标题
//toolbar.setSubtitle("Subtitle");//设置子标题
toolbar.inflateMenu(R.menu.menu_toolbar);//设置右上角的填充菜单
}
}
说明: setupWithViewPager必须在ViewPager.setAdapter()之后调用
某些时候也可以用下面的代码来实现TabLayout与viewpager的双向交互
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
viewPager = (ViewPager) findViewById(R.id.viewPager);
pagerAdapter = new SimpleFragmentPagerAdapter(getSupportFragmentManager(), this);
//viewPager.setAdapter(pagerAdapter);
//注意一下,setupWithViePager必须在ViewPager.setAdapter()之后调用!
//tabLayout.setupWithViewPager(viewPager);
//1.设置TabLayout的选项卡监听
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
colorChange(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
//2.设置Tab的标题来自PagerAdapter.getPageTitle()
tabLayout.setTabsFromPagerAdapter(pagerAdapter);
//3.设置TabLayout.TabLayoutOnPageChangeListener,给ViewPager
TabLayout.TabLayoutOnPageChangeListener listener =
new TabLayout.TabLayoutOnPageChangeListener(tabLayout);
viewPager.addOnPageChangeListener(listener);
viewPager.setAdapter(pagerAdapter);
最后是adapter和fragment的代码
public class SimpleFragmentPagerAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = 3;
private String tabTitles[] = new String[]{"tab1", "tab2", "tab3"};
private Context context;
public SimpleFragmentPagerAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
@Override
public Fragment getItem(int position) {
return PageFragment.newInstance(position);
}
@Override
public int getCount() {
return PAGE_COUNT;
}
@Override
public CharSequence getPageTitle(int position) {
return tabTitles[position];
}
}
public class PageFragment extends Fragment {
public static final String ARGS_PAGE = "args_page";
private int mPage;
public static PageFragment newInstance(int page) {
Bundle args = new Bundle();
args.putInt(ARGS_PAGE, page);
PageFragment fragment = new PageFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPage = getArguments().getInt(ARGS_PAGE);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_page, container, false);
TextView textView = (TextView) view.findViewById(R.id.textView);
textView.setText("第" + mPage + "页");
return view;
}
}
fargment的xml文件我只是放了个textview,这里就不帖代码了
至此就是TabLayout的简单用法,但是我们也可以自己定义TabLayout的样式
关于如何自定义TabLayout的样式有兴趣的朋友可以移步:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0731/3247.html参考泡哥的博文。
碰到的坑:
在Android Studio 1.4 ,buildToolsVersion “23.0.3”,小米2s测试机 中创建demo使用TabLayout:最外层不使用CoordinatorLayout而使用LinearLayout做为最外层根布局则界面如下图所示,
通知栏透明变成白色,很是难看,原因是此Activity默认设置了android:theme=”@style/AppTheme.NoActionBar”这个主题
我的解决办法是:修改次Activity的主题
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
其中最后两个item的作用是去除ActionBar,顺便配图一张,意会下前面3个item所代表的含义;
(二): AppBarLayout、CoordinatorLayout
- AppBarLayout 是继承LinerLayout实现的一个ViewGroup容器组件,它是为了Material Design设计的App Bar,支持手势滑动操作。默认的AppBarLayout是垂直方向的,它的作用是把AppBarLayout包裹的内容都作为AppBar,很多时候AppBarLayout都是作为Toolbar的父布局容器
- CoordinatorLayout:是一个增强型的FrameLayout:它的作用有两个
a. 作为一个布局的根布局
b. 最为一个为子视图之间相互协调手势效果的一个协调布局
它是组织它众多子view之间互相协作的一个ViewGroup。CoordinatorLayout使得子view之间知道了彼此的存在,一个子view的变化可以通知到另一个子view,CoordinatorLayout 所做的事情就是当成一个通信的桥梁,连接不同的view,使用 Behavior 对象进行通信。 - CoordinatorLayout + AppBarLayout(向上滚动隐藏指定的View)
1). 首先需要用CoordinatorLayout包住AppBarLayout;
2). 顶部区域的View都放在AppBarLayout里面;
3). AppBarLayout外面,CoordinatorLayout里面,放一个带有可滚动的View.如下的例子,放的是ViewPager,而ViewPager里面是放了RecylerView的,即是可以滚动的View.;
4). 在可以滚动的View上设置属性 app:layout_behavior=”@string/appbar_scrolling_view_behavior”这个Behavior的class是真正控制滚动时候View的滚动行为
比如:在CoordinatorLayout中使用AppBarLayout,如果AppBarLayout的子View(如ToolBar、TabLayout)标记了app:layout_scrollFlags滚动事件,那么在CoordinatorLayout布局里其它标记了app:layout_behavior的子View(LinearLayout、RecyclerView、NestedScrollView等)就能够响应(如ToolBar、TabLayout)控件被标记的滚动事件。
4). 在AppBarLayout里面的View,通过app:layout_scrollFlags属性来控制,滚动时候的表现.其中有4种Flag的类型;
- scroll: 所有想滚动出屏幕的view都需要设置这个flag, 没有设置这个flag的view将被固定在屏幕顶部。
- enterAlways:这个flag让任意向下的滚动都会导致该view变为可见,启用快速“返回模式”。
- enterAlwaysCollapsed:当你的视图已经设置minHeight属性又使用此标志时,你的视图只能已最小高度进入,只有
当滚动视图到达顶部时才扩大到完整高度。 - exitUntilCollapsed:滚动退出屏幕,最后折叠在顶端。
总结:这两个Layout暂时只是做些记录,感觉使用的频率不是很高,有兴趣的朋友可以移步我参考的博文
http://blog.csdn.net/u010687392/article/details/46852565
(三): Toolbar
Toolbar是在 Android 5.0 开始推出的一个 Material Design 风格的导航控件 ,Google 非常推荐大家使用 Toolbar 来作为Android客户端的导航栏,以此来取代之前的 Actionbar 。与 Actionbar 相比,Toolbar 明显要灵活的多。它不像 Actionbar 一样,一定要固定在Activity的顶部,而是可以放到界面的任意位置。其支持:
- 设置导航栏图标;
- 设置App的logo;
- 支持设置标题和子标题;
- 支持添加一个或多个的自定义控件;
- 支持Action Menu;
Toolbar 是在 Android 5.0 才开始加上的,如果想向下兼容的话,我们需要在工程中引入 appcompat-v7 的兼容包,使用 android.support.v7.widget.Toolbar 进行开发。
Toolbar在xml文件中的代码
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<!--自定义控件-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clock" />
</android.support.v7.widget.Toolbar>
其中:background的值的作用是:使其背景色跟随Activity主题指定的颜色(我是这么理解的)
android toolbar作为actionbar 在低分辨率手机上高度太高如何解决?(在知乎看到的,并没有测试)
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="@color/white"
android:minHeight="48dp"
android:theme="@style/ToolBarStyle"
app:maxButtonHeight="48dp"
app:paddingEnd="0dp"
app:paddingStart="0dp"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:titleMarginStart="0dp" />
Activity中的代码:
toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setNavigationIcon(R.mipmap.ic_launcher);//设置导航栏图标
//toolbar.setLogo(R.mipmap.ic_launcher);//设置app logo
toolbar.setTitle("Title");//设置主标题
//toolbar.setTitleTextColor(getResources().getColor(R.color.colorAccent));
//setSupportActionBar(toolbar);
//toolbar.setSubtitle("Subtitle");//设置子标题
toolbar.inflateMenu(R.menu.menu_toolbar);//设置右上角的填充菜单
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
int menuItemId = item.getItemId();
if (menuItemId == R.id.action_search) {
Toast.makeText(MainActivity.this, "searh", Toast.LENGTH_SHORT).show();
} else if (menuItemId == R.id.action_share) {
Toast.makeText(MainActivity.this, "action_share", Toast.LENGTH_SHORT).show();
} else if (menuItemId == R.id.action_item1) {
Toast.makeText(MainActivity.this, "action_item1", Toast.LENGTH_SHORT).show();
} else if (menuItemId == R.id.action_item2) {
Toast.makeText(MainActivity.this, "action_item2", Toast.LENGTH_SHORT).show();
}
return true;
}
});
(四): NavigationView
在Material Design中,NavigationView导航抽屉,被设计用于应用导航,提供了一种通用的导航方式,体现了设计的一致性。而NavigationView的典型用途就是配合之前v4包的DrawerLayout,作为其中的Drawer部分,即导航菜单的本体部分。NavigationView是一个导航菜单框架,使用menu资源填充数据,使我们可以更简单高效的实现导航菜单。它提供了不错的默认样式、选中项高亮、分组单选、分组子标题、以及可选的Header。
参考博文:http://www.jianshu.com/p/76e30f87a4ed;
Tip:在使用Android Studio 开发的时候创建Activity可以选择带NavigationView的Activity,一分钟就搞定了这个效果,你还瞎折腾啥;
碰到的坑:java.lang.IllegalArgumentException: DrawerLayout must be measured with MeasureSpec.EXACTLY.
这个错误是的解决办法是把DrawerLayout 的父容器宽高设置成match_paren
如何使用:典型的布局文件如下,外层是DrawerLayout,它的第一个child将作为content,第二个child作为Drawer
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="start">
<!-- Content -->
<FrameLayout
android:id="@+id/content_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/content_bg" />
<!-- Drawer -->
<android.support.design.widget.NavigationView
android:id="@+id/navigation"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@color/content_bg"
android:fitsSystemWindows="true"
app:headerLayout="@layout/drawer_header"
app:menu="@menu/drawer" />
</android.support.v4.widget.DrawerLayout>
</android.support.design.widget.AppBarLayout>
</LinearLayout>
其中:在DrawerLayout节点添加tools:openDrawer=”start”这个属性目前发现的作用是在布局的时候能查看到效果,去除的话会使节点下的drawer布局在preview观察模式下不可见,删除亦没有影响
但是NavigationView节点下的android:layout_gravity=”start”这条属性不可删除,删除的后果是drawer布局充满屏幕,点击程序异常崩溃 ,且可在此节点下设置drawer布局的背景颜色
NavigationView节点下:这两条属性是引用抽屉的头布局和布局用的
app:headerLayout=”@layout/drawer_header”
app:menu=”@menu/drawer”
效果图如上:这里我们会看到toolbar的title是默认对应的Activity名称,如果想更换的话手动设置toolbar.setTitle(“噜噜噜”),并且你也可以看到一个text文本显示clock,这个就是toolbar自定义的按钮
抽屉头布局xml代码:
<?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="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="@color/heard_bg" />
</LinearLayout>
drawer布局xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="@+id/nav_camara"
android:icon="@android:drawable/ic_menu_camera"
android:title="Import" />
<item
android:id="@+id/nav_manage"
android:icon="@android:drawable/ic_menu_manage"
android:title="Tools" />
</group>
<item android:title="Communicate">
<menu>
<item
android:id="@+id/nav_share"
android:icon="@android:drawable/ic_menu_share"
android:title="Share" />
<item
android:id="@+id/nav_send"
android:icon="@android:drawable/ic_menu_send"
android:title="Send" />
</menu>
</item>
</menu>
说明:其中节点代表分组,android:checkableBehavior=”single”这个属性表述这个group子条目只能单选,我们还可以通过为item添加子菜单来实现带有头部的分组效果,就像上图group小组下面item那样设置,并可以为这个小组设置title;分组是可以选中的,在子 menu item 设置 android:checkable=”true” 就行了
在Activity中的代码:
Activity中必须实现:implements NavigationView.OnNavigationItemSelectedListener
//获取控件,设置监听
NavigationView navigationView = (NavigationView) findViewById(R.id.navigation);
navigationView.setNavigationItemSelectedListener(this);
//设置点击返回键抽屉缩进
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
//抽屉里item的点击事件
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.navigation_original) {
} else if (id == R.id.navigation_library) {
} else if (id == R.id.navigation_component) {
} else if (id == R.id.navigation_ui) {
} else if (id == R.id.navigation_text) {
} else if (id == R.id.nav_send) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
(五): Palette
compile ‘com.android.support:palette-v7:21.0.+’
Eclipse首先我们找到sdk/extras/android/support/v7/palette/libs/android-support-v7-palette.jar导入我们的工程。
/**
* 界面颜色的更改
*/
private void colorChange(int position) {
// 用来提取颜色的Bitmap
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),drawables[position] );
// Palette的部分
Palette.generateAsync(bitmap, new Palette.PaletteAsyncListener() {
/**
* 提取完之后的回调方法
*/
@Override
public void onGenerated(Palette palette) {
Palette.Swatch vibrant = palette.getVibrantSwatch();
//设置tabLayout的背景颜色,为palette取出来的颜色
tabLayout.setBackgroundColor(vibrant.getRgb());
//设置选中的TabLayout标签底部游标的颜色为palette取出来的颜色,并且加深颜色
tabLayout.setSelectedTabIndicatorColor(colorBurn(vibrant.getRgb()));
//设置tab标签颜色,第一个参数是未被选中tab标签颜色,第二个是选中的tab标签颜色
tabLayout.setTabTextColors(getResources().getColor(R.color.gray),getResources().getColor(R.color.withe));
//设置toolbar背景色为palette取出来的颜色
toolbar.setBackgroundColor(vibrant.getRgb());
if (android.os.Build.VERSION.SDK_INT >= 21) {
Window window = getWindow();
// 很明显,这两货是新API才有的。
window.setStatusBarColor(colorBurn(vibrant.getRgb()));
window.setNavigationBarColor(colorBurn(vibrant.getRgb()));
}
}
});
}
/**
* 颜色加深处理
*
* @param RGBValues
* RGB的值,由alpha(透明度)、red(红)、green(绿)、blue(蓝)构成,
* Android中我们一般使用它的16进制,
* 例如:"#FFAABBCC",最左边到最右每两个字母就是代表alpha(透明度)、
* red(红)、green(绿)、blue(蓝)。每种颜色值占一个字节(8位),值域0~255
* 所以下面使用移位的方法可以得到每种颜色的值,然后每种颜色值减小一下,在合成RGB颜色,颜色就会看起来深一些了
* @return
*/
private int colorBurn(int RGBValues) {
int alpha = RGBValues >> 24;
int red = RGBValues >> 16 & 0xFF;
int green = RGBValues >> 8 & 0xFF;
int blue = RGBValues & 0xFF;
red = (int) Math.floor(red * (1 - 0.1));
green = (int) Math.floor(green * (1 - 0.1));
blue = (int) Math.floor(blue * (1 - 0.1));
return Color.rgb(red, green, blue);
}
最后附上demo:http://download.csdn.net/detail/laogong3783/9551694
结束语:写这篇博文只是想对最近的学习的知识做个整理,如有错误,欢迎指正,新人勿喷。
以上是关于Android M新控件知识整理的主要内容,如果未能解决你的问题,请参考以下文章