XBMC界面交互处理流程

转载自 http://bbs.51cto.com/thread-979614-1.html

XBMC 是一个优秀的自由和开源的(GPL)媒体中心软件。XBMC最初为Xbox而开发,现在可以运行在Linux、OSX、Windows系统。 2003年,一些兴趣相投的程序员 创建了这个项目。XBMC是一个非盈利的项目,由遍布世界各地的自愿者开发维护。超过50名软件开发人员为XBMC作出贡献,还有超过100名翻译人员努力扩大它的应用范围,使它支持超过30种语言。
     由于XBMC一开始设计就是倾向于遥控输入,自身的框架极其强大,容易扩展,用在电视盒上面刚好可以补充小公司在内容不足时的替代品。值得庆幸的是,XBMC的android 源码也开源了,android 电视盒的开发者可以学习或者拿过来改造了。

    XBMC官方网站: 点击打开 。
 也可直接下载:
  $ git clone git://github.com/xbmc/xbmc.git
 XBMC的WIKI:  点击打开 。
[hr]
  最近一直在负责xbmc 的扩展,大致对xbmc的结构比较清晰,今天不讲结构目录,网上大把。主讲一些控件的使用的数据填充等。 大致会讲到从一个界面的形成到界面上的元素的交互这方面,基本可以满足一般开发者对现有XBMC简单的界面扩展需要。
先上一张效果图



1):界面的继承

  XBMC使用的是C++编写的界面,所有眼睛能看到的界面都是继承于CGUIWindow(Dialog 继承于CGUIDialog),XBMC又分为不同的类别,比如音乐、视频、图片、天气等,每个类别分别有一个Base界面继承自CGUIWindow用来作为该类别的基类,比如视频的基类为:CGUIWindowVideoBase,假如你要为视频新增一个界面,那么可以继承CGUIWindowVideoBase,实现这个类的一些虚承数即可,非常方便。

  以我为视频增加一个缩略图展示界面的页面为例,代码为:

CGUIWindowVideoThumbList::CGUIWindowVideoThumbList( void)         :CGUIWindowVideoBase(WINDOW_VIDEO_THUMBLIST, " MyVideoThumb.xml ")

  A. MyVideoThumb.xml这个文件代表界面元素,可以理解成android 的xml界面,但编写方式和控件的排列方面都不相同,关于界面控件的排布斋在第2点详细说明。到此为止,一个新的界面就算是完成了,下面说说如何在xml上画界面。

注意:需要在Makefile文件将你新增的文件写进去,以便编译时能够顺利编进去。
2):界面元素
        XBMC所支持的控件列表: 点击打开 。
        默认界面存放于android/addons/skin.confluence/720p目录,这里面包含了所有界面的XML,对应的素材包括:声音、字体、语言文字、图片、颜色等也一并在android/addons/skin.confluence此目录,最后生成build.bat文件。
       注意:一些经常用的或者通用的布局,可以写在Includes.xml文件里面,以后有需要用到的可以直接写在你需要的xml上,比如:
<include>CommonBackground</include>
以一个panel的控件的XML为例,代码如下:
复制内容到剪贴板
代码:
<control type="group">
        <include>VisibleFadeEffect</include>
             <control type="panel" id="8000">类型panel,id为8000
                 <posx>180</posx> 位于界面x 轴为180
                 <posy>20</posy>  位于界面y轴为20
                 <width>1160</width> panel 的宽度的1160
                 <height>590</height> panel 的高度为590
                 <onleft>9000</onleft> 遥控按向左键时如果焦点还在panel里面,并且己经是最左边一个元素时,将焦点切换到ID为9000的控件上
                <onright>60</onright>遥控按向右键时如果焦点还在panel里面,并且己经是最右边一个元素时,将焦点切换到ID为60的控件上
                 <onup>1000</onup>遥控按向上键时如果焦点还在panel里面,并且己经是最顶一个元素时,将焦点切换到ID为1000的控件上
                 <ondown>1000</ondown>遥控按向下键时如果焦点还在panel里面,并且己经是最底一个元素时,将焦点切换到ID为1000的控件上
                 <viewtype label="21371">list</viewtype> 显示类型为列表
                <pagecontrol>60</pagecontrol> 与下面scrollbar绑定,作为该panel的滚动控件 
                 <scrolltime tween="sine" easing="out">200</scrolltime>拖动延时
                <preloaditems>2</preloaditems>预加载项目2
                 元素默认时的控件高度200宽度220,该荐包括一个默认无获得焦点的image(图片)和未获得含焦点的label(文字)
        <itemlayout height="200" width="220"> 
                    <control type="image"> 类型image
                         <posx>1</posx> 位于panel里面的位置是x 轴1
                        <posy>0</posy>位于panel 里面的位置 是y轴0
                        <width>180</width>image宽度180
                         <height>160</height> image高度160
                        <aspectratio>scale</aspectratio>不论图片大小填充整个图片的宽高.keep 为保持图片的大小不拉伸。更多请 点击 。
                        <bordertexture border="5">folder-nofocus.png</bordertexture>image边框纹理图片
                        <bordersize>5</bordersize>边框大小
                        <texture background="true">$INFO[Listitem.Icon]</texture>image图片,ListItem.Icon为获取CFileItemPtr里面的数据,后文会介绍
                    </control>
                     <control type="label">类型label
                         <posx>88</posx>位于panel里面的位置是x 轴88
                          <posy>160</posy>位于panel 里面的位置 是y轴160
                         <width>180</width>label宽度为180
                         <height>25</height>label高度为25
                         <font>font50caps_title</font> 文体类型,该字体定义于:xml同级目录的Font.xml里面,也可以自行设置filename与size
                         <textcolor>white</textcolor>文体颜色
                        <selectedcolor>selected</selectedcolor>选中时颜色 
                        <align>center</align>位于itemLayout的中间x方向
                        <aligny>center</aligny>位于itemLayout的中间y方向
                        <info>ListItem.Label</info>显示信息同样获取自CFileitemPtr,也可自行指定
                    </control>
                     
                 </itemlayout>
                 元素获得焦点时的控件高度200宽度250,该荐包括一个默认无获得焦点的image(图片)和未获得含焦点的label(文字)
        <focusedlayout  height="200" width="250">
                     
                     <control type="image">
                         <posx>1</posx>
                         <posy>0</posy>
                         <width>180</width>
                         <height>160</height>
                         <aspectratio>scale</aspectratio>
                         <bordertexture border="5">folder-focus.png</bordertexture> 获取焦点时的图片
                        <bordersize>5</bordersize>
                         <texture background="true">$INFO[Listitem.Icon]</texture>
                     </control>
                     <control type="label">
                         <posx>88</posx>
                         <posy>160</posy>
                         <width>180</width>
                         <height>25</height>
                         <font>font50caps_title</font>
                         <textcolor>white</textcolor>
                         <selectedcolor>selected</selectedcolor>
                         <align>center</align>
                         <aligny>center</aligny>
                         <info>ListItem.Label</info>
                     </control>
                 </focusedlayout>
             </control>
             <control type="scrollbar" id="60">滚动条
                <posx>1250</posx>
                 <posy>20</posy>
                 <width>25</width>
                 <height>590</height>
                 <onleft>8000</onleft>
                 <onright>9000</onright>
                 <texturesliderbackground border="0,14,0,14">ScrollBarV.png</texturesliderbackground>
                 <texturesliderbar border="2,16,2,16">ScrollBarV_bar.png</texturesliderbar>
                 <texturesliderbarfocus border="2,16,2,16">ScrollBarV_bar_focus.png</texturesliderbarfocus>
                 <textureslidernib>ScrollBarNib.png</textureslidernib>
                 <textureslidernibfocus>ScrollBarNib.png</textureslidernibfocus>
                 <onleft>500</onleft>   
                 <onright>2</onright>
                 <showonepage>false</showonepage>
                 <orientation>vertical</orientation>方向
            </control>
         </control>
3):界面需要实现的几个虚函数
头文件代码为:
复制内容到剪贴板
代码:
#include "GUIWindowVideoBase.h"
#include "ThumbLoader.h"
#include "GUIWindowVideoNav.h"
class CGUIWindowVideoThumbList : public CGUIWindowVideoBase
{
   public:
      
     CGUIWindowVideoThumbList(void);
     virtual ~CGUIWindowVideoThumbList(void);

     virtual bool OnAction(const CAction &action);动作回调函数,不怎么用到
    virtual bool OnMessage(CGUIMessage& message);消息回调函数,处理界面元素的点击消息,有点像android 的handler消息机制 

    virtual bool Update(const CStdString &strDirectory);当界面完成一个更新或者显示一开始显示时调用

     void LoadItemByDirectory(const CStdString &strDirectory);

      void LoadItemByDirectory(const CFileItemList &items);


  protected:
    virtual void OnInitWindow();初始化
   virtual void OnWindowLoaded();加载完毕后
   
    int GetWindowSeletectedItem(int iControl);
   
    CFileItemList* m_vecItems;
    CFileItemList* itemList;
    bool load_done;

   
    CFileItemList* page_index_list;

    CStdString previous_path;
   
    CStdString next_path;

    int pageIndex;


         }; [url="][/url]
以上几个有添加注释为必须实现函数,XBMC界面控制也基本在这几个回调函数里面进行。

4): 数据的加载或者填充
普通的控件如Button、Label之类的加载文字,可以直接使用预定义好的全局方法SET_CONTROL_LABEL(controlID,label)来做。
而列表加载需要做一个类型List的数据给CGUIMessage,代码为:
复制内容到剪贴板
代码:
[url="][/url]
bool CGUIWindowVideoThumbList::Update(const CStdString &strDirectory) {     
   
   //if(!load_done){

       CFileItemList list;
     GetDirectory("plugin://plugin.video.XuZhiTV",list);通过获取目录得到python插件的数据目录

    itemList->Clear();
     for(int i=0;i<list.Size();i++){循环填充进itemList
           
       CFileItemPtr pItem = list.Get(i);
         
       if(strcmp(pItem->GetLabel().c_str(),"..")==0)
         continue;
         CFileItemPtr cateItem(new CFileItem(pItem->GetLabel()));
         cateItem->SetPath(pItem->GetPath());
         itemList->Add(cateItem);
       }
   通过消息将列表广播出去,加载列表
      CGUIMessage msg(GUI_MSG_LABEL_BIND, GetID(), CONTROL_LOAD_CATEGORY_LIST_ID, 0, 0, itemList);
       g_windowManager.SendMessage(msg);

//--------------------end------------------------

//-------------item list---------------------------
     CFileItemList firstList;
      GetDirectory(itemList->Get(0)->GetPath(),firstList);得到插件目录的子目录
//-------------------end-----------------------


    /*  load_done=true;
   */

     LoadItemByDirectory(firstList); 加载子项

  //}
  return true;
}


LoadItemByDirectory方法代码:
void CGUIWindowVideoThumbListadItemByDirectory(const CFileItemList &items){
     m_vecItems->Clear();
     page_index_list->Clear();
      for (int i=0;i<items.Size(); ++i)
       {
           CFileItemPtr pItem = items.Get(i);
         if(strcmp(pItem->GetLabel().c_str(),"..")==0)
             continue;
         CFileItemPtr item(new CFileItem(pItem->GetLabel()));
         item->SetThumbnailImage(pItem->GetThumbnailImage());获取网络上的图片给上面panel 的image
          item->SetPath(pItem->GetPath());
         
         if(pItem->GetLabel().Find("|")>0){
             item->SetIntParam(-1);
             CFileItemPtr ptr(new CFileItem(pItem->GetLabel())); 获取label给上面panel 的label
             ptr->SetPath(pItem->GetPath());
             page_index_list->Add(ptr);
             continue;
         }else{
             item->SetIntParam(0);
         }
         item->SetIconImage("DefaultVideoCover.png");
         
         item->SetLabelPreformated(true);
         
         m_vecItems->Add(item);
       }广播消息加载内容
     CGUIMessage refresh(GUI_MSG_LABEL_BIND, GetID(), CONTROL_LOAD_ITEM_LIST_ID, 0, 0, m_vecItems);
      bool isRefresh= g_windowManager.SendMessage(refresh);
      if(isRefresh){
         
          int m_size=page_index_list[0].Size();
         CFileItemPtr ptr=page_index_list[0].Get(0);
         if(m_size==0){
             SET_CONTROL_HIDDEN(CONTROL_NEXT_ID);
             SET_CONTROL_HIDDEN(CONTROL_PREVIOUSE_ID);
             SET_CONTROL_LABEL(CONTROL_PAGE_COUNT_ID,"");
         }else{
             SET_CONTROL_LABEL(CONTROL_PAGE_COUNT_ID,ptr->GetLabel().Right(6));
             SET_CONTROL_VISIBLE(CONTROL_NEXT_ID);
             SET_CONTROL_VISIBLE(CONTROL_PREVIOUSE_ID);
         }
         
         switch(m_size){
             case 0:
                 previous_path="";
                 next_path="";
                 break;
             case 1:{
                     CStdString control_text=ptr->GetLabel().Left(ptr->GetLabel().Find("|"));
                     if(strcmp(control_text,"down")==0){
                         next_path=ptr->GetPath();
                     }else{
                         previous_path=ptr->GetPath();
                     }
                 }
                 break;
             case 2:
                 previous_path=ptr->GetPath();
                 next_path=page_index_list[0].Get(1)->GetPath();
                 break;
         }
      }
}
5):点击事件的处理

点击事件可以重写onclick,也可以由OnMessage函数处理,都可以。处理非常简单代码为:
复制内容到剪贴板
代码:
bool CGUIWindowVideoThumbList::OnMessage(CGUIMessage& message)
{
     if (message.GetMessage() == GUI_MSG_CLICKED)消息类型为点击时,message不止可以处理点击,还有很多事件可以处理。
    {
     int iControl = message.GetSenderId();获得点击控件的ID
    if(iControl == 2000){ID等于2000时
       //处理点击时响 应的代码
    }
   }
     return CGUIWindowVideoBase::OnMessage(message); }
希望对移植xmbc的android 开发者有帮助  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值