How to support scroll bar in webkit of android platform

前话:

    webkit是一个复杂的程序,复杂意味着简单,也是最基本的东西,下面是我对webkit在android中不支持scrollbar而写的文章,是说为什么不支持,以及怎么解决,我已经完全解决了这个问题。并在android 2.0中实现。 文章当初是用英文写的,因为也想让国外的朋友能读到,但没有国外的blog,也就先发在这里了。

    文章并没有写全,因为最近事情比较多,我会慢慢写完。

    原谅我的语法错误,拼写错误!

 

 

How to support scroll bar in webkit of android platform

Jian Jun

 

    In platform such as qt , webkit support scrollbar , as well as google’s chrom ,which use webkit as it’s web enghine . but google’s another system ,android, haven’t support scroll bar . it just let the overflow area big enough to show all the things in the scroll bar . in this text , I will show you how to add some code to webkit to let android do support scroll bar. here we go.

1 How scroll bar come from

   Scroll bar comes from css tags “overflow”. Bellow it is a html text.

it’s DIV ‘css attribute is define at style mydiv , it show that , the div area in the html page , which is a square area ,with width of 100px , height of 100px,it’s border is line of style solid red . after it overflow attribute , it’s define as “scroll” , which mean , if the div tag have some child html tags ,and child tags is too big to let div to hold it in it’s area which is 100*100 at the example ,the div will show a scroll bar , so user can use it to view all of it child . the overflow have some other attribute , we don’t show dettel it at here , cause just it’s “scroll” value will generate a scroll bar .

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">

<HEAD>

  <TITLE>Anonymous text interrupted by a block</TITLE>

  <STYLE type="text/css">

    .mydiv { 

    width: 100px;

    height: 100px;

    border: solid red;

    border-width: 3px;

    overflow:scroll

    }

  </STYLE>

</HEAD>

<BODY >

  <div class=" mydiv ">

    <a>china is a great country , every people like it very much</a>

  </div>

</BODY>

</HTML>

 

2 How webit draw the scroll bar in other platform

   Before we start , we should know how the webkit draw scroll bar in web page ,then we can do with android . though android haven’t draw it ,but in others platform ,such as qt , it support ,so, let’s we first insight how qt draw the scroll bar .

2.1  when to draw the scroll bar .

  In the RenderBlock Class , there is a method called paint() . bellow is last line of this method . when the program goes there , it start to draw scrolls . but in android , it never goes there ( hasOverflowClip() always return false ) .i will tell how to let it return true when necessary .

 

    // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with

     // z-index.  We paint after we painted the background/border, so that the scrollbars will

    // sit above the background/border.

    if (hasOverflowClip() && style()->visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground) && shouldPaintWithinRoot(paintInfo))

        layer()->paintOverflowControls(paintInfo.context, tx, ty, paintInfo.rect);

 

the layer() above refer to RenderLayer .let view it .

 

void RenderLayer::paintOverflowControls(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)

{

    // Don't do anything if we have no overflow.

    if (!renderer()->hasOverflowClip())

        return;

   

    // Move the scrollbar widgets if necessary.  We normally move and resize widgets during layout, but sometimes

    // widgets can move without layout occurring (most notably when you scroll a document that

    // contains fixed positioned elements).

    positionOverflowControls(tx, ty);

 

    // Now that we're sure the scrollbars are in the right place, paint them.

    if (m_hBar)

        m_hBar->paint(context, damageRect);

    if (m_vBar)

        m_vBar->paint(context, damageRect);

 

    // We fill our scroll corner with white if we have a scrollbar that doesn't run all the way up to the

    // edge of the box.

    paintScrollCorner(context, tx, ty, damageRect);

   

    // Paint our resizer last, since it sits on top of the scroll corner.

    paintResizer(context, tx, ty, damageRect);

}

 

In the paintOverflowControls method , there is a call to positionOverflowControls(tx, ty) , this method is very important  bellow is it’s content .

 

  void RenderLayer::positionOverflowControls(int tx, int ty)

{

    if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))

        return;

   

    RenderBox* box = renderBox();

    if (!box)

        return;

 

    IntRect borderBox = box->borderBoxRect();

    IntRect scrollCorner(scrollCornerRect(this, borderBox));

    IntRect absBounds(borderBox.x() + tx, borderBox.y() + ty, borderBox.width(), borderBox.height()); // borderBox 转换 成屏幕上的 绝对

    if (m_vBar)               // 置垂直 滚动 条的矩形

        m_vBar->setFrameRect(IntRect(absBounds.right() - box->borderRight() - m_vBar->width(),

                                     absBounds.y() + box->borderTop(),

                                     m_vBar->width(),

                                     absBounds.height() - (box->borderTop() + box->borderBottom()) - scrollCorner.height()));

 

    if (m_hBar)               // 置水平 滚动 条的矩形

        m_hBar->setFrameRect(IntRect(absBounds.x() + box->borderLeft(),

                                     absBounds.bottom() - box->borderBottom() - m_hBar->height(),

                                     absBounds.width() - (box->borderLeft() + box->borderRight()) - scrollCorner.width(),

                                     m_hBar->height()));

   

    if (m_scrollCorner)

        m_scrollCorner->setFrameRect(scrollCorner);

    if (m_resizer)

        m_resizer->setFrameRect(resizerCornerRect(this, borderBox));

}

 

m_vBar refers to vertical scroll bar , m_hBar refers to horizontal scroll bar . m_scrollCorner refers to the square corner between vertical scroll bar and horizontal scroll bar ,it’s at bottown right often . what this function do is to compute and set the three widget’s position in the web page . after the coordinate is set , the paintOverflowControls   method will call m_vBar and the m_hBar ‘s paint method to draw the draw bar .now ,let say what’s the inside of Scrollbar’s (the Class of m_vBar and the m_hBar) paint method .

Scrollbar is a class defined at WebCore/platform directory . so it’s platform depended. Now let’s view it’s paint() function .

 

void Scrollbar::paint(GraphicsContext* context, const IntRect& damageRect)

{

    if (context->updatingControlTints() && theme()->supportsControlTints()) {

        invalidate();

        return;

    }

       

    if (context->paintingDisabled() || !frameRect().intersects(damageRect))

        return;

 

    if (!theme()->paint(this, context, damageRect))

        Widget::paint(context, damageRect);

}

 

Oh! This function is clear . it call one of another two paint method instead,paint of ScrollbarTheme class and paint of Widget Class . as we read the code , we know if   ScrollbarTheme’s paint method return false , it will call Widget’s paint method .

Let’s view ScrollbarTheme’s paint method , we are more closer to the reality ! ScrollbarTheme is a platform depended Class as well , in qt , it’s realized  in ScrollbarThemeQt   Sub Class . bellow is it’s paint method .

bool ScrollbarThemeQt::paint(Scrollbar* scrollbar, GraphicsContext* graphicsContext, const IntRect& damageRect)

{

    if (graphicsContext->updatingControlTints()) {

       scrollbar->invalidateRect(damageRect);

       return false;

    }

                                      

    StylePainter p(this, graphicsContext);

    if (!p.isValid())

      return true;

 

    p.painter->save();

    QStyleOptionSlider* opt = styleOptionSlider(scrollbar, p.widget);

 

    p.painter->setClipRect(opt->rect.intersected(damageRect), Qt::IntersectClip);

 

#ifdef Q_WS_MAC

    p.drawComplexControl(QStyle::CC_ScrollBar, *opt);

#else

    const QPoint topLeft = opt->rect.topLeft();

    p.painter->translate(topLeft);

    opt->rect.moveTo(QPoint(0, 0));

 

    // The QStyle expects the background to be already filled

    p.painter->fillRect(opt->rect, opt->palette.background());

 

    p.drawComplexControl(QStyle::CC_ScrollBar, *opt);

    opt->rect.moveTo(topLeft);

#endif

    p.painter->restore();

 

    return true;

}

 

We needn’t to read this code detailed . it just call the Qt’s graphic method to draw the scroll bar . finally it return true .as it return true,in ScrollBar’s paint method ,it didn’t call Widget’s paint method anymore .

 

3 How android avoid to draw the scroll bar

  I mentioned that in platform of android ,it’s just let the overflow area bit enough to ensure all the content in the overflow area displayed . it’s done at ScrollView . another Class in the WebCore/platform directory .

 

1   let scrollbar off:

   In WebCore/platform/ScrollViewAndroid.cpp file , there is a method named  platformScrollbarModes , it set both of vertical and horizontal scroll bar mode to ScrollbarAlwaysOff .

 

2  Don’t generate a render layer for overflow

   In platform such as qt , the webkit generate a render layer (a RenderLayer Class) for the overflow . but android didn’t do se it .

  

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值