华为手机兼容性处理

华为Toast显示

因为华为系统对Toast进行了定制,所以如果两个触发时机非常接近的Toast,华为只会显示一个。例:

1
2
Toast.makeText(this, "this is toast 1", Toast.LENGTH_SHORT).show();
Toast.makeText(this, "this is toast 2", Toast.LENGTH_Long).show();

则华为手机只会显示最后一个toast。

背景绘制

最近在做项目的时候,需要给一个Fragment的背景绘制上倾斜的水印,水印的绘制通过自定义drawable,重写draw()方法生成一张drawable,然后用setBackground()设置为背景。

水印生成的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public class WarterMarkDrawable extends Drawable {

Context context;
String markStr = "";
int textColor = Color.BLACK;
int textSize = 30;
int backgroundColor = Color.WHITE;
int rotate = -30;
int alpha = 41;
int density = 10;
private Paint paint = new Paint();

public WarterMarkDrawable(Context context, String watermark) {
this.context = context;
this.markStr = watermark;
this.textColor = ContextCompat.getColor(context, R.color.water_mark_color);
this.textSize = 42;
this.backgroundColor = ContextCompat.getColor(context, R.color.background_6_0);
this.rotate = -20;
this.density = 7;
}

@Override
public void draw(@NonNull Canvas canvas) {
int width = getBounds().right + 200;
int height = getBounds().bottom + 200;

canvas.drawColor(backgroundColor);
paint.setColor(textColor);
paint.setAntiAlias(true);
paint.setTextSize(textSize);
canvas.rotate(rotate);
canvas.save();
float textWidth = paint.measureText(markStr);
int index = 0;
int sheight = 100;
float swidth = textWidth * 2 + 20;
for (int positionY = sheight; positionY <= height; positionY += sheight) {
float fromX = -width + (index++ % 2) * textWidth;
for (float positionX = fromX; positionX < width; positionX += swidth) {
canvas.drawText(markStr, positionX, positionY, paint);
}
}
canvas.restore();
}

@Override
public void setAlpha(int i) {

}

@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {

}

@Override
public int getOpacity() {
return PixelFormat.UNKNOWN;
}
}

一开始这方法生成的drawable都没有问题,也没有造成内存泄露。直到遇到了华为MT7 4.4系统,用这方法生成水印背景,导致所有设置该背景的Fragment内容全部变成倾斜。在前辈的帮助下,定位问题,可能是在draw()方法里面绘制背景的时候,用canvas.rotate(rotate);对整个画布进行旋转,华为MT7 4.4系统应该把所有的内容(包括listview等)都绘制在canvas上面,是得在进行选择的时候,不是对该背景的canvas进行旋转,而是旋转了所有的view。

更新:经过多个机型匹配发现,这是Android4.4手机系统都会有的问题

前辈说在onDraw()函数加canvas.save()和canvas.restore()可以解决问题,还没验证

对生成自定义drawable进行了改造。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
public class WarterMarkDrawable extends Drawable {

Context context;
String markStr = "";
int textColor = Color.BLACK;
int textSize = 30;
int backgroundColor = Color.WHITE;
int rotate = -30;
int alpha = 41;
int density = 10;
private Paint paint = new Paint();
Bitmap bitmap = null;

public WarterMarkDrawable(Context context, String watermark) {
this.context = context;
this.markStr = watermark;
this.textColor = ContextCompat.getColor(context, R.color.water_mark_color);
this.textSize = 42;
this.backgroundColor = ContextCompat.getColor(context, R.color.background_6_0);
this.rotate = -20;
this.density = 7;
}

public WarterMarkDrawable(Context context, String watermark, Bitmap bitmap) {
this.context = context;
this.markStr = watermark;
this.textColor = ContextCompat.getColor(context, R.color.water_mark_color);
this.textSize = 42;
this.backgroundColor = ContextCompat.getColor(context, R.color.background_6_0);
this.rotate = -20;
this.density = 7;
this.bitmap = bitmap;
}


@Override
public void draw(@NonNull Canvas canvas) {
int width;
int height;

// 只有mt7才会进入该方法 在外面将水平drawable转换成bitmap后再旋转bitmap 绘制在canvas上
if (bitmap != null) {
Matrix matrix = new Matrix();
// 根据中点旋转
matrix.postRotate(rotate, bitmap.getWidth() / 2, bitmap.getHeight() / 2);
canvas.drawBitmap(bitmap, matrix, paint);
} else {
// 华为MT7不能直接旋转画布 先生成一个水平的不旋转的drawable
if (DeviceInfo.MODEL.getModel().contains("HUAWEI MT7")) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
width = wm.getDefaultDisplay().getWidth() + 200;
height = wm.getDefaultDisplay().getHeight() + 200;
} else {
// 普通系统走正常的生成水印代码
width = getBounds().right + 200;
height = getBounds().bottom + 200;
canvas.rotate(rotate);
}
canvas.drawColor(backgroundColor);
paint.setColor(textColor);
paint.setAntiAlias(true);
paint.setTextSize(textSize);
canvas.save();
float textWidth = paint.measureText(markStr);
int index = 0;
int sheight = 100;
float swidth = textWidth * 2 + 20;
for (int positionY = sheight; positionY <= height; positionY += sheight) {
float fromX = -width + (index++ % 2) * textWidth;
for (float positionX = fromX; positionX < width; positionX += swidth) {
canvas.drawText(markStr, positionX, positionY, paint);
}
}
canvas.restore();
}
}

@Override
public void setAlpha(int i) {

}

@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {

}

@Override
public int getOpacity() {
return PixelFormat.UNKNOWN;
}
}

增加了一个bitmap成员,在华为MT7 系统上,先生成一个不旋转的水平的水印背景drawable,将改drawable转化成bitmap,然后对该bitmap进行旋转,绘制在canvas上,避免了旋转canvas。

在外围调用的时候

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 先生成一张drawable 若是华为MT7系统 则生成的是不旋转的水平drawable
WarterMarkDrawable waterDrawable = new WarterMarkDrawable(context, watermark);

// 华为MT7不能直接在画布上旋转
if (DeviceInfo.MODEL.getModel().contains("HUAWEI MT7")) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
// 将drawable转化成bitmap
int width = wm.getDefaultDisplay().getWidth() + 200;
int height = wm.getDefaultDisplay().getHeight() + 200;
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
waterDrawable.draw(canvas);
// 再生成一次drawable,这次传入bitmap后,会将改bitamp选择并绘制在canvas上,而不是选择canvas
WarterMarkDrawable bitmapDrawable = new WarterMarkDrawable(context, watermark, bitmap);
}
// ... 将waterDrawable 或 bitmapDrawable设置成view的背景,即完成水印背景的绘制

总结:简直被华为系统坑爆了。。。

0%