- Android Material Design 详解(使用support v7兼容5.0以下系统)
-
Material Design是Google在2014年的I/O大会上推出的全新设计语言。Material Design是基于Android 5.0(API level 21)的,兼容5.0以下的设备时需要使用版本号v21.0.0以上的support v7包中的appcpmpat,不过遗憾的是support包只支持Material Design的部分特性。使用eclipse或Android Studio进行开发时,直接在Android SDK Manager中将Extras->Android Support Library升级至最新版即可。目前最新版本为:
1com.android.support:appcompat-v7:
21.0
.
3
本文中示例程序使用minSdkVersion=14,即属于使用support包实现Material Design风格。
使用Material Design的步骤:
一、使用Material主题
1.创建一个Android应用,应用主题Theme.AppCompat(或其子主题,如Theme.AppCompat.Light.DarkActionBar)
2.自定义程序所使用的主题的某些属性,示例:
12345678910<style name=
"AppTheme"
parent=
"Theme.AppCompat.Light.DarkActionBar"
type=
"text/css"
><!--ActionBar的颜色-->
<item name=colorPrimary>
@color
/primary</item>
<!-- 随主题而改变的颜色(如CheckBox的颜色)-->
<item name=colorAccent>
@color
/accent</item>
<!--状态栏的颜色 (使用support包时似乎无效。)-->
<item name=colorPrimaryDark>
@color
/primary_dark</item>
<!--ActionBar的样式-->
<item name=actionBarStyle>
@style
/AppTheme.ActionBarStyle</item></style><style name=
"AppTheme.ActionBarStyle"
parent=
"Widget.AppCompat.ActionBar.Solid"
type=
"text/css"
><item name=android:titleTextStyle>
@style
/AppTheme.ActionBar.TitleTextStyle</item></style><style name=
"AppTheme.ActionBar.TitleTextStyle"
parent=
"@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
type=
"text/css"
><!--ActionBar标题文字颜色-->
<item name=android:textColor>
@android
:color/white</item></style>
效果图:相对于普通的ActionBar的变化:
(1)右侧三个小点的样式变了。(这个无所谓。。。)
(2)点击右侧三个小点(更多)时,下拉菜单不是从ActionBar的下面开始展开,而是直接从ActionBar之上开始!也许的确有办法把它改成旧的样式,不过查阅官方文档之后发现,Google对此的解释是:菜单是一个临时展现给用户的组件,因此应该悬浮在上面。也就是说,新的设计规则推荐的就是这种默认的样式。
二、使用RecyclerView
RecyclerView是Google在support v7包中提供的一个全新的组件。该组件是一个增强版的ListView,新特性:
1.提高了性能;
2.adapter中自动进行item复用,也就是说,以前的这种繁琐的写法不需要了:
12345678910if
(convertView ==
null
) {
convertView = LayoutInflater.from(context).inflate(R.layout.friends_item, parent,
false
);
holder =
new
ViewHolder();
holder.nameTV = (TextView) convertView.findViewById(R.id.friends_item_name);
holder.phoneTV = (TextView) convertView.findViewById(R.id.friends_item_phone);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
3.预置了item的添加,删除,移动,修改时的动画,当且改动画也可以自定义。
效果图:
(1)主页面,获取到RecyclerView,设置adapter即可。
1234567891011121314151617181920212223RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
mRecyclerView.setHasFixedSize(
true
);
// use a linear layout manager
mRecyclerView.setLayoutManager(
new
LinearLayoutManager(
this
));
//data
List<cityinfobean> myDataset =
new
ArrayList<cityinfobean>();
for
(
int
i =
0
; i <
50
; i++) {
CityInfoBean city =
new
CityInfoBean();
city.setCityName(Tianjin- + i);
city.setCityPhone(
022
- + i);
city.setLocation(Asia_ + i);
myDataset.add(city);
}
RecyclerViewAdapter mAdapter =
new
RecyclerViewAdapter(
this
, myDataset);
mRecyclerView.setAdapter(mAdapter);
//RecyclerView doesn't has a 'OnItemClickListener' or 'OnItemLongClickListener' like ListView,
// so you should add the callback in adapter </cityinfobean></cityinfobean>
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121public
class
RecyclerViewAdapter
extends
RecyclerView.Adapter<recyclerviewadapter.viewholder> {
private
Context context;
private
List<cityinfobean> mDataset;
public
RecyclerViewAdapter(Context context, List<cityinfobean> myDataset) {
this
.context = context;
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
@Override
public
ViewHolder onCreateViewHolder(ViewGroup parent,
int
viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_list_item, parent,
false
);
// set the view's size, margins, paddings and layout parameters
final
ViewHolder vh =
new
ViewHolder(v);
v.setOnClickListener(
new
View.OnClickListener() {
@Override
public
void
onClick(View v) {
int
position = vh.getPosition();
Toast.makeText(v.getContext(), Item click. Position: +
position, Toast.LENGTH_SHORT).show();
}
});
v.setOnLongClickListener(
new
View.OnLongClickListener() {
@Override
public
boolean
onLongClick(View v) {
int
position = vh.getPosition();
// Toast.makeText(v.getContext(), Item long click. Position: +
// position, Toast.LENGTH_SHORT).show();
showDialog(position);
return
true
;
}
});
return
vh;
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public
void
onBindViewHolder(ViewHolder holder,
int
position) {
holder.cityNameTV.setText(mDataset.get(position).getCityName());
holder.phoneTV.setText(mDataset.get(position).getCityPhone());
holder.addrTV.setText(mDataset.get(position).getLocation());
}
@Override
public
int
getItemCount() {
return
mDataset.size();
}
private
void
showDialog(
final
int
position) {
AlertDialog.Builder builder =
new
AlertDialog.Builder(context);
builder.setTitle(Choose operation);
String[] dialogItems =
new
String[]{
context.getString(R.string.delete_one_item),
context.getString(R.string.add_one_item),
context.getString(R.string.move_one_item),
context.getString(R.string.change_one_item),
context.getString(R.string.add_many_items),
};
builder.setItems(dialogItems,
new
DialogInterface.OnClickListener() {
@Override
public
void
onClick(DialogInterface dialog,
int
which) {
switch
(which) {
case
0
:
//delete this item
mDataset.remove(position);
notifyItemRemoved(position);
break
;
case
1
:
//add one item
mDataset.add(position,
new
CityInfoBean(New City,
010
, Asia));
notifyItemInserted(position);
break
;
case
2
:
//TODO remember to change the data set...
//move one item to another position
notifyItemMoved(position, position +
2
);
//May cause IndexOutOfBoundsException. This is just a demo!
break
;
case
3
:
//change one item
mDataset.get(position).setCityName(City name changed);
notifyItemChanged(position);
break
;
case
4
:
//add many items
List<cityinfobean> insertList =
new
ArrayList<cityinfobean>();
insertList.add(
new
CityInfoBean(New City
01
,
010
, Asia));
insertList.add(
new
CityInfoBean(New City
02
,
020
, America));
mDataset.addAll(position, insertList);
notifyItemRangeInserted(position, insertList.size());
break
;
default
:
break
;
}
}
});
builder.create().show();
}
public
static
class
ViewHolder
extends
RecyclerView.ViewHolder {
public
TextView cityNameTV, phoneTV, addrTV;
public
ViewHolder(View v) {
super
(v);
cityNameTV = (TextView) v.findViewById(R.id.city_name);
phoneTV = (TextView) v.findViewById(R.id.city_phone);
addrTV = (TextView) v.findViewById(R.id.city_addr);
}
}
}
</cityinfobean></cityinfobean></cityinfobean></cityinfobean></recyclerviewadapter.viewholder>
recycler_layout.xml:
123456<!--?xml version=
1.0
encoding=utf-
8
?-->
<linearlayout android:layout_height=
"match_parent"
android:layout_width=
"match_parent"
android:orientation=
"vertical"
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
</android.support.v7.widget.recyclerview></linearlayout>
二、使用CardView
CardView是Google在support v7包中提供了另一个全新组件,可以很方便的实现“卡片式布局”(具有投影/圆角 的立体效果)。CardView继承自FrameLayout,因此如果内部需要互不重叠的放置多个组件时,可能需要再嵌套一个LinearLayout或RelativeLayout等。
效果图:
布局文件:
123456789101112131415<linearlayout android:layout_height=
"wrap_content"
android:layout_width=
"match_parent"
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:card_view=
"http://schemas.android.com/apk/res-auto"
>
<linearlayout android:layout_height=
"match_parent"
android:layout_margin=
"6dp"
android:layout_width=
"match_parent"
android:orientation=
"vertical"
>
<imageview android:contentdescription=
"@null"
android:layout_height=
"wrap_content"
android:layout_width=
"wrap_content"
android:src=
"@drawable/ic_launcher"
>
<textview android:id=
"@+id/info_text"
android:layout_height=
"match_parent"
android:layout_width=
"match_parent"
android:text=
"@string/example_text"
android:textsize=
"18sp"
>
</textview></imageview></linearlayout>
</android.support.v7.widget.cardview>
</linearlayout>
cardCornerRadius:圆角大小;
cardElevation:投影的深度;
cardBackgroundColor:卡片的背景色。