如何在Ubuntu QML应用中设计像微信对话那样的UI

我们知道像微信那样的带有气球的对话框对于一些聊天的应用来说非常好。在很多即时通讯的应用中可以用到。在今天的文章中,我们将介绍如何使用QML来实现这样的界面。

为了方便,我们可以采用Ubuntu SDK中的“QtQuick App with QML UI (qmake)”这个模版来实现一个模版的应用。为了能够创建一个TextBalloon的控件,我们使用了C++代码:

textballoon.h

#ifndef TEXTBALLOON_H
#define TEXTBALLOON_H

#include <QtQuick>

class TextBalloon : public QQuickPaintedItem
{
    Q_OBJECT
    Q_PROPERTY(bool rightAligned READ isRightAligned WRITE setRightAligned NOTIFY rightAlignedChanged)

    public:
        TextBalloon(QQuickItem *parent = 0);
        void paint(QPainter *painter);

        bool isRightAligned();
        void setRightAligned(bool rightAligned);

    private:
        bool rightAligned;

    signals:
        void rightAlignedChanged();
};

#endif

textballoon.cpp

#include "textballoon.h"

TextBalloon::TextBalloon(QQuickItem *parent)
    : QQuickPaintedItem(parent)
    , rightAligned(false)
{
}

void TextBalloon::paint(QPainter *painter)
{
    QBrush brush(QColor("#007430"));
    QBrush white(QColor("#FFFFFF"));

    if (rightAligned)
    {
        painter->setBrush(brush);
        painter->setPen(Qt::NoPen);
        painter->setRenderHint(QPainter::Antialiasing);
        painter->drawRoundedRect(10, 0, boundingRect().width() - 19, boundingRect().height(), 10, 10);

        const QPointF points[3] = {
            QPointF(boundingRect().width() - 10.0, 10.0),
            QPointF(boundingRect().width(), 20.0),
            QPointF(boundingRect().width() - 10.0, 30.0),
        };

        painter->drawConvexPolygon(points, 3);
    }
    else
    {
        painter->setBrush(white);
        painter->setPen(Qt::NoPen);
        painter->setRenderHint(QPainter::Antialiasing);
        painter->drawRoundedRect(10, 0, boundingRect().width() - 19, boundingRect().height(), 10, 10);

        const QPointF points[3] = {
            QPointF(10,10),
            QPointF(0, 20),
            QPointF(10, 30),
        };

        painter->drawConvexPolygon(points, 3);
    }
}

bool TextBalloon::isRightAligned()
{
    return this->rightAligned;
}

void TextBalloon::setRightAligned(bool rightAligned)
{
    this->rightAligned = rightAligned;
}

在main.cpp中,注册该类:

   qmlRegisterType<TextBalloon>("TextBalloon", 1, 0, "TextBalloon");

这样这个TextBalloon就可以在QML中被利用。我们的QML界面非常简单:

import QtQuick 2.0
import Ubuntu.Components 1.1

Item {
    id: root

    property int contentWidth: width *.6

    ListModel {
        id: balloonModel
    }

    ListView {
        id: balloonView
        anchors.bottom: controls.top
        anchors.bottomMargin: 2
        anchors.top: parent.top
        clip:true

        delegate: MyDelegate {}

        model: balloonModel
        spacing: units.gu(4)
        width: parent.width
    }

    Rectangle {
        id: controls

        anchors.bottom: parent.bottom
        anchors.left: parent.left
        anchors.margins: 1
        anchors.right: parent.right
        border.width: 2
        color: "white"
        height: parent.height * 0.15

        Text {
            anchors.centerIn: parent
            text: "Add another balloon"
        }

        MouseArea {
            anchors.fill: parent
            hoverEnabled: true
            onClicked: {
                balloonModel.append({"balloonWidth": Math.floor(Math.random() * 200 + 100),
                                     "content": "this is cool"
                                     })
                balloonView.positionViewAtIndex(balloonView.count -1, ListView.End)
            }
            onEntered: {
                parent.color = "#8ac953"
            }
            onExited: {
                parent.color = "white"
            }
        }
    }

    Component.onCompleted: {
        console.log("contentWidth: " + root.contentWidth);
        balloonModel.append({"balloonWidth": root.contentWidth,
                             "content": "this is a text, this is a perfect world to play with, and I love to play the world"
                             });
        balloonModel.append({"balloonWidth": root.contentWidth,
                             "content": "this is a text, this is a perfect world to play with, and I love to play the world"
                             });

    }
}

上面是一个ListView,下面是一个按钮来动态生成一些ListView中的项。我们的ListView的delegate设计稍微麻烦一点:

import QtQuick 2.0
import TextBalloon 1.0
import Ubuntu.Components 1.1
import QtQuick.Layouts 1.1

Item {
    id: delegate
    width: ListView.view.width
    height: txt.contentHeight + 20
    property bool rightAligned: index % 2 == 0 ? false : true

    RowLayout {
        spacing: units.gu(2)
        anchors.right: index % 2 == 0 ? undefined : parent.right

        Image {
            id: leftImg
            width: root.contentWidth*.2
            height: width
            anchors.top:parent.top
            source: "images/pic1.jpg"
            visible: delegate.rightAligned ? false : true
            fillMode: Image.PreserveAspectCrop
            Layout.maximumWidth:root.contentWidth*.2
            Layout.maximumHeight: root.contentWidth*.2
        }

        Text {
            id: txt
            anchors.top: parent.top
            anchors.topMargin: units.gu(1)
            width: root.contentWidth
            wrapMode: Text.WordWrap
            text: content
//            horizontalAlignment: delegate.rightAligned ? Text.AlignRight : Text.AlignLeft
            font.pixelSize: units.gu(3)

            Layout.maximumWidth: root.contentWidth

            TextBalloon {
                anchors.fill: parent
                z: -1
                rightAligned: delegate.rightAligned
                anchors.margins: -units.gu(1.5)
            }
        }

        Image {
            id: rightImg
            anchors.top:parent.top
            width: root.contentWidth*.2
            height: width
            source: "images/pic2.jpg"
            visible: delegate.rightAligned ? true : false
            fillMode: Image.PreserveAspectCrop
            Layout.maximumWidth:root.contentWidth*.2
            Layout.maximumHeight: root.contentWidth*.2
        }
    }
}

这里我们使用RowLayout,也是非常tricky的一个设计。运行我们的应用:

   

整个项目的源码在: git clone https://gitcafe.com/ubuntu/weixin_new.git

时间: 2024-10-18 14:00:28

如何在Ubuntu QML应用中设计像微信对话那样的UI的相关文章

如何在Ubuntu QML应用中播放视频

在这篇文章中,我们将介绍如何在Ubuntu QML应用中播放一个视频.为了实现方便,我们可以事先用手机录下一个视频,并置于我们已经创建好的项目中. 首先,我们利用Ubuntu SDK来创建一个"QML app with Simple UI (qmake)"的项目.我们修改我们的Main.qml文件如下: import QtQuick 2.0 import Ubuntu.Components 1.1 import QtMultimedia 5.0 /*! \brief MainView

如何在Ubuntu QML应用中使用Push Notification

我们知道目前Ubuntu手机平台有些类似iPhone平台,是一个单任务的操作系统,虽然系统本身具有多任务的功能.如果当前的应用被推到后台的话,应用将会被自动挂起,而不会被系统所运行.在这个时候如果我们的应用需要等待一个消息,比如就想微信之类的信息,我们就要使用Ubuntu平台所提供的Push Notification机制来实现我们的类似多任务的东西.当通知被收到后,我们就可以直接点击接受到的通知,应用又会被重新运行到前台. 关于Push notification,在我们的开发者网站上,有一篇文章

如何在Ubuntu QML应用中播放音乐

昨天我看见一个开发者发了一个问题,询问如何播放声音.目前由于一些原因在模拟器中没法测试.其实,播放声音很容易.如果使用qmake的话,可能需要做一些修改才可以正确地在手机上播放. 我们首先使用SDK来创建一个简单的项目(QML app with Simple UI "qmake").我们记得修改我们的Main.qml如下: import QtQuick 2.0 import Ubuntu.Components 1.1 import QtMultimedia 5.0 /*! \brief

如何在Ubuntu QML应用中判断应用的方位(landscape或portrait)

我们知道对于一些应用来说,判断方位可以使得我们可以重新定位我们的应用的布局,以使得我们的应用在不同的方位中更加合理及好看.在这篇文章中,我们来介绍如何来侦测应用方位的变化. 我们首先来创建一个我们自己的简单的QML应用.对于大多数的QML应用来说,一般是含有一个"MainView"的: MainView { id: root // objectName for functional testing purposes (autopilot-qt5) objectName: "m

如何在Ubuntu QML应用中震动(vibration)

对于有些QML应用来说,震动是非常重要的一个功能.特别是对一下游戏来说.那么我们怎么在QML应用中震动呢? 我们官方有一个API HapticsEffect,这个API的功能就是让我们的应用来震动的.使用这个API非常容易: import QtQuick 2.0 import Ubuntu.Components 1.1 import QtFeedback 5.0 /*! \brief MainView with a Label and Button elements. */ MainView {

如何在Ubuntu QML应用中进行语言录音

在QML API中,目前并没有一个相应的API来进行录音.我们必须使用Qt C++ API QAudioRecorder来进行录音的工作.在这篇文章中,我们来介绍如何使用这个API来进行录音. 首先,我们来创建一个"QML App with C++ plugin (qmake)"模版的应用.注意qmake的项目必须是在15.04及以上的target上才可以运行. 为了录音,我创建了一个叫做"AudioRecorder"的类: audiorecorder.h #ifn

如何在Ubuntu QML应用中实现一个垂直的Slider

我们在使用Ubuntu SDK中的Slider的时候,我们发现,它没有orientation的属性尽管在Qt官方网站的slider是有这个属性的.在默认的情况下,这个Slider是水平的.那么我们该如实现这个呢? 我们的任何一个QML Item都有一个属性叫做rotation.我们可以通过这个属性来得到一个旋转90度的水平Slider.这样我们就可以用如下的代码来实现了: import QtQuick 2.0 import Ubuntu.Components 1.1 /*! \brief Mai

如何在Ubuntu 14.04中安装最新版Eclipse

想必很多开发人员都知道,Ubuntu 软件源中提供的并不是最新版本的 Eclipse,本教程就教大家如何在 Ubuntu 14.04 中快速安装 Eclipse 官方发布的最新版本. 到目前为止,Eclipse 的官方最新版本为 Eclipse Kepler (4.3.2),我们可以使用如下步骤在 Ubuntu 14.04 或其它 Ubuntu 版本中进行快速安装. 1.安装OpenJDK Java 7 如果你的系统中没有安装 Java,我们需要按如下步骤事先安装好 OpenJDK Java 7

【转】如何在Ubuntu 14.04 LTS上设置Nginx虚拟主机

介绍 转自http://www.pandacademy.com/%E5%A6%82%E4%BD%95%E5%9C%A8ubuntu-14-04-lts%E4%B8%8A%E8%AE%BE%E7%BD%AEnginx%E8%99%9A%E6%8B%9F%E4%B8%BB%E6%9C%BA/#i-3 使用Nginx Web服务器时,可以使用server blocks(类似于Apache中的虚拟主机)来封装配置详细信息,并托管单个服务器的多个域. 在本教程中,我们将讨论如何在Ubuntu 14.04服