物联网实战--平台篇之(九)分组界面设计

目录

一、界面设计

二、项目工程概览

三、分组切换

四、分组管理

五、新建分组

六、编辑分组


 本项目的交流QQ群:701889554

物联网实战--入门篇https://blog.csdn.net/ypp240124016/category_12609773.html

物联网实战--驱动篇https://blog.csdn.net/ypp240124016/category_12631333.html

本项目资源文件 https://download.csdn.net/download/ypp240124016/89317308

一、界面设计

                

上图是米家APP关于分组管理的界面,主页面是选项卡+视图的模式,分组管理可以删除和排序,重命名它需要单机某个分组再进入一层界面进行操作,我们做些省略,下图是模仿的界面。

                

             

     

二、项目工程概览

以下是针对这部分界面的项目代码结构图,主要分为两部分,一是分组切换页面——GroupTabView,二是分组管理页面——GroupEditView,其它都是对话框类型的,下面对这些内容做具体讲解。

三、分组切换

        分组就是下图红框里的内容,每个名称都是一个选项卡,下面对应的界面内容也会跟着切换,原本想着用QT自带的TabView来实现,后面发现达不到想要的效果,实际上米家APP里的选项卡和页面内容是分开的,是通过当前页面值关联起来的。所以后面就自己实现了这个过程,相对比较啰嗦点。

import QtQuick 2.7
import QtQuick.Controls 2.12
import "../base"
Rectangle
{
    color: "transparent"
    ListView//滑动tab bar
    {
        id:id_tabBarView
        clip:true
        orientation: ListView.Horizontal
        height: 40
        anchors
        {
            left:parent.left
            right:id_listButton.left
        }
        model: ListModel{
            id:id_tabBarModel
        }
        delegate: Rectangle{
            height: 40
            width: id_titleText.contentWidth+15
            color: "transparent"
            Text{
                id:id_titleText
                height: parent.height
                width: 20
                anchors.centerIn: parent
                font.family: Qt.platform.os === "windows" ? "宋体" : "黑体"
                font.pointSize: 18
                font.bold: id_tabBarView.currentIndex===id
                text: group_name
                verticalAlignment: Text.AlignVCenter
                horizontalAlignment: Text.AlignHCenter
            }
            MouseArea
            {
                anchors.fill: parent
                onClicked: 
                {
                    id_tabBarView.currentIndex=id
                }
            }
        }
        onCurrentIndexChanged: 
        {
            id_mainView.currentIndex=currentIndex
        }
    }
    
    GroupNewDialog
    {
        id:id_groupNewDialog
    }
    
    GroupManDialog
    {
        id:id_groupManDialog
        onSiqNewGroup: //新建分组
        {
            id_groupNewDialog.funOpen("新分组")
        }
        onSiqManGroup: //分组管理
        {
            theAccountMan.setHomeCurrView("home-group")
        }
        onSiqOpenGroup: 
        {
            id_tabBarView.currentIndex=id
            id_mainView.currentIndex=id
        }
    }
    
    Rectangle{  //列表按钮
        id:id_listButton
        height: id_tabBarView.height*0.8
        width: height*1.5
        anchors
        {
            right:parent.right
            rightMargin:15
            verticalCenter:id_tabBarView.verticalCenter
        }
        
        radius: height/2
        color: "#BFC5D6"
        ImageButton01{
            anchors.centerIn: parent
            height: parent.height*0.85
            width: height
            source: "qrc:/mainImgRC/images/home/list.png"
            onSiqClickedLeft: 
            {
                id_groupManDialog.open()
            }
        }
    }

    SwipeView {  //主页面切换
         id: id_mainView
         width: parent.width
         anchors
         {
            top:id_tabBarView.bottom
            bottom:parent.bottom
         }
         Repeater {
             model: ListModel{
             id:id_mainModel
             }
    
             Rectangle {
              color: "transparent"
              Text{
                anchors.centerIn: parent
                font.pointSize: 18
                text: id
              }
          }
         }
         onCurrentIndexChanged: {
             id_tabBarView.currentIndex=currentIndex
         }
     }
      Component.onCompleted: 
      {
            for(var i=0; i<1; i++)
            {
                id_tabBarModel.append({"id":i, "group_name":"全部"})
                id_mainModel.append({"id":i, "group_name":"全部"})
            }
      }
    
      Connections
      {
          target: theCenterMan
          onSiqAddGroup:
          {
                if(index===0)
                {
                    id_tabBarModel.clear()
                    id_mainModel.clear()
                    id_tabBarModel.append({"id":0, "group_name":"全部"})
                    id_mainModel.append({"id":0, "group_name":"全部"})
                }
                index=id_tabBarModel.count
                id_tabBarModel.append({"id":index, "group_name":group_name})
                id_mainModel.append({"id":index, "group_name":group_name})
          }
          onSiqRenameGroup:
          {
              for(var i=1; i<id_tabBarModel.count; i++)
              {
                  var group_name=id_tabBarModel.get(i).group_name
                  if(group_name===old_name)
                  {
                      id_tabBarModel.setProperty(i, "group_name", new_name)
                      id_mainModel.setProperty(i, "group_name", new_name)
                      break
                  }
              }
          }
          onSiqDelGroup:
          {
              for(var i=1; i<id_tabBarModel.count; i++)
              {
                  if(group_name===id_tabBarModel.get(i).group_name)
                  {
                      id_tabBarModel.remove(i)
                      id_mainModel.remove(i)
                      break
                  }
              }
          }
      }
}





        分组切换具体代码如上所示,主要分为Tab和View两部分,Tab用一个ListView,这样就可以实现滑动而不切换的效果了,如果是QT的TabView,点一下就会切换过去,没法用。

        ListView核心就两个内容,模型和单元格,即model和delegate两个属性,模型一般采用ListModel,通过操作ListModel实例就可以改变单元格的内容以及增减单元格等操作了。delegate就是单元格具体内容了,在这里主要就是文本,另外背景的矩形要改成透明的,这样APP的背景色才能透出来,还有一个是鼠标,点击后会触发切换,tab切换后又会联动下方的主视图切换,这样两者就关联起来了。

        主页面是一个SwipeView ,这个是之前常用的模块了,后面这个页面是要承载设备显示用的,暂时没什么用处,就显示个页码。

四、分组管理

        在tab的右边有一个按钮,是触发分组管理用的,下面是分组管理的具体代码,是一个对话框,显示内容有三个——新建分组、编辑分组和各分组的显示。其中分组显示采用一个ListView列表视图,显示组名和组内设备数量。

import QtQuick 2.7 
import QtQuick.Controls 2.14 
import "../base"
//分组管理弹框

Popup { 
    signal siqNewGroup()
    signal siqManGroup()
    signal siqOpenGroup(var id, var group_name)
    property var rowHeight: 40
    id:id_popup
    visible: false
    implicitWidth: parent.width*0.6
    implicitHeight: rowHeight*(id_listModel.count+2)+id_popup.topPadding+id_popup.bottomPadding
    modal: true
    focus: true
    closePolicy: Popup.CloseOnEscape | Popup.CloseOnReleaseOutside
    
    x:parent.width*0.3
    y:10
    
    
    background: Rectangle
    {
        
        radius:15
    }
    Rectangle//分割横线
    {
        id:id_lineRect
        width: parent.width*0.8
        height: 1
        color:"#F0F0F0"
        anchors
        {
            horizontalCenter:parent.horizontalCenter
            bottom:parent.bottom
            bottomMargin:rowHeight*2
        }
    }
    TextButton01//新建按钮
    {
        id:id_newButton
        height: rowHeight
        width: parent.width
        anchors
        {
            left:parent.left
            leftMargin:10
            top:id_lineRect.bottom
        }
        textValue: "新建"
        onSiqClickedLeft: 
        {
            id_popup.close()
            siqNewGroup()
        }
        Image//新建图标
        {
            width: height
            height: parent.height*0.6  
            mipmap: true
            anchors
            {
                verticalCenter:parent.verticalCenter
                right:parent.right
                rightMargin:15
            }
            source: "qrc:/mainImgRC/images/home/new.png"
        }
    }
    
    TextButton01//分组管理
    {
        id:id_manButton
        height: id_newButton.height
        width: parent.width
        anchors
        {
            left:parent.left
            leftMargin:10
            top:id_newButton.bottom
        }
        textValue: "管理"
        onSiqClickedLeft: 
        {
            id_popup.close() 
            siqManGroup()
        } 
        Image//管理图标
        {
            width: height
            height: parent.height*0.5  
            mipmap: true
            anchors
            {
                verticalCenter:parent.verticalCenter
                right:parent.right
                rightMargin:17
            }
            source: "qrc:/mainImgRC/images/home/man.png"
        }
    }
    
    ListView
    {
        clip: true
        width: parent.width
        anchors
        {
            top:parent.top
            bottom:id_lineRect.top
        }
        model: ListModel{
            id:id_listModel
        }
        
        delegate: Rectangle{
            height: rowHeight
            width: parent.width
            TextButton01//分组按钮
            {
                id:id_groupButton
                height: rowHeight
                width: parent.width-20
                anchors
                {
                    left:parent.left
                    leftMargin:10
                    verticalCenter:parent.verticalCenter
                }
                textValue: group_name
                onSiqClickedLeft: //打开某个分组
                {
                    id_popup.close()
                    siqOpenGroup(id, group_name)
                }
                Text{
                    id:id_totalNumText
                    height: parent.height
                    width: 30
                    anchors{
                        right: parent.right
                        verticalCenter: parent.verticalCenter
                    }
                    color: "#808080"
                    font.family: "宋体"
                    font.pointSize: 18
                    text: total_num
                    verticalAlignment: Text.AlignVCenter
                    horizontalAlignment: Text.AlignHCenter
                }
            }
        }
    }
    
    Component.onCompleted: 
    {
          for(var i=0; i<1; i++)
          {
              id_listModel.append({"id":i, "group_name":"全部", "total_num":0})
          }
    }
    
    Connections
    {
        target: theCenterMan
        onSiqAddGroup:
        {
              if(index===0)
              {
                  id_listModel.clear()
                  id_listModel.append({"id":0, "group_name":"全部", "total_num":total_num})
              }
              index=id_listModel.count
              id_listModel.append({"id":index, "group_name":group_name, "total_num":total_num})
        }
        onSiqRenameGroup:
        {
            for(var i=1; i<id_listModel.count; i++)
            {
                var group_name=id_listModel.get(i).group_name
                if(group_name===old_name)
                {
                    id_listModel.setProperty(i, "group_name", new_name)
                    break
                }
            }
        }
        onSiqDelGroup:
        {
            for(var i=1; i<id_listModel.count; i++)
            {
                if(group_name===id_listModel.get(i).group_name)
                {
                    id_listModel.remove(i)
                    break
                }
            }
        }
    }
    
}

五、新建分组

        点击 新建按钮后,会弹出新建对话框,可以输入组名进行新建操作。

六、编辑分组

        编辑分组比较复杂,包含了删除、重命名和排序,其中重点是排序功能,具体代码如下。这里面主要难点是一个分组排序的拖拽功能,核心思想是—— 单元格内分为两部分,一个是拖拽有效区id_dragRect,一个是拖拽显示区dropRectangle,当鼠标捕捉到拖拽信号后,就把拖拽区的父组件从单元格修改为根矩形组件,然后取消布局,这样拖拽区就可以被拉动了;接着是放掉后检测当前坐标,看下在哪个单元格上就跟其做交换即可,最后配合ListView的move和moveDisplaced动画,产生交换效果就完成了,具体实现看代码。

import QtQuick 2.7
import QtQuick.Controls 2.0
import "../base"

//分组编辑界面

Rectangle {
    id:id_rootRect
    
    focus: true
    MsgDialog01
    { 
        id:id_msgDialog
    }
    
    Keys.onPressed: 
    {
        if(event.key === Qt.Key_Back)
        {
            console.log("phone Key_Back!")
            event.accepted = true;
            theAccountMan.setHomeCurrView("home-logined")
        }
    }
    
    ImageButton01//返回按钮
    {
        id:id_backButton
        source: "qrc:/mainImgRC/images/login/back.png"
        
        anchors
        {
            left:parent.left
            leftMargin:20
            top:parent.top
            topMargin:20            
        }
        onSiqClickedLeft: 
        {
            theAccountMan.setHomeCurrView("home-logined")
        }
    }
    ImageButton01{
        id:id_okButton
        source: "qrc:/mainImgRC/images/home/ok.png"
        height: 35
        anchors
        {
            right:parent.right
            rightMargin:20
            verticalCenter:id_backButton.verticalCenter
        }
        onSiqClickedLeft: //完成
        {
            var str_list=[]
            for(var i=1; i<id_listModel.count; i++)
            {
                str_list[i]=id_listModel.get(i).group_name
            }
            theCenterMan.requestOrderGroup(str_list)
        }
    }
    
    GroupRenameDialog//重命名
    {
        id:id_renameDialog
        onSiqOkClicked: 
        {
            if(text)
            {
                if(text==="全部")
                {
                    id_msgDialog.funOpen("不能使用\"全部\"作为组名!")
                    return
                }
                theCenterMan.requestRenameGroup(oldName, text)
            }
            funClose()
        }
    }
    GroupDelDialog //删除分组对话框
    {
        id:id_delGroupDialog
        onSiqOkClicked: 
        {
            theCenterMan.requestDelGroup(groupName)
            funClose()
        }
    }
    
    ListView{
        property int dragItemIndex: -1
        id:id_editListView
        clip: true
        width: parent.width
        anchors
        {
            top:id_backButton.bottom
            bottom:parent.bottom
        }
        model: ListModel{
            id:id_listModel
        }
        move:Transition {
            NumberAnimation { properties: "x,y"; duration: 200 }
        }
        moveDisplaced:Transition {
            NumberAnimation { properties: "x,y"; duration: 200 }
        }
        delegate: Rectangle{
            id:id_unionRect
            height: 60
            width: parent.width
            Rectangle
            {
                id:id_dragRect
                height: id_unionRect.height
                width: id_unionRect.width
                color: id_moveMouseArea.drag.active ? "transparent" : "white"
                MouseArea
                {
                    id:id_moveMouseArea
                    enabled: id>0
                    anchors.fill: parent
                    drag.target: id_dragRect
                    drag.axis: Drag.YAxis
                    drag.onActiveChanged: {
                        if (id_moveMouseArea.drag.active) {
                            id_editListView.dragItemIndex = index;
//                            console.log("index=", index)
                        }
                        id_dragRect.Drag.drop();
                    }
                }
                states: [
                    State {
                        when: id_dragRect.Drag.active
                        ParentChange {
                            target: id_dragRect
                            parent: id_rootRect
                        }
    
                        AnchorChanges {
                            target: id_dragRect
                            anchors.horizontalCenter: undefined
                            anchors.verticalCenter: undefined
                        }
                    }
                ]
                Drag.active: id_moveMouseArea.drag.active
                Drag.hotSpot.x: id_dragRect.width / 2
                Drag.hotSpot.y: id_dragRect.height / 2
                
                ImageButton01{
                    id:id_delButton
                    source: "qrc:/mainImgRC/images/home/del.png"
                    height: 25
                    width: height
                    visible: id>0
                    anchors
                    {
                        verticalCenter:parent.verticalCenter
                        left:parent.left
                        leftMargin:20
                    }
                    onSiqClickedLeft: //删除
                    {
                        id_delGroupDialog.groupName=group_name
                        id_delGroupDialog.funOpen()
                    }
                }
                
                Text{  //组名文本
                    id:id_groupText
                    height: 40
                    anchors{
                        left: id_delButton.right
                        leftMargin: 10
                        right: id_totalNumText.left
                        verticalCenter: parent.verticalCenter
                    }
                    color: "black"
                    font.family: Qt.platform.os === "windows" ? "宋体" : "黑体"
                    font.pointSize: 18
                    font.bold: id_moveMouseArea.pressed
                    text: group_name
                    verticalAlignment: Text.AlignVCenter
                    horizontalAlignment: Text.AlignLeft
                    elide: Text.ElideRight 
                }
       
                Text{ //数量文本
                    id:id_totalNumText
                    height: 30
                    width: 30
                    anchors{
                        right: id_renameButton.left
                        rightMargin: 5
                        verticalCenter: parent.verticalCenter
                    }
                    color: "#808080"
                    font.family: "宋体"
                    font.pointSize: 18
                    text: total_num
                    verticalAlignment: Text.AlignVCenter
                    horizontalAlignment: Text.AlignLeft
                    elide: Text.ElideRight 
                }
                ImageButton01{ 
                    id:id_renameButton
                    source: "qrc:/mainImgRC/images/home/rename.png"
                    height: 25
                    width: height
                    visible: id>0                
                    anchors
                    {
                        verticalCenter:parent.verticalCenter
                        right:parent.right
                        rightMargin:20
                    }
                    onSiqClickedLeft: //重命名
                    {
                        id_renameDialog.oldName=group_name
                        id_renameDialog.funOpen(group_name)
                    }
                }
             
                
            }
           DropArea {
           id: dropArea
           anchors.fill: parent
           onDropped:{
//               console.log("onDropped")
               var other_index = id_editListView.indexAt(id_moveMouseArea.mouseX + id_unionRect.x, id_moveMouseArea.mouseY + id_unionRect.y);
//               console.log("index:",index,"other_index:",other_index,"listView.dragItemIndex:",id_editListView.dragItemIndex);
               if(other_index>0)
               {
                   id_listModel.move(id_editListView.dragItemIndex,other_index, 1);
               }
           }
           
           Rectangle {
                   id: dropRectangle

                   anchors.fill: parent
                   color: "transparent"

                   states: [
                       State {
                           when: dropArea.containsDrag
                           PropertyChanges {
                                target: dropRectangle
                                color: "lightsteelblue"
                                opacity:0.3
                           }
                       }
                   ]
               }//end Rectangle

           }//end drop
            
        }
    }
    Component.onCompleted: 
    {
          for(var i=0; i<1; i++)
          {
              id_listModel.append({"id":i, "group_name":"全部", "total_num":0})
          }
    }
    Connections
    {
        target: theCenterMan
        onSiqAddGroup:
        {
              if(index===0)
              {
                  id_listModel.clear()
                  id_listModel.append({"id":0, "group_name":"全部", "total_num":total_num})
              }
              index=id_listModel.count
              id_listModel.append({"id":index, "group_name":group_name, "total_num":total_num})
        }
        onSiqRenameGroup:
        {
            for(var i=1; i<id_listModel.count; i++)
            {
                var group_name=id_listModel.get(i).group_name
                if(group_name===old_name)
                {
                    id_listModel.setProperty(i, "group_name", new_name)
                    break
                }
            }
        }
        onSiqDelGroup:
        {
            for(var i=1; i<id_listModel.count; i++)
            {
                if(group_name===id_listModel.get(i).group_name)
                {
                    id_listModel.remove(i)
                    break
                }
            }
        }
    }
    
}

        删除和重命名就是相关对话框内容了,没有很复杂的内容,具体看代码。

import QtQuick 2.7 
import QtQuick.Controls 2.14 

Popup {
    
    property var titleText: "标题"
    property var cancelText: "取消"
    property var okText: "确定"
    property var cancelColor: "#303030"
    property var okColor: "#303030"
    
    signal siqCancelClicked()
    signal siqOkClicked()
    id:id_popup
    visible: false
    implicitWidth: parent.width
    implicitHeight: 200
    modal: true
    focus: true
    closePolicy: Popup.CloseOnEscape | Popup.CloseOnReleaseOutside
    anchors.centerIn: Overlay.overlay
    
    background: Rectangle
    {
        radius:10
    }
    
    Text {//标题文字
        id:id_titleText
        height: 40
        width: parent.width*0.8
        anchors
        {
            top:parent.top
            topMargin:10
            horizontalCenter:parent.horizontalCenter
        }
        verticalAlignment: Text.AlignVCenter
        horizontalAlignment: Text.AlignHCenter
        font.pointSize: height*0.4
        font.family: "宋体"
        text: titleText
        color: "black"
    }
    
    
    BaseButton02//取消按钮
    { 
        id:id_cancelButton
        height: 50
        width: parent.width*0.4
        releaseColor: "#F0F0F0"
        pressedColor: "#F0F0F0"
        anchors
        {
            left:parent.left
            leftMargin:20
            bottom:parent.bottom
            bottomMargin:20
        }
        buttonText: cancelText
        buttonColor:cancelColor
        onSiqClickedLeft: 
        {
            siqCancelClicked()
        }
    }
    BaseButton02//确定按钮
    { 
        id:id_okButton
        height: id_cancelButton.height
        width: id_cancelButton.width
        releaseColor: "#F0F0F0"
        pressedColor: "#F0F0F0"
        anchors
        {
            verticalCenter:id_cancelButton.verticalCenter
            right:parent.right
            rightMargin:20
        }
        buttonText: okText
        buttonColor:okColor
        onSiqClickedLeft: 
        {
            siqOkClicked()
        }
    }
    
    function funOpen()
    {
        id_popup.open()
    }
    
    function funClose()
    {
        id_popup.close()
    }
}

import QtQuick 2.0
import "../base"

//删除警示对话框


BaseWarnDialog {
    
    titleText: "确认删除分组吗?"
    property var groupName: ""
    
    okText: "删除"
    okColor: "#F00000"
    onSiqCancelClicked: 
    {
        funClose()
    }
    
    
}
import QtQuick 2.0
import "../base"

//重命名分组对话框


BaseEditDialog {
    
    titleText: "重命名分组"
    property var oldName: ""
    onSiqCancelClicked: 
    {
        funClose()
    }
    
    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瓦力农场

本文有偿阅读,自愿打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值