Android4.4以上推出了Toolbar,改变程序的style属性就可以给手机的标题栏填充颜色,可以是你设置好的系统的主题色,也可以是自己填充的颜色,其实这个效果在iOS早就有了,但在Android中还是很少见的。在iOS中,最常见的Navigationbar的效果就是一个转场动画(多出现于两个界面切换的时候),一个就是随着手势滑动背景渐变(多出现于详情页)。今天我们就来实现下大多出现于详情页的这个渐变效果的标题栏。
具体效果见:点击打开链接
接下来我们就来实现这个效果。
首先,我们要先把手机上面的状态栏的颜色背景隐藏掉,在这里会有一个坑,在小米和魅族手机里,好想说是MIUI6以上,上面状态栏上的时间啊什么的文字默认的颜色是白色,如果你的Toolbar的背景是相对深颜色的话,是没有问题的,但是如果你的Toolbar是相对浅的背景颜色,那么很可能这些时间文字会显示不出来,那么就要修改上面状态栏的颜色了。具体可以参考这篇:点击打开链接
先在style里设置,这是我的style.xml:
接下来我们就要把状态栏设置为透明:
private void setTranslucentWindows(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//透明状态栏
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
以下是我写的标题栏的布局文件:
将标题栏的布局文件引入到我们界面的布局文件里,我们是相当于在recyclerView的header上叠加了一层透明的标题栏,这里对recyclerView的adapter的所有操作我都集成了一个通用格式来进行操作,方便很多。我给recyclerView添加了一个header,在这里为了简便,用imageView来代替了轮播图。为了达到渐变的效果,我们要去监听滑动事件,是否滑动到imageView的高度,也就是把imageView隐藏,当正好隐藏的时候标题栏的文字将出现(这个一般看交互,如果大图下面有标题,一般建议标题覆盖以后,标题栏上的标题再显示),当前的y与整体要滑动距离的百分比来控制标题栏的背景透明度。在这里要注意,当onCreate方法的时候,一个view的getMeasuredHeight()方法或者宽度的方法获得的都是0,因为这个时候你的view还没有draw上去,只有当onCreate方法执行完了以后,控件才会被onMeasure。所以有两种策略,一种是我以下代码实现的,等view的onMeasure好了以后再去调用方法,还有一种是去注册一个ViewTreeObserver的监听回调,具体大家可以去自行百度。ok,下面贴上Activity里的代码:
public class MainActivity extends AppCompatActivity {
@Bind(R.id.recycler)
RecyclerView recyclerView;
@Bind(R.id.layout_toolbar_my_container)
RelativeLayout layoutToolBarBackground;
@Bind(R.id.text_toolbar_index)
TextView centerText;
private ArrayList modelList = new ArrayList<>();
private MyRecyclerAdapter adapter;
private LinearLayoutManager layoutManager;
private int itemIndex;
private ToolBarBackgroundController toolBarBackgroundController;
private int anchorHeight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTranslucentWindows(this);
ButterKnife.bind(this);
layoutManager = new LinearLayoutManager(this.getApplicationContext());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST,
R.drawable.devide_line_gray, 0));
initHead();
initData();
initView();
}
private void initHead() {
layoutToolBarBackground.setBackgroundColor(Color.TRANSPARENT);
toolBarBackgroundController = new ToolBarBackgroundController(layoutToolBarBackground);
}
public class ToolBarBackgroundController {
private View layoutToolbar;
public ToolBarBackgroundController(View layoutToolbar) {
this.layoutToolbar = layoutToolbar;
layoutToolbar.setBackgroundColor(Color.TRANSPARENT);
}
public void setTransparent(boolean needTransparent) {
if (needTransparent) {
//变透明
centerText.setVisibility(View.GONE);
} else {
layoutToolbar.setBackgroundColor(getResources().getColor(R.color.base));
centerText.setVisibility(View.VISIBLE);
}
}
}
private void setTranslucentWindows(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//透明状态栏
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
private int getStatusBarHeight(Context context) {
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
return context.getResources().getDimensionPixelSize(resourceId);
} else return 0;
}
private void initData() {
for (int i = 0; i < 20; i++) {
Model model = new Model();
model.setName("jjq" + i);
model.setDesc("哈哈哈哈哈哈哈哈");
modelList.add(model);
}
}
private void initView() {
if (adapter == null) {
adapter = new MyRecyclerAdapter();
} else {
adapter.notifyDataSetChanged();
}
adapter.initData(false);
adapter.appendData(modelList);
recyclerView.setAdapter(adapter);
recyclerView.addOnScrollListener(new OnScrollColorChangeListener());
}
private class OnScrollColorChangeListener extends RecyclerView.OnScrollListener {
private boolean isTrans = true;
private int y = 0;
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (anchorHeight != 0) {
y += dy;
boolean needTrans = y <= anchorHeight;
if (needTrans != isTrans) {
isTrans = needTrans;
toolBarBackgroundController.setTransparent(needTrans);
} else {
if (y / anchorHeight < 1) {
layoutToolBarBackground.setBackgroundColor(getResources().getColor(R.color.base));
layoutToolBarBackground.getBackground().setAlpha((int) ((float) y / anchorHeight * 255));
}
}
}
}
}
private class MyRecyclerAdapter extends RecyclerView.Adapter {
private final int TYPE_HEADER = 0x1000;
private final int TYPE_NORMAL = 0x2000;
private final int TYPE_FOOTER = 0x3000;
private final int TYPE_EMPTY = 0x4000;
private final int TYPE_THEME = 0x5000;
private ArrayList itemInfos;
private boolean needFooter = false;
private boolean hasFooter = false;
public class MyItemInfo {
int type;
Model model;
public MyItemInfo(int type, Model model) {
this.type = type;
this.model = model;
}
}
public MyRecyclerAdapter() {
itemInfos = new ArrayList<>();
}
public void initData(boolean needFooter) {
this.needFooter = needFooter;
this.hasFooter = false;
int oldCount = itemInfos.size();
itemInfos.clear();
this.notifyItemRangeRemoved(0, oldCount);
itemInfos.add(new MyItemInfo(TYPE_HEADER, null));
//itemInfos.add(new MyItemInfo(TYPE_FOOTER, null));
//this.notifyItemRangeInserted(0, 2);
}
public void appendData(ArrayList models) {
int oldCount = itemInfos.size();
if (hasFooter) {
itemInfos.remove(oldCount - 1);
this.notifyItemRemoved(oldCount - 1);
oldCount--;
}
int size = models.size();
for (int i = 0; i < size; i++) {
itemInfos.add(new MyItemInfo(TYPE_NORMAL, models.get(i)));
}
this.notifyItemRangeInserted(oldCount + 1, size);
if (needFooter) {
itemInfos.add(new MyItemInfo(TYPE_FOOTER, null));
this.notifyItemInserted(itemInfos.size() - 1);
hasFooter = true;
}
}
public void removeFooter() {
int oldCount = itemInfos.size();
itemInfos.remove(oldCount - 1);
notifyItemRemoved(oldCount - 1);
}
public void appendEmptyView() {
int oldCount = itemInfos.size();
if (hasFooter) {
itemInfos.remove(oldCount - 1);
this.notifyItemRemoved(oldCount - 1);
oldCount--;
}
itemInfos.add(new MyItemInfo(TYPE_EMPTY, null));
notifyItemRangeInserted(oldCount, 1);
}
@Override
public int getItemViewType(int position) {
return itemInfos.get(position).type;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = null;
switch (viewType) {
case TYPE_HEADER:
view = inflater.inflate(R.layout.layout_main_recycler_head, parent, false);
return new MyHeaderItemHolder(view, MainActivity.this);
case TYPE_NORMAL:
view = inflater.inflate(R.layout.layout_list_item, parent, false);
return new NormalViewHolder(view);
case TYPE_EMPTY:
return null;
case TYPE_FOOTER:
return null;
default:
return null;
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) {
switch (viewHolder.getItemViewType()) {
case TYPE_NORMAL:
NormalViewHolder normalViewHolder = (NormalViewHolder) viewHolder;
normalViewHolder.setContent(itemInfos.get(i).model, i);
break;
case TYPE_HEADER:
MyHeaderItemHolder headerViewHolder = (MyHeaderItemHolder) viewHolder;
headerViewHolder.setContent();
break;
case TYPE_FOOTER:
case TYPE_EMPTY:
break;
default:
break;
}
}
@Override
public int getItemCount() {
return itemInfos.size();
}
private class EmptyItemHolder extends RecyclerView.ViewHolder {
public EmptyItemHolder(View itemView) {
super(itemView);
}
}
private class MyHeaderItemHolder extends RecyclerView.ViewHolder {
private Context context;
private ImageView imageView;
public MyHeaderItemHolder(View itemView, Context context) {
super(itemView);
this.context = context;
imageView = (ImageView) itemView.findViewById(R.id.img_main_recycler_head_banner);
imageView.post(new Runnable() {
@Override
public void run() {
anchorHeight = imageView.getMeasuredHeight() - layoutToolBarBackground.getMeasuredHeight();
}
});
}
//填充头部内容
public void setContent() {
}
}
private class NormalViewHolder extends RecyclerView.ViewHolder {
private Model model;
private TextView nameView;
private TextView descView;
public NormalViewHolder(View itemView) {
super(itemView);
nameView = (TextView) itemView.findViewById(R.id.text_list_item_name);
descView = (TextView) itemView.findViewById(R.id.text_list_item_desc);
itemView.setOnClickListener(new OnItemClickListener());
}
public void setContent(Model model, int index) {
this.model = model;
nameView.setText(model.getName());
descView.setText(model.getDesc());
itemIndex = index;
}
private class OnItemClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
}
}
}
private class FooterViewHolder extends RecyclerView.ViewHolder {
public FooterViewHolder(View itemView) {
super(itemView);
}
}
}
}
ok,到这里demo就搞定了!当然如果你的标题栏上的文字太长的话,你也可以自己给textView加上跑马灯效果,很简单,不知道的人可以自行去谷歌百度,记得给textView加上焦点就可以了。
项目地址:点击打开链接