我们希望可以自定义Toolbar,实现一些特定的功能,android.support.v7.widget.Toolbar正好完成这些工作
首先看一下我们预期的效果图:
先看一下Toolbar的布局
这里背景的渐变色可以通过定义如下xml来实现,同时将Toolbar的background设置为该xml
为了使标题可以居中显示,在Toolbar中添加了一个TextView用来显示标题,并且需要在Activity中将原标题隐藏
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayUseLogoEnabled(false);
在DrawerLayout中,我们新建ActionBarDrawerToggle并且传入toolbar,我们希望更改Toolbar的导航按钮图标,注意这个操作必须在setSupportActionBar和addDrawerListener操作之后
Resources resources = MainActivity.this.getResources();
Drawable drawable = resources.getDrawable(R.drawable.image);
int size = 44;
CircleDrawable circleDrawable = new CircleDrawable(drawable, MainActivity.this, size);
toolbar.setNavigationIcon(circleDrawable);
CircleDrawable是我自己定义为了绘制原型图标的Drawable
package com.sdu.runningsdu.Utils;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.TypedValue;
/**
* Created by FTDsm on 2018/6/7.
*/
public class CircleDrawable extends Drawable {
private Bitmap bitmap;
private BitmapShader bitmapShader;
private Paint paint;
// 圆心
private float cx, cy;
// 半径
private float radius;
public CircleDrawable(Drawable drawable, Context context, int size) {
size = dip2px(context, size);
drawable = zoomDrawable(drawable, dip2px(context, size), dip2px(context, size));
this.bitmap = drawableToBitmap(drawable);
bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(bitmapShader);
cx = size / 2;
cy = size / 2;
radius = size / 2;
}
@Override
public void draw(@NonNull Canvas canvas) {
canvas.drawCircle(cx, cy, radius, paint);
}
/**
* 缩放Drawable
* */
private Drawable zoomDrawable(Drawable drawable, int w, int h) {
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
Bitmap oldbmp = drawableToBitmap(drawable);
Matrix matrix = new Matrix();
float scaleWidth = ((float) w / width);
float scaleHeight = ((float) h / height);
matrix.postScale(scaleWidth, scaleHeight);
Bitmap newbmp = Bitmap.createBitmap(oldbmp, 0, 0, width, height,
matrix, true);
return new BitmapDrawable(null, newbmp);
}
/**
* Drawable转Bitmap
* */
private Bitmap drawableToBitmap(Drawable drawable) {
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
Bitmap.Config cOnfig= drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565;
Bitmap bitmap = Bitmap.createBitmap(width, height, config);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, width, height);
drawable.draw(canvas);
return bitmap;
}
/**
* dp to px
* */
private int dip2px(Context context, float dipValue) {
Resources resources = context.getResources();
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dipValue, resources.getDisplayMetrics());
}
public static int dip2px1(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
private int dip2px2(Context context,float dpValue){
float scale=context.getResources().getDisplayMetrics().density;
return (int)(dpValue*scale+0.5f);
}
@Override
public void setAlpha(int alpha) {
paint.setAlpha(alpha);
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
paint.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
工具栏右侧的菜单可以通过menu设置,以下代码可以完成menu的初始化和无法同时显示图标和文字的问题
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.action_menu, menu);
return super.onCreateOptionsMenu(menu);
}
/**
* 解决Toolbar中Menu无法同时显示图标和文字的问题
* */
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
if (menu != null) {
if (menu.getClass().getSimpleName().equalsIgnoreCase("MenuBuilder")) {
try {
Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
method.setAccessible(true);
method.invoke(menu, true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return super.onMenuOpened(featureId, menu);
}
溢出菜单可以通过定义style来配置,并且要将其添加到Activity Theme style中
弹出菜单可以通过setOnMenuItemClickListener设置点击事件
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
int id = item.getItemId();
Intent intent;
switch (id) {
case R.id.item_create_group:
break;
case R.id.item_add_friend:
break;
case R.id.item_scan:
break;
case R.id.item_help_and_feedback:
break;
}
return true;
}
});
最后如果Toolbar遮挡了content_main.xml,在其被遮挡的布局设置app:layout_behavior属性即可
app:layout_behavior="@string/appbar_scrolling_view_behavior"