在新版本里面android的SDK多了几个兼容包,分别是MultiDex,Design,annotations,至于v7下新增的几个控件,基本用不上,因为是基于androidL的,所以这里不说明。
对于android下的annotations,他的完整搜索名字应该是support-annotations-xx.xx。这是新增的注解特性,可以帮助我们在开发中更好的设计接口,方法等。主要是@NoNull,@Nollalbe,@XXXRes等,其中@XXXRes一般是@DrawableRes,@StringRes这一类的,一般使用资源文件下的各种资源文件夹的名字对XX进行代替即可。另外,需要注意,即使我们添加了这些,但是在实际使用中,系统会提示@NoNull警告,但是@XXXRes不会提示警告,我们可以用@CheckResult让系统帮我们提示错误,这样,接口或者方法一旦传输参数错误,就会有错误提示,这样更加明显,也更好。
@XXXRes一般有如下几种:
1.资源文件夹名字类型的:
AnimatorRes
AnimRes
ArrayRes
AttrRes
ColorRes
DimenRes
DrawableRes
StringRes
IdRes
MenuRes
RawRes
StyleableRes
InterpolatorRes
LayoutRes
XmlRes
2.不常用的:
AnyRes
BoolRes
FractionRes
IntegerRes
PluralsRes
StyleRes
另外还有诸如IntDef,StringDef需要注意使用。
在新的兼容包里面多了很多有空的东西,例如support-design兼容包,里面就多了很多很有用的控件,而这些控件,其实就是meterial design的,所以这个兼容包才会命名成support-design兼容包,这个兼容包可以兼容到2.2版本。兼容包下有TextInputLayout,FloatingActionButton,SnackBar,TabLayout,NavigationView,CoordinatorLayout,AppBarLayout,CollapsingToolBarLayout等。
对于TextInputLayout是作为EditText的包裹控件使用的,可以让EditText的hint在点击输入时出现在EditText上面,可以让错误提示出现在EditText下面。使用中需要在xml中布局如下:
<android.support.design.widget.TextInputLayout android:id="@+id/til_pwd" android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" /> </android.support.design.widget.TextInputLayout>然后再使用代码如下:
final TextInputLayout textInputLayout = (TextInputLayout) findViewById(R.id.til_pwd); EditText editText = textInputLayout.getEditText(); textInputLayout.setHint("Password"); editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { if (s.length() > 4) { textInputLayout.setError("Password error");//这个必须要在setErrorEnabled之前 textInputLayout.setErrorEnabled(true); } else { textInputLayout.setErrorEnabled(false); } } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { } });即可实现功能。
而对于FloatingActionButton,其实就是一个拥有特定效果的按钮而已,一个设置的宽高小于应有的宽高的FloatingActionButton就是一个深绿色的圆形下面有一个十字架一样的放射形阴影。而设置的背景会被改成深绿色,同时如果设置的背景是
android.R.drawable.ic_menu_add
则背景与十字架阴影中间会有一个倒立白色水滴一样的图片。当我们点击的时候会有波纹,同时我们设置的波纹会覆盖FloatingActionButton。另外,这个控件本身就是圆形的。使用中,xml如下:
<android.support.design.widget.FloatingActionButton android:id="@+id/button" android:layout_width="48dp" android:layout_height="48dp" android:layout_below="@id/view_button" android:orientation="vertical" />代码如下:
FloatingActionButton button = (FloatingActionButton) findViewById(R.id.button); button.setRippleColor(Color.GRAY);//设置按下去的波纹颜色 button.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.ic_menu_add));//背景色
SnackBar则更为简单仅仅是一个类似ActionSheet一样的,从底部跳起的,左右才有文字的,黑色背景的方框而已。左边为SnackBar实际内容,右边为SnackBar设置的action的内容。使用中不需要xml代码,使用如下:
Button button = (Button) findViewById(R.id.view_button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Snackbar .make(v, "你好啊", Snackbar.LENGTH_LONG) .setAction("delete", new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "delete", Toast.LENGTH_SHORT).show(); } }) .show(); } });
TabLayout跟以前的TabHost类似,只是更好而已。TabLayout继承自ScrollView,可以跟ViewPager搭配使用,也可以单独使用。跟ViewPager搭配使用中,xml如下:
<android.support.design.widget.TabLayout android:id="@+id/tablayout" android:layout_width="match_parent" android:background="#1FBCD2" android:layout_below="@id/view_button" android:layout_height="48dp" /> <android.support.v4.view.ViewPager android:id="@+id/vp" android:layout_below="@id/tablayout" android:layout_width="match_parent" android:layout_height="match_parent" />代码部分涉及到PagerAdapter,这里我自定义的PagerAdapter如下:
public class ViewPagerAdapter extends PagerAdapter { private List<TextView> mViewList; private String[] items; public ViewPagerAdapter(List<TextView> viewList, String[] items) { mViewList = viewList; this.items = items; } @Override public int getCount() { return mViewList.size(); } @Override public CharSequence getPageTitle(int position) { return items[position]; } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(mViewList.get(position)); } @Override public int getItemPosition(Object object) { return super.getItemPosition(object); } @Override public Object instantiateItem(ViewGroup container, int position) { container.addView(mViewList.get(position)); return mViewList.get(position); } }这里需要特别注意,一般情况下,我们不需要重写getPageTitle这个方法的,但是这里使用TabLayout中,如果TabLayout配合ViewPager使用,那么就必须重写getPageTitle这个方法,不然Tab将不能显示信息。
下面是代码部分:
ArrayList<TextView> tvs = new ArrayList<TextView>(); String[] items = {"第一个", "第二个", "第三个"}; for (int i = 0; i < items.length; i++) { TextView tv = new TextView(this); tv.setText(items[i]); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); tv.setTextColor(Color.BLACK); tv.setBackgroundColor(Color.WHITE); tv.setGravity(Gravity.CENTER); tv.setLayoutParams(lp); tv.setTextSize(22); tvs.add(tv); } TabLayout tabLayout = (TabLayout) findViewById(R.id.tablayout); tabLayout.setTabTextColors(Color.WHITE, Color.GRAY);//设置文本在选中和为选中时候的颜色 tabLayout.addTab(tabLayout.newTab().setText("第一个"), true);//添加 Tab,默认选中 tabLayout.addTab(tabLayout.newTab().setText("第二个"),false);//添加 Tab,默认不选中 tabLayout.addTab(tabLayout.newTab().setText("第三个"),false);//添加 Tab,默认不选中 ViewPager vp = (ViewPager) findViewById(R.id.vp); //用来设置tab的,同时也要覆写 PagerAdapter 的 CharSequence getPageTitle(int position) 方法,要不然 Tab 没有 title ViewPagerAdapter adapter = new ViewPagerAdapter(tvs, items); vp.setAdapter(adapter);
//设置TabLayout的viewpager
tabLayout.setupWithViewPager(vp);//和ViewPager联动tabLayout.setTabsFromPagerAdapter(adapter);
这里
setupWithViewPager设置点击跳转ViewPager,而setTabsFromPagerAdapter则是设置ViewPager的滑动切换tab。
NavigationView是配合DrawerLayout使用的,实际上没看出多少用处,一般如下xml进行设置即可。
<android.support.v4.widget.DrawerLayout 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.support.design.widget.NavigationView android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" app:headerLayout="@layout/drawer_header" app:menu="@menu/drawer"/> </android.support.v4.widget.DrawerLayout>app:headerLayout设置主界面,而app:menu设置弹出菜单。
在说明接下来的几个控件之前,需要先讲讲ToolBar。在之前,google曾经推荐使用的ActionBar在Android5.0之后就不再推荐使用了,现在推荐的是使用ToolBar了。
在android5.0之后,使用ActionBar跟之前不一样了,这点是必须要注意的地方。android5.0之后,如果需要使用ActionBar的icon之类的,需要使用
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setLogo(R.drawable.ic_launcher);
getSupportActionBar().setDisplayUseLogoEnabled(true);
官方说法:在API21之后,ActionBar中图标加标题将不再被推荐!
在android5.0Lollipop,也就是API21之后,ToolBar代替了ActionBar。ToolBar使用确实比ActionBar更加简洁明了,更加强大有用。对于使用ToolBar,有两种方式,第一种:使用ToolBar作为ActionBar;第二种:直接使用ToolBar。
对于使用ToolBar作为ActionBar的情况,需要加入appcompat兼容包,然后使用继承parent=“Theme.Appcompat.Light.NoActionBar”的style,最后将ToolBar控件加入到layout布局里面,然后再setSupportActionBar(ToolBar)。这样ActionBar的menu的这些功能就植入ToolBar了,我们对ActionBar的操作也就可以在ToolBar上使用了。
对于直接使用ToolBar的情况,仅仅是将ToolBar作为一个控件进行使用,过程跟其他控件一样。但是需要注意,前一种使用方式就算没进行什么设置,依然会有标题,和右边的操作按钮,但是后一种情况如果不进行什么设置那就什么都不会显示。
对于CoordinatorLayout这个控件是为了实现MD的滚动效果而设计的控件。往往跟同为MD的控件结合使用,常见效果有:1.让浮动操作按钮FloatingActionButton上下滑动,为SnackBar留出空间。这里SnackBar出来的时候不会挡住原本的控件,例如RecyclerView列表,SnackBar会出现在RecyclerView上面。而当SnackBar出来的时候,如果FloatingActionButton在SnackBar的上面,则FloatingActionButton会上移;2.列表控件等控件下滑时,顶部ToolBar隐藏,上移时,出现;3.控制哪个view应该扩展或者收缩,以及其显示大小比例,包括视差显示效果动画。也就是说,其实就是折叠效果,在扩展或者收缩中可以添加效果动画,例如添加图片。
这里涉及到support-v7的RecyclerView的使用,下面先讲讲RecyclerView的使用。可以将RecyclerView认为是一个优化过ListView,RecyclerView可以分为横向和纵向两种,并且不用我们在自定义ViewHolder,因为RecyclerView有一个ViewHolder让我们继承。另外,RecyclerView有自己的Adapter需要我们继承实现。最后不同于ListView的是,RecyclerView需要设置一个LayoutManager,而使用这个LayoutManager我们可以设置RecyclerView的纵向或者横向。
下面是xml布局部分
<android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical" />
下面是一个简单的Adapter代码:
public class RecyclerAdapter extends RecyclerView.Adapter { private String[] mDataset; public RecyclerAdapter(String[] dataset) { mDataset = dataset; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View layout = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, null); return new RecyclerHolder(layout); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { RecyclerHolder mHolder = (RecyclerHolder)holder; mHolder.mTextView.setText(mDataset[position]); } @Override public int getItemCount() { return mDataset.length; } public class RecyclerHolder extends RecyclerView.ViewHolder { public TextView mTextView; public RecyclerHolder(View itemView) { super(itemView); mTextView = (TextView) itemView.findViewById(android.R.id.text1); } } }然后再添加代码:
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView); // 创建一个线性布局管理器 LinearLayoutManager layoutManager = new LinearLayoutManager(this);
// 设置RecyclerView为横向,默认是纵向
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);// 设置布局管理器recyclerView.setLayoutManager(layoutManager);// 创建数据集String[] dataset = new String[100];for (int i = 0; i < dataset.length; i++) { dataset[i] = "item" + i;}// 创建Adapter,并指定数据集RecyclerAdapter adapter = new RecyclerAdapter(dataset);// 设置AdapterrecyclerView.setAdapter(adapter);
这样,一个简单的RecyclerView就可以实现了。
回到CoordinatorLayout,对于第一种常见效果,应该注意,FloatingActionButton会自动检测SnackBar的添加,并让自己自动上移,只要配合CoordinatorLayout进行使用。FloatingActionButton的app:layout_anchor,app:layout_anchorGravity,属性配合使用就可以创造出浮动效果。但是需要特别注意的事CoordinatorLayout必须作为跟布局,不然根本不能实现效果。下面是xml布局:
<?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" android:layout_below="@id/view_button"> <Button android:id="@+id/view_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/view_image" /> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical" /> <android.support.design.widget.FloatingActionButton android:id="@+id/float_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|right" android:layout_margin="16dp" android:src="@mipmap/ic_launcher" app:layout_anchor="@id/recyclerView" app:layout_anchorGravity="bottom|right|end" /> </android.support.design.widget.CoordinatorLayout>下面是代码部分:
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView); // 创建一个线性布局管理器 LinearLayoutManager layoutManager = new LinearLayoutManager(this); // layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); // 设置布局管理器 recyclerView.setLayoutManager(layoutManager); // 创建数据集 String[] dataset = new String[100]; for (int i = 0; i < dataset.length; i++) { dataset[i] = "item" + i; } // 创建Adapter,并指定数据集 RecyclerAdapter adapter = new RecyclerAdapter(dataset); // 设置Adapter recyclerView.setAdapter(adapter); FloatingActionButton button = (FloatingActionButton) findViewById(R.id.float_button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Snackbar .make(v, "你好啊", Snackbar.LENGTH_LONG) .setAction("delete", new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "delete", Toast.LENGTH_SHORT).show(); } }) .show(); } });这样,当我们点击FloatingActionButton的时候SnackBar就会弹出,然后FloatingActionButton就会上移,当SnackBar消失时,FloatingActionButton又会下移。需要注意,CoordinatorLayout的控件添加跟FrameLayout一样,后一个会覆盖在前一个控件之上。
对于CoordinatorLayout的第二种效果,同样需要将CoordinatorLayout作为根布局,另外需要用到一个AppBarLayout控件,这个控件也需要作为CoordinatorLayout的第一个控件使用才行。最后需要在RecyclerView中设置
app:layout_behavior="@string/appbar_scrolling_view_behavior"
这个属性很重要,它是support-v7包的属性,CoordinatorLayout一旦发现这个属性,就会在他包裹的控件中寻找适合的控件,所以我们还需要在ToolBar中设置
app:layout_scrollFlags="scroll|enterAlways"
CoordinatorLayout一旦发现这个属性,那么RecyclerView滑动导致ToolBar的出现,消失这个属性也就成立了。下面是代码部分:
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView); // 创建一个线性布局管理器 LinearLayoutManager layoutManager = new LinearLayoutManager(this); // layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); // 设置布局管理器 recyclerView.setLayoutManager(layoutManager); // 创建数据集 String[] dataset = new String[100]; for (int i = 0; i < dataset.length; i++) { dataset[i] = "item" + i; } // 创建Adapter,并指定数据集 RecyclerAdapter adapter = new RecyclerAdapter(dataset); // 设置Adapter recyclerView.setAdapter(adapter);
对于CoordinatorLayout的第三种效果,如果需要对ToolBar造成折叠效果需要使用CoordinatorLayout作为根布局,使用AppBarLayout作为CoordinatorLayout的第一个控件并包裹CollapsingToolbarLayout,然后CollapsingToolbarLayout包裹Toolbar,这样才能有效果。同时RecyclerView需要设置
app:layout_behavior="@string/appbar_scrolling_view_behavior"
CollapsingToolbarLayout需要设置
app:layout_scrollFlags="scroll|exitUntilCollapsed"这样才行。下面是xml部分:
<?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:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="256dp" android:fitsSystemWindows="true"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="match_parent" app:contentScrim="#30469b" app:expandedTitleMarginStart="48dp" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" android:src="@mipmap/bg" app:layout_collapseMode="parallax" app:layout_collapseParallaxMultiplier="0.7" /> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin" /> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" android:scrollbars="none" /> </android.support.design.widget.CoordinatorLayout>下面是代码部分:
Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(mToolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true);//返回箭头 mToolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onBackPressed(); } }); //使用CollapsingToolbarLayout必须把title设置到CollapsingToolbarLayout上,设置到Toolbar上则不会显示 CollapsingToolbarLayout mCollapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar); mCollapsingToolbarLayout.setTitle("CollapsingToolbarLayout"); //通过CollapsingToolbarLayout修改字体颜色 mCollapsingToolbarLayout.setExpandedTitleColor(Color.WHITE);//设置还没收缩时状态下字体颜色 mCollapsingToolbarLayout.setCollapsedTitleTextColor(Color.GREEN);//设置收缩后Toolbar上字体的颜色 RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView); // 创建一个线性布局管理器 LinearLayoutManager layoutManager = new LinearLayoutManager(this); // layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); // 设置布局管理器 recyclerView.setLayoutManager(layoutManager); // 创建数据集 String[] dataset = new String[100]; for (int i = 0; i < dataset.length; i++) { dataset[i] = "item" + i; } // 创建Adapter,并指定数据集 RecyclerAdapter adapter = new RecyclerAdapter(dataset); // 设置Adapter recyclerView.setAdapter(adapter);
这样就可以实现有背景图片的折叠效果了。
support-v7包里面还有一个CardView控件,这个控件是一个可以实现圆角,阴影等操作的控件
未完成