FBReaderJ学习笔记(二):PopWindow实现自定义阅读页菜单

  很少写技术博客,最常用的博客还是Lofter这个:chacePM。非技术博客。

  另外基于FBReaderJ本人开发了一个阅读器:悦读。有兴趣的朋友可以去安装看看,支持一下。

  以下是实现的菜单截图。

 

  MainMenuPopup

  FBReaderJ学习笔记(二):PopWindow实现自定义阅读页菜单

 

  ConfigPopup

  FBReaderJ学习笔记(二):PopWindow实现自定义阅读页菜单

  本文使用的是FBReaderJ-2.2.2.1

 

 注意:本文不涉及具体界面设计,只谈思路。

 

  1.结构

  在正式动手改代码前,我们最好先搞清楚几个PopWindow的结构和继承关系,因为FBReaderJ的封装严密,容易走入死胡同。FBReaderJ学习笔记(二):PopWindow实现自定义阅读页菜单

  整个跟popup相关的类结构大概就是这样,其中红色的为抽象类。命名很清楚,我就不解释每一个是干嘛的了。

  我们要实现自定义popwindow菜单,可以模仿NavigationPopup的做法,写一个MainMenuPopup继承自PopupPanel。

  2.原理

  我们打开assets目录,发现在下面的目录里定义了tapzones。

  FBReaderJ学习笔记(二):PopWindow实现自定义阅读页菜单

  打开down.xml,发现内容是这样的。这下明白阅读页面的点击事件是怎么回事了吧,其实就是把整个区域划分为九宫格,每个格子响应不同的事件。为了让我们的菜单显示,只要把这里的menu全改成navigate,再在代码里实现navigate响应事件为显示我们的自定义菜单。其实我们看到这里是少了(1,1)区域的,不知道是原作者为什么弄成这样,为了更好的体验,我们需要加上(1,1)也响应navigate。

FBReaderJ学习笔记(二):PopWindow实现自定义阅读页菜单

  3.两个PopWindow同时显示的解决方案

  在我们的菜单里,是同时包含顶部菜单和底部菜单,如何解决这个问题呢?

  一种直观的方式当然是弄两个菜单,BottomMenuPopup和TopMenuPopup都继承自PopupPanel,我最开始也是这么想的,但是问题就来了,PopupPanel的显示是用的Application.showPopup(ID)。代码如下,发现在show之前会先调用hideActivePopup(),这样我们show第二个Popup的时候会先把第一个Popup隐藏掉。

    public final void showPopup(String id) {
        hideActivePopup();
        myActivePopup = myPopups.get(id);
        if (myActivePopup != null) {
            myActivePopup.show_();
        }
    }

  我们当然可以把这行去掉,但这会导致我们每次显示其他Popup的时候都得先调用hideActivePopup,出于少改动代码的目的,我放弃了这种方法。

  第二种方法是单独弄一个TopMenuPopup而不继承PopupPanel,但是我尝试了一下后发现会更麻烦,什么时候显示什么消失一团糟。

  最后我想到的方法是,在PopupPanel里面增加一个myWindowTop。这样我们就有两个PopupWindow,但是都显示在一个PopupPanel子类里,我们命名为MainMenuPopup。

    protected volatile PopupWindow myWindow;
    protected volatile PopupWindow myWindowTop;

  4.切换PopupPanel

  上面解决了MainMenuPopup的显示,但是其实我们是包含多个PopupPanel的,这就涉及到切换问题。我们以MainMenuPopup和NavigationPopup的切换为例。

下面的代码是用来显示NavigationPopup的,上面说过,在showPopup(ID)方法里会先调用hideActivePopup(),所以这里的切换不成问题。

((NavigationPopup)Application.getPopupById(NavigationPopup.ID)).runNavigation();

  另一个问题是显示和隐藏Popup,因为点击书本,对应的都是navigate()方法,所以我们需要判断点击时到底该显示还是隐藏。好在FBReaderJ已经有一个方法Application.getActivePopup()来获得当前显示的Popup,只要判断是否为空即可。所以在MainMenuPopup里面的showBottomMenu()方法是这样的。

    public void showBottomMenu(){
        if (myWindow == null || myWindow.getVisibility() == View.GONE){
            if(Application.getActivePopup()==null){
                Application.showPopup(ID);
            }else{
                Application.hideActivePopup();
            }
        }else{
            Application.hideActivePopup();
        }
    }

  5.结语

  FBReaderJ学习笔记(二):PopWindow实现自定义阅读页菜单

  现在的结构就是这样了,增加了一个MainMenuPopup。

  大致的流程就是更改tapzones->新建MainMenuPopup->新增myPopWindowTop->判断显示/隐藏popup

  到此思路基本已经理清了,开头就说过,本文不涉及具体界面开发,开头的截图仅作演示,千万不要有上当受骗的感觉。

  实现自定义菜单的方式有很多种。比如顶部的菜单可以用Actionbar来实现,FBReaderJ的ics版本就是这样做的;或者在XML里面直接在ZLViewWidget外放上底部和顶部菜单。本文的方法只是一种。我说的不明白的地方,以及不足之处,欢迎与我探讨交流。

 

  另外,基于FBReaderJ本人开发了一个阅读器:悦读。有兴趣的朋友可以去安装看看,支持一下。

 

  下一篇讲底部状态栏的自定义。

FBReaderJ学习笔记(二):PopWindow实现自定义阅读页菜单

上一篇:DelphiXE7 FMX 退出程序写法!


下一篇:Windows live Writer Tips