chromium的标签栏是一种波浪式的风格,如下图所示,为了更改风格,需要先了解它的绘制原理:
在src\chrome\browser\ui\views\tabs\tab_strip.cc中,有一个参数kTabHorizontalOffset。在每个标签按钮进行布局的时候,相邻的标签的边界会重叠在一起。
如果啥也不管直接进行绘制的话,就会显示如下的效果。
为了显示出边界效果,会使用两个src\chrome\app\theme\default_100_percent\common目录下的掩码文件tab_alpha_left.png、tab_alpha_right.png,画出边缘形状。
这两文件把需要显示的像素填充成(255,255,255,255)不绘制的部分填充成(255,255,255,0),这样绘制出来的就会有预定的形状了。
按钮在选中和非选中状态下的边界是不一样的,在非选中状态下,按钮底部会有一条分隔线,而选中的情况下是没有的,所以tab_inactive_center.png、tab_inactive_left.png、tab_inactive_right.png这三个文件的倒数第二行的像素是黑实线,而tab_active_center.png、tab_active_left.png、tab_active_right.png这三个文件的最底端是没有黑实线。为了与主题配合。
注:这六个文件除了边界填充为黑色,其它部分全是透明,否则在绘制时会把图片上的色彩绘制出来,在更改主题时色彩可能会不协调。由于标签栏的绘制框底部与工具栏的像素框顶部有一个像素的重叠,所以绘制底部边界时,会把倒数第二行的像素填成黑实线,而不是倒数第一行。这个重叠通过kToolbarOverlap设置。
制作好这些图标,并调整kTabHorizontalOffset的值,就能实现不同效果的标签栏。如图是修改成直方效果的标签栏。
修改了标签栏后,新标签的按钮也需要进行相应的调整。原始的按钮图样为:
按钮的图样需要考虑三种状态,这三种状态对应普通状态、鼠标停留在按钮上时、按钮被按下时。对应的图标在src\chrome\app\theme\theme_resources.grd中定义,
<if expr="toolkit_views or is_macosx or is_ios">
<structure type="chrome_scaled_image" name="IDR_NEWTAB_BUTTON" file="common/newtab_normal.png" />
<structure type="chrome_scaled_image" name="IDR_NEWTAB_BUTTON_H" file="common/newtab_hover.png" />
<structure type="chrome_scaled_image" name="IDR_NEWTAB_BUTTON_P" file="common/newtab_pressed.png" />
</if>
为了跟主题配合,这几个图标最好也是透明底。
图标的文件位于src\chrome\app\theme\default_100_percent\common目录下。当替换这些文件后,会发现实现的效果会和图片定义的有些不一致。这是由于按钮的绘制并不是完全按照图片定义的样式绘制导致,chrome原有的绘制只用到了IDR_NEWTAB_BUTTON_P和IDR_NEWTAB_BUTTON两个图标,需要修改绘制的代码,不同的状态直接返回不同状态的图片就可以了。
src\chrome\browser\ui\views\tabs\tab_strip.cc
gfx::ImageSkia NewTabButton::GetImageForState(
views::CustomButton::ButtonState state,
float scale) const {
int overlay_id;
if (state == views::CustomButton::STATE_PRESSED) {
overlay_id = IDR_NEWTAB_BUTTON_P;
} else {
if (state == views::CustomButton::STATE_HOVERED) {
overlay_id = IDR_NEWTAB_BUTTON_H;
} else {
overlay_id = IDR_NEWTAB_BUTTON;
}
}
gfx::ImageSkia* overlay = GetThemeProvider()->GetImageSkiaNamed(overlay_id);
gfx::Canvas canvas(
gfx::Size(overlay->width(), overlay->height()),
scale,
false);
const int kGlassFrameOverlayAlpha = 178;
const int kOpaqueFrameOverlayAlpha = 230;
uint8 alpha = ShouldWindowContentsBeTransparent() ?
kGlassFrameOverlayAlpha : kOpaqueFrameOverlayAlpha;
canvas.DrawImageInt(*overlay, 0, 0, alpha);
return gfx::ImageSkia(canvas.ExtractImageRep());
}
本人使用的图标如下
实现完成后的效果为