<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4005196037721136658</id><updated>2011-06-16T13:38:16.336-07:00</updated><title type='text'>Radioal</title><subtitle type='html'>code snippets, examples, and tricks for software developers</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://radioal.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4005196037721136658/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://radioal.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Fabrizio</name><uri>http://www.blogger.com/profile/06857225138675289185</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/-YvNiP-wwJp0/TXHThNx0frI/AAAAAAAABSo/PNPSjmZx8LY/s220/IMAG0073.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>2</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4005196037721136658.post-3570380417063825832</id><published>2011-05-21T23:18:00.000-07:00</published><updated>2011-05-22T00:38:58.194-07:00</updated><title type='text'>Stretching Rows in Android TableLayout</title><content type='html'>&lt;a href="http://2.bp.blogspot.com/-RsiMYtJZFWQ/Tdi1RRcy2hI/AAAAAAAABU4/o8bVCHxSG9o/s1600/stretchedrows.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 295px;" src="http://2.bp.blogspot.com/-RsiMYtJZFWQ/Tdi1RRcy2hI/AAAAAAAABU4/o8bVCHxSG9o/s320/stretchedrows.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5609432644236532242" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Google's Android SDK allows developers to architect a UI from the comfort and safety of XML.  This is done by creating a layout resource *.xml file under the /res/layout directory of the project.&lt;br /&gt;&lt;br /&gt;Hand-coded UIs can be difficult to maintain and update.  For example, grid-based layouts can become complex and unwieldy as they evolve.  An XML-based layout tries to address these problems, and the Android Developers forum provides helpful &lt;a href="http://developer.android.com/resources/tutorials/views/index.html"&gt;tutorials&lt;/a&gt; on the subject.&lt;br /&gt;&lt;br /&gt;As I studied the layout tutorials, I hoped to use percentage values for the android:layout_height and android:layout_width attributes to evenly stretch buttons in a TableLayout.  Since percentage values are not allowed however, another solution was required.&lt;br /&gt;&lt;br /&gt;The android:stretchColumns attribute addresses part of the problem.  For example, a 3-column table layout can be evenly laid out--horizontally, at least--by setting android:stretchColumns="0,1,2".  But the rows are not stretched and no corresponding android:stretchRows exists.&lt;br /&gt;&lt;br /&gt;The solution actually depends &lt;span style="font-style:italic;"&gt;android:stretchColumns&lt;/span&gt; as well as a few other layout attributes and can be outlined as follows:&lt;ol&gt;&lt;li&gt;give the top-level &lt;span style="font-weight:bold;"&gt;TableLayout&lt;/span&gt; node in the XML file an android:weightSum value corresponding to the number of rows in the layout.  If the layout has 3 rows, then set &lt;span style="font-style:italic;"&gt;android:weightSum=3&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;give each &lt;span style="font-weight:bold;"&gt;TableRow&lt;/span&gt; node within the &lt;span style="font-weight:bold;"&gt;TableLayout&lt;/span&gt; an android:layout_weight attribute and set the value such that the sum of all the &lt;span style="font-style:italic;"&gt;android:layout_weigh&lt;/span&gt;t values from all the &lt;tablerow&gt; nodes within &lt;tablelayout&gt; is equal to the value of &lt;span style="font-style:italic;"&gt;android:weightSum&lt;/span&gt; in the containing &lt;span style="font-weight:bold;"&gt;TableLayout&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;set the &lt;span style="font-style:italic;"&gt;android:layout_height&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;android:layout_width&lt;/span&gt; of the items inside the &lt;span style="font-weight:bold;"&gt;TableRow&lt;/span&gt; elements ( in my case, a &lt;span style="font-weight:bold;"&gt;Button&lt;/span&gt; element ), to "&lt;span style="font-style:italic;"&gt;fill_parent&lt;/span&gt;."&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;With this approach, I was able to achieve the above pictured layout without hard-coding any numeric values in the XML for height or width.  Here is the XML that I used as a layout resource in my test Android app:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;br /&gt;&lt;TableLayout xmlns:android="http://schemas.android.com/apk/res/android"&lt;br /&gt;    android:layout_width="fill_parent"&lt;br /&gt;    android:layout_height="fill_parent"&lt;br /&gt;    android:weightSum="3"&lt;br /&gt;    android:stretchColumns="0,1,2"&gt;&lt;br /&gt;&lt;br /&gt;    &lt;TableRow android:layout_weight="1"&gt;&lt;br /&gt;        &lt;Button&lt;br /&gt;        android:id="@+id/pad1"&lt;br /&gt;        android:layout_width="wrap_content"&lt;br /&gt;        android:layout_height="wrap_content"&lt;br /&gt;        android:text="1"&gt;&lt;br /&gt; &lt;/Button&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;Button&lt;br /&gt;        android:id="@+id/pad2"&lt;br /&gt;        android:layout_width="wrap_content"&lt;br /&gt;        android:layout_height="wrap_content"&lt;br /&gt;        android:text="2"&gt;&lt;br /&gt; &lt;/Button&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;Button&lt;br /&gt;        android:id="@+id/pad3"&lt;br /&gt;        android:layout_width="wrap_content"&lt;br /&gt;        android:layout_height="wrap_content"&lt;br /&gt;        android:text="3"&gt;&lt;br /&gt; &lt;/Button&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/TableRow&gt;&lt;br /&gt;&lt;br /&gt;    &lt;TableRow android:layout_weight="1"&gt;&lt;br /&gt;        &lt;Button&lt;br /&gt;        android:id="@+id/pad4"&lt;br /&gt;        android:layout_width="wrap_content"&lt;br /&gt;        android:layout_height="wrap_content"&lt;br /&gt;        android:text="4"&gt;&lt;br /&gt; &lt;/Button&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;Button&lt;br /&gt;        android:id="@+id/pad5"&lt;br /&gt;        android:layout_width="wrap_content"&lt;br /&gt;        android:layout_height="wrap_content"&lt;br /&gt;        android:text="5"&gt;&lt;br /&gt; &lt;/Button&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;Button&lt;br /&gt;        android:id="@+id/pad6"&lt;br /&gt;        android:layout_width="wrap_content"&lt;br /&gt;        android:layout_height="wrap_content"&lt;br /&gt;        android:text="6"&gt;&lt;br /&gt; &lt;/Button&gt;&lt;br /&gt;    &lt;/TableRow&gt;&lt;br /&gt;&lt;br /&gt;    &lt;TableRow android:layout_weight="1"&gt;&lt;br /&gt;        &lt;Button &lt;br /&gt;        android:id="@+id/pad7"&lt;br /&gt;        android:layout_width="fill_parent"&lt;br /&gt;        android:layout_height="fill_parent"&lt;br /&gt;        android:text="7"&gt;&lt;br /&gt; &lt;/Button&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;Button&lt;br /&gt;        android:id="@+id/pad8"&lt;br /&gt;        android:layout_width="wrap_content"&lt;br /&gt;        android:layout_height="wrap_content"&lt;br /&gt;        android:text="8"&gt;&lt;br /&gt; &lt;/Button&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;Button&lt;br /&gt;        android:id="@+id/pad9"&lt;br /&gt;        android:layout_width="wrap_content"&lt;br /&gt;        android:layout_height="wrap_content"&lt;br /&gt;        android:text="9"&gt;&lt;br /&gt; &lt;/Button&gt;&lt;br /&gt;    &lt;/TableRow&gt;&lt;br /&gt;&lt;br /&gt;&lt;/TableLayout&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4005196037721136658-3570380417063825832?l=radioal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://radioal.blogspot.com/feeds/3570380417063825832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4005196037721136658&amp;postID=3570380417063825832' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4005196037721136658/posts/default/3570380417063825832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4005196037721136658/posts/default/3570380417063825832'/><link rel='alternate' type='text/html' href='http://radioal.blogspot.com/2011/05/stretching-rows-in-android-tablelayout.html' title='Stretching Rows in Android TableLayout'/><author><name>Fabrizio</name><uri>http://www.blogger.com/profile/06857225138675289185</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/-YvNiP-wwJp0/TXHThNx0frI/AAAAAAAABSo/PNPSjmZx8LY/s220/IMAG0073.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-RsiMYtJZFWQ/Tdi1RRcy2hI/AAAAAAAABU4/o8bVCHxSG9o/s72-c/stretchedrows.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4005196037721136658.post-919310068767184562</id><published>2011-03-04T22:09:00.000-08:00</published><updated>2011-03-05T13:35:39.224-08:00</updated><title type='text'>Test WebKit Rendering with Qt</title><content type='html'>Using the QtWebKit module provided by Qt, developers can test WebKit rendering without visual inspection. The QWebView class from QtWebKit, along with a few classes from QtGui, can be used to verify rendering in relatively few lines of code.&lt;br /&gt;&lt;br /&gt;The basic approach creates a QImage by rendering a QWebView's frame to a QPainter, whose paint device is a QImage instance. Once QWebView has rendered to the QImage, this object can be simply compared with another QImage.&lt;br /&gt;&lt;br /&gt;This is creating a screenshot of a web page and comparing it to another screenshot to confirm or refute that the images are the same. The images can be optionally saved to a file if visual proof is desired.&lt;br /&gt;&lt;br /&gt;For example, given two QWebView objects, a screenshot for each can be generated and then compared:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:cpp"&gt;&lt;br /&gt;QWebView viewA, viewB;&lt;br /&gt;QImage screenShotA, screenShotB;&lt;br /&gt;WebKitRenderTest renderTest;&lt;br /&gt;&lt;br /&gt;screenShotA = renderTest.initWebView(QColor(Qt::red), viewA, html, QString("viewA"));&lt;br /&gt;&lt;br /&gt;screenShotB = renderTest.initWebView(QColor(Qt::blue), viewB, html, QString("viewB"));&lt;br /&gt;&lt;br /&gt;QString result = (screenShotA == screenShotB) ? "images are same" : "images are different";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note that the comparison is done with the overloaded equality operator in QImage.&lt;br /&gt;&lt;br /&gt;The WebKitRenderTest is just a helper class with little more than a function for initializing a QWebVIew, setting the HTML content, applying a background color via QWebView's QPalette, and returning a QImage--the screenshot. Here is the body of such a function:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:cpp"&gt;&lt;br /&gt;QImage WebKitRenderTest::initWebView(QColor bgColor, QWebView&amp;amp; view, QString&amp;amp; content, QString imgName){&lt;br /&gt;QPalette pal;&lt;br /&gt;QBrush brush(bgColor);&lt;br /&gt;brush.setStyle(Qt::SolidPattern);&lt;br /&gt;pal.setBrush(QPalette::Base, brush);&lt;br /&gt;&lt;br /&gt;view.setPalette(pal);&lt;br /&gt;view.setHtml(content);&lt;br /&gt;view.page()-&gt;setViewportSize(view.page()-&gt;currentFrame()-&gt;contentsSize());&lt;br /&gt;&lt;br /&gt;QImage img(view.page()-&gt;viewportSize(), QImage::Format_ARGB32);&lt;br /&gt;QPainter paintView(&amp;amp;img);&lt;br /&gt;view.page()-&gt;currentFrame()-&gt;render(&amp;amp;paintView);&lt;br /&gt;paintView.end();&lt;br /&gt;&lt;br /&gt;QString imgFileName = imgName + ".png";&lt;br /&gt;img.save(imgFileName); // not necessary, just for visual inspection&lt;br /&gt;view.close();&lt;br /&gt;&lt;br /&gt;return img;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;By using the QPalette::Base color role on the brush, the entire page background can be colored as desired by the application.&lt;br /&gt;&lt;br /&gt;The technique is straightforward and easily adapted for automated tests. It is especially suited for use with the QTestLib framework provided by Qt.&lt;br /&gt;&lt;br /&gt;A compilable, buildable project based on this example can be found here in zipped form:&lt;br /&gt;&lt;a href="https://docs.google.com/uc?id=0B7qXaguuORTFNWM4MjE1MGMtMTg4Yi00YzQ4LTk2ZjYtYzczZjQ1NzFiOTMw&amp;amp;export=download&amp;amp;authkey=COfEpIoB&amp;amp;hl=en"&gt;https://docs.google.com/uc?id=0B7qXaguuORTFNWM4MjE1MGMtMTg4Yi00YzQ4LTk2ZjYtYzczZjQ1NzFiOTMw&amp;amp;export=download&amp;amp;authkey=COfEpIoB&amp;amp;hl=en&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;To see how this approach is already being used in WebKit, see this Changeset:&lt;br /&gt;&lt;a href="http://trac.webkit.org/changeset/79409"&gt;http://trac.webkit.org/changeset/79409&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4005196037721136658-919310068767184562?l=radioal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://radioal.blogspot.com/feeds/919310068767184562/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4005196037721136658&amp;postID=919310068767184562' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4005196037721136658/posts/default/919310068767184562'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4005196037721136658/posts/default/919310068767184562'/><link rel='alternate' type='text/html' href='http://radioal.blogspot.com/2011/03/test-webkit-rendering-with-qt.html' title='Test WebKit Rendering with Qt'/><author><name>Fabrizio</name><uri>http://www.blogger.com/profile/06857225138675289185</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/-YvNiP-wwJp0/TXHThNx0frI/AAAAAAAABSo/PNPSjmZx8LY/s220/IMAG0073.jpg'/></author><thr:total>0</thr:total></entry></feed>
