精华内容
下载资源
问答
  • Drupal 7 模块开发,为模块建立帮助文档,使用 hook_help,及参数 arg() 介绍

    建立模块请参考 《Drupal 7 模块开发 建立

    如果你要支持中文,文件格式必须保存为 UTF-8,NO BOM

    ------------------------------

    hook_help 为用户提供此模块的帮助信息。我们要用自己模块名替换 hook。在这里我们建立一个 my_first_module_help 在 my_first_module.module文件里

    function my_first_module_help($path, $arg) {
    }

      参数:  

    $path 是指需要添加的帮助信息的所在路径:

    • 为模块自己写一个帮助文件,使用路径:admin/help#module_name module_name就是你的模块名
    • 指定路径:admin/people  user/register
    • 路径可以使用通配符 %,譬如:node/% 或者 node/%/view

    $arg()  是对应于arg() 函数返回值的数组,当$path里有通配符(%)时候会可以用到,来满足特殊要求。

    譬如,你 $path 用到了 node/%/edit,当你访问 node/1/edit,$arg[0] == 'node', $arg[1] == '1', $arg[2] == 'edit'。

    具体 arg() 解释可以访问:https://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/arg/7

    当你建立 hook_help 的时候,arg[0]到arg[11]已经建立,只是这些数组内的值都是空(empty)

      返回值:  

    返回本地化的字符串到帮助文档。

      举例:  

    我要给My First Module写一个帮助模块。

    <?php
    
    function my_first_module_help($path, $arg) {
      switch ($path) {
        case "admin/help#my_first_module":
          $output = '<p>' . t("这是My First Module的帮助文档")  . '</p>';
          return $output;
          break;
      }
    } 

    注意:结尾不要写 ?>

    • Druap核心模块,会自动把admin/help#my_first_module转换成 admin/help/my_first_module
    • 在$output里用到 t("xxxxxxx"),在使用翻译模块的时候,可以翻译成其他语言,不用修改代码。

      检查运行结果: 

    以管理员身份,登录你的Drupal网站,点 Modules,你会进入 admin/modules 页面。在 Other 分类下找到 My First Module,激活此模块后,你会发现一个多一个 Help 链接

    点击 Help 后就会进入我们创建的 帮助页面

      arg() 测试:  

    修改代码

    function my_first_module_help($path, $arg) {
      switch ($path) {
        case "admin/help#my_first_module":
          $output = '<p>' . t("这是My First Module的帮助文档") . '</p>';
          return $output;
          break;
        case "node/%/edit":
          $output = '这里是 ' . $arg[0] . ' ' . $arg[1] . ' ' . $arg[2] . '帮助信息';
          return $output;
          break;
      }
    } 

      检查 arg() 运行结果: 

    建立一个页面(点击 Add Conent -> Basic page,进入 node/add/page),保存后,再点击编辑(Edit),这时候你就能看到下面显示


      更多详细资料:  

    • 模块的一般帮助(overview help),参考 node_help().
    • 特定网页的帮助,单一简单路径,参考 dashboard_help()
    • 特定网页的帮助,如果路径里有通配符或者$arg,参考node_help() 和block_help()
    
    展开全文
  • 建立模块请参考 《Drupal 7 模块开发 建立》 如果你要支持中文,文件格式必须保存为 UTF-8,NO BOM ------------------------------ hook_menu 定义菜单项和页面反馈。 我们要用自己模块名替换 hook。在这里我们建立...

    建立模块请参考 《Drupal 7 模块开发 建立

    如果你要支持中文,文件格式必须保存为 UTF-8,NO BOM

    ------------------------------

    hook_menu 定义菜单项和页面反馈。

    我们要用自己模块名替换 hook。在这里我们建立一个 my_first_module_menu() 在 my_first_module.module文件里

    <?php
    
    function my_first_module_menu() {
      $items = array();
      
      $items['mypage'] = array(
        'title' => '第一个模块 —— 页面', //菜单项的名称
        'description' => '我的第一个模块页面', //当鼠标移动到菜单项,显示菜单的说明
        'page callback' => 'my_page_view', //产生页面内容
        'access callback' => TRUE, //所有人都能访问
        'type' => MENU_NORMAL_ITEM, //菜单项显示类型
      );
      
      return $items;
    }
    
    function my_page_view() {
      $output = t('这是模块做的第一个页面。');
    
      return $output;
    }
    

    注意:结尾不要写 ?>

    清空Cache,然后访问 http://www.mysite.com/?q=mypage ,会看到下图

    (事实上,这时你访问任何 http://www.mysite.com/?q=mypage/aaa/bbb 都会访问到这个page)

    $items[] 路径

    • $items先在 [ ] 里定义路径,在访问 /mypage 页面时候,去调用 my_page_view 函数产生页面
    • 每一个$items都是对应一个路径,写在 [ ] 里。当item用一样路径时候,就调用后写那个$items的。(有文章说和$items里参数weight有关,我测试weight不会影响先后次序)

    • [ ] 里也可以用通配符,譬如: [node/%/edit]。详细参见:function hook_menu 里的Wildcards in Paths一段

    title 必须

    未翻译的主题

    title callback

    产生主题的函数。默认是 t()。如果你不想翻译,就设置FALSE (所以我们不必再写 'title' => t('第一个表单')

    title arguments

    传递到 t() 或者 你自定义函数 的参数。可以和路径组件结合
    参考:Menu item title and description callbacks, localization

    description

    未翻译的说明描述。

    page callback

    当用户访问页面路径的时候,调用一个显示网页的函数。

    如果不写,父菜单的回调函数将代替执行。也就是说 $items['mypage'] 和 $items['mypage/child'] 会执行一样内容。

    有一个特别回调函数 drupal_get_form(),这个将在后面 Drupal 7 模块开发 建立、验证、提交表单(Form) 具体讲

    page arguments

    传递给 page callback 函数的一串参数数组,上面例子没用用到,我们稍加修改:

    • 修改一下 $items,路径成为 $items['mypage/%/edit'],意思是当访问 mypage/1/edit,或者 mypage/2/edit 等,执行此函数
    • 添加 page arguments:'page arguments' => array('hello', 1),
      ‘hello' 作为一个常量传给 $arg1
      1 表示路径mypage后面第一层:当你访问 mypage/1/edit 时候,返回就是 1;如果你访问 mypage/world/edit,返回就是world
    • 给函数 my_page_view增加传递参数, function my_page_view($arg1, $arg2)

    修改后,完整代码如下:

    <?php
    
    function my_first_module_menu() {
      $items = array();
      
      $items['mypage/%/edit'] = array( //修改路径
        'title' => '第一个模块 —— 页面',
        'description' => '我的第一个模块页面',
        'page callback' => 'my_page_view',
        'page arguments' => array('hello', 1), //添加参数
        'access callback' => TRUE,
        'type' => MENU_NORMAL_ITEM,
      );
      
      return $items;
    }
    
    function my_page_view($arg1, $arg2) { //添加参数传递
      $output = t('这是模块做的第一个页面。');
      $output .= '<br />' . $arg1 . ' ' . $arg2; //打印参数
      return $output;
    }


    清空Cache,然后访问 http://www.mysite.com/?q=mypage/world/edit ,会看到下图

    access callback

    如果有访问这页权限,就要返回TRUE,否则就FALSE(如果不写,默认是FALSE)。如果false,页面就会出现 Access denied 提示。

    type

    描述菜单项属性的代码。许多快捷代码的常量在 menu.inc 里。

    我们这里用了默认项 MENU_NORMAL_ITEM,所以$items里可以不写 'type' => MENU_NORMAL_ITEM,

    常用几种:

    • MENU_NORMAL_ITEM,显示在Navigation菜单列表下,管理员可以拖动或隐藏
    • MENU_SUGGESTED_ITEM,和MENU_NORMAL_ITEM一样,只是默认状态是Disabled的,需要管理员去手工Enabled
    • MENU_CALLBACK 不会产生菜单和面包屑(Breadcrumbs)。只是简单注册一个路径,当路径被访问时,执行相应功能。通常是被API调用。
    • MENU_LOCAL_ACTION 在父菜单里,显示一个link,引导下步操作。譬如:添加一个菜单
    • MENU_LOCAL_TASK 也是作为一个link,不过通常是以标签(TAB)格式显示
    • MENU_DEFAULT_LOCAL_TASK 和 MENU_LOCAL_TASK 一样是标签(TAB),不过是默认标签,和父菜单路径一样(这个itmes的路径只是表达是父菜单)

    想深入了解,可以打开目录下 /modules/menu/menu.modules文件,然后结合http://www.yoursite.com/?q=admin/structure/menu/manage/navigation,帮助你了解

    file

    在页面回调前,这个文件已经被包含。允许页面回调函数在另一个分开的文件里。除非这个在“file path”已经指定路径,否则这个文件在执行模块的同一个目录里。这个文件不适合其他回回调(call back),只适用于 page callback

    file path

    这是指定file所在目录。默认路径是当前模块执行hook所在路径

    menu_name

    如果你不要把这个菜单项放在Navigation下,就可以在这里指定。譬如:'menu_name' => 'main-menu',这样就会和Home一起出现在主菜单上

    (更多参数,慢慢完善)

    
    
    展开全文
  • Floodlight 入门 之 起步篇 - 建立一个Floodlight模块

    千次阅读 热门讨论 2017-03-01 11:53:52
    Floodlight 入门 之 起步篇 - 建立一个Floodlight模块 2017-3-1 网上也有不少关于Floodlight的入门教程了,我写该博文的目的主要是问了整理个人在学习和使用Floodlight时掌握的知识,如果这些文字能为大家带来帮助是...

    Floodlight 入门 之 起步篇 - 建立一个Floodlight模块

    • 2017-3-1

    网上也有不少关于Floodlight的入门教程了,我写该博文的目的主要是问了整理个人在学习和使用Floodlight时掌握的知识,如果这些文字能为大家带来帮助是最好不过的了。

    博文会持续更新,如果想要跟踪该博文的进度,推荐使用RSS。每次更新会在博文开始出更改时间戳。

    该博文系列是从Floodlight官网的官方教程翻译而来,想嚼原味教程请点击链接Tutorials


    前提条件

    我们在进行下面的实验前,首先要检查我们的实验环境是否满足下面的条件:

    • 成功地完成了Getting Started的教程,包括配置Eclipse。
    • 安装了Mininet或者有一个可以使用的OpenFlow物理交换机。

    确保满足上述条件后,就可以进行下面的实验了。

    创建一个监听器

    在Eclipse中添加一个Class

    1. 展开floodlight项,你会看到“src/main/java”文件夹。
    2. 选中“src/main/java”文件夹,然后右击,在弹出的菜单中选中 “New/Class”。
    3. 在“Package”栏写入net.floodlightcontroller.mactracker。
    4. 在“Name”栏写入MACTracker。
    5. 然后就是“Interfaces”栏,我们点击旁边的“Add..”为该类添加接口。
    6. 添加”IOFMessageListener”和”IFloodlightModule”,然后点击OK。
    7. 点击“Finish”完成类的创建。

    上面的步骤完成后,你将会看到下面的代码:

    package net.floodlightcontroller.mactracker;
    
    import java.util.Collection;
    import java.util.Map;
    
    import org.projectfloodlight.openflow.protocol.OFMessage;
    import org.projectfloodlight.openflow.protocol.OFType;
    import org.projectfloodlight.openflow.types.MacAddress;
    
    import net.floodlightcontroller.core.FloodlightContext;
    import net.floodlightcontroller.core.IOFMessageListener;
    import net.floodlightcontroller.core.IOFSwitch;
    import net.floodlightcontroller.core.module.FloodlightModuleContext;
    import net.floodlightcontroller.core.module.FloodlightModuleException;
    import net.floodlightcontroller.core.module.IFloodlightModule;
    import net.floodlightcontroller.core.module.IFloodlightService;
    
    public class MACTracker implements IOFMessageListener, IFloodlightModule {
    
        @Override
        public String getName() {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public boolean isCallbackOrderingPrereq(OFType type, String name) {
            // TODO Auto-generated method stub
            return false;
        }
    
        @Override
        public boolean isCallbackOrderingPostreq(OFType type, String name) {
            // TODO Auto-generated method stub
            return false;
        }
    
        @Override
        public Collection<Class<? extends IFloodlightService>> getModuleServices() {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public void init(FloodlightModuleContext context)
                throws FloodlightModuleException {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public void startUp(FloodlightModuleContext context) {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
            // TODO Auto-generated method stub
            return null;
        }
    
    }

    设置模块依赖项和初始化

    在我们开始之前,我们需要为我们创建的代码设置一系列的依赖项。使用Eclipse的话,添加这些依赖项会很容易。如果你没有使用Eclipse来编写代码,你就需要手动将下面的依赖项添加到java文件的开头:

    import net.floodlightcontroller.core.IFloodlightProviderService;
    import java.util.ArrayList;
    import java.util.concurrent.ConcurrentSkipListSet;
    import java.util.Set;
    import net.floodlightcontroller.packet.Ethernet;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    现在我们有了必需的依赖项,而且通过之前创建类的操作,我们有了一个有框架的类。然而这样的类肯定还是不能正常使用的,我们需要实现一些方法来确保我们创建的模块可以被加载。首先,我们需要在该类中添加一些必要的成员变量。我们现在要创建的模块是要实现跟踪MAC地址的功能,所以我们需要监听Openflow messages,需要添加一个FloodlightProvider((IFloodlightProviderService class)。我们还需要一个数据结构存储我们监听到的MAC地址,需要一个logger来输出我们监听到的信息。最后我们需要的成员变量如下所示:

    protected IFloodlightProviderService floodlightProvider;
    protected Set<Long> macAddresses;
    protected static Logger logger;

    现在我们需要完成模块被加载的功能。我们对getModuleDependencies()方法进行更改,以此来告诉模块加载器我们依赖于它:

    @Override
    public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
        Collection<Class<? extends IFloodlightService>> l =
            new ArrayList<Class<? extends IFloodlightService>>();
        l.add(IFloodlightProviderService.class);
        return l;
    }

    现在我们的模块可以被加载了。一般来说,一个模块被加载时是要进行初始化的。所以接下来我们来对初始化方法进行实现:

    @Override
    public void init(FloodlightModuleContext context) throws FloodlightModuleException {
        floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
        macAddresses = new ConcurrentSkipListSet<Long>();
        logger = LoggerFactory.getLogger(MACTracker.class);
    }

    处理Packet-In消息

    经过上面的操作,我们的模块已经可以作为一个模块正常的运行了。然而我们的目的是创建一个能跟踪MAC地址的模块,所以我们接下来还要对模块的功能进行实现。首先,我们需要实现一个简单的监听器(用来监听OpenFlow消息)。我们将会在我们的startUp方法中注册一个监听PACKET_IN消息的监听器。这里我们假定我们依赖的其他模块已经初始化好了:

    @Override
    public void startUp(FloodlightModuleContext context) {
        floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
    }

    我们还须要为我们的OFMessage监听器放入一个ID什么的(原文:We also have to put in an ID for our OFMessage listener.)。这里可以在在回调函数getName()中完成:

    @Override
    public String getName() {
        return MACTracker.class.getSimpleName();
    }

    现在我们就可以叫我们的PACKET_IN消息与特定的行为进行绑定了。这在receive方法中实现,注意:我们这里要返回Command.CONTINUE,这样在我们之后模块才可以继续执行针对该PACKET_IN消息的操作:

    @Override
       public net.floodlightcontroller.core.IListener.Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
            Ethernet eth =
                    IFloodlightProviderService.bcStore.get(cntx,
                                                IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
    
            Long sourceMACHash = eth.getSourceMACAddress().getLong();
            if (!macAddresses.contains(sourceMACHash)) {
                macAddresses.add(sourceMACHash);
                logger.info("MAC Address: {} seen on switch: {}",
                        eth.getSourceMACAddress().toString(),
                        sw.getId().toString());
            }
            return Command.CONTINUE;
        }

    在处理Openflow消息是模块的序列

    这一段说明在该教程中并不是必要的,但当我们用IOFMessageListeners处理OpenFlow消息时,定义处理顺序往往是必要的。IOFMessageListeners的isCallbackOrderingPrereq(OFType type, String name)和isCallbackOrderingPostreq(OFType type, String name)方法定义了处理来自交换机的消息的模块的处理顺序。

    isCallbackOrderingPrereq()定义了在处理某一类的OpenFlow消息时,哪些模块应该跑在我们的模块前。 isCallbackOrderingPostreq()定义了在处理某一类的OpenFlow消息时,哪些模块应该跑在我们的模块后。

    注册模块

    经过上面的操作,我们差不多已经完成了模块的实现。现在我们只需要告诉Floodlight我们要在启动时加载该模块。首先我们要告诉加载器这些模块的存在。我们打开src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule,然后添加下面一行文字:

    net.floodlightcontroller.mactracker.MACTracker

    然后我们还需要修改配置文件src/main/resources/floodlightdefault.properties:

    floodlight.modules = <leave the default list of modules in place>, net.floodlightcontroller.mactracker.MACTracker

    最后,我们启动控制器(选中Run As…/Java Application,然后选中Main.java)。

    如何将Mininet与Floodlight控制器相连

    Floodlight默认的监听端口是6653(可以在配置文件中查看和修改src/main/resources/floodlightdefault.properties),我们连接Floodlight需要知道Floodlight所在主机的IP地址(如果是本地,就输入127.0.0.1或0.0.0.0),注意:好像只有Floodlight v1.2版本支持OpenFlow1.3协议,如果使用早期版本的Floodlight如v1.0,建议将protocols=OpenFlow13改为protocols=OpenFlow10

    mininet@mininet:~$ sudo mn --controller=remote,ip=<Floodlight IP Address>,port=6653 --switch=ovsk,protocols=OpenFlow13
    *** Loading ofdatapath
    *** Adding controller
    *** Creating network
    *** Adding hosts:
    h2 h3
    *** Adding switches:
    s1
    *** Adding edges:
    (s1, h2) (s1, h3)
    *** Configuring hosts
    h2 h3
    *** Starting controller
    *** Starting 1 switches
    s1
    *** Starting CLI:
    mininet>pingall

    连接成功后,输入pingall,则可以在Eclipse的Console中看到模块的输出信息。

    练习

    作为练习,我写了一个模块,但并不是MACtracer,而是监听所有Packet-In然后输出Payload,输出结果如下:

    13:56:05.521 INFO [n.f.p.m.NetMonitor:nioEventLoopGroup-3-4] Switch Id:00:00:00:00:00:00:00:01,Payload:IPv6 [version=6, trafficClass=0, flowLabel=0, payloadLength=16, nextHeader=0x3a, hopLimit=-1, sourceAddress=fe80::ac97:c0ff:fe0b:a39b, destinationAddress=ff02::2, parent=
    0x86dd
    dl_vlan: untagged
    dl_vlan_pcp: 0
    dl_src: ae:97:c0:0b:a3:9b
    dl_dst: 33:33:00:00:00:02
    nw_src: fe80::ac97:c0ff:fe0b:a39b
    nw_dst: ff02::2
    nw_tclass: 0
    nw_proto: 0x3a, payload=net.floodlightcontroller.packet.Data@da31eb25]
    13:56:08.717 INFO [n.f.p.m.NetMonitor:nioEventLoopGroup-3-4] Switch Id:00:00:00:00:00:00:00:01,Payload:IPv6 [version=6, trafficClass=0, flowLabel=0, payloadLength=16, nextHeader=0x3a, hopLimit=-1, sourceAddress=fe80::ac7d:88ff:fe59:6165, destinationAddress=ff02::2, parent=
    0x86dd
    dl_vlan: untagged
    dl_vlan_pcp: 0
    dl_src: ae:7d:88:59:61:65
    dl_dst: 33:33:00:00:00:02
    nw_src: fe80::ac7d:88ff:fe59:6165
    nw_dst: ff02::2
    nw_tclass: 0
    nw_proto: 0x3a, payload=net.floodlightcontroller.packet.Data@f8ec7dee]
    13:56:09.529 INFO [n.f.p.m.NetMonitor:nioEventLoopGroup-3-4] Switch Id:00:00:00:00:00:00:00:01,Payload:IPv6 [version=6, trafficClass=0, flowLabel=0, payloadLength=16, nextHeader=0x3a, hopLimit=-1, sourceAddress=fe80::ac97:c0ff:fe0b:a39b, destinationAddress=ff02::2, parent=
    0x86dd
    dl_vlan: untagged
    dl_vlan_pcp: 0
    dl_src: ae:97:c0:0b:a3:9b
    dl_dst: 33:33:00:00:00:02
    nw_src: fe80::ac97:c0ff:fe0b:a39b
    nw_dst: ff02::2
    nw_tclass: 0
    nw_proto: 0x3a, payload=net.floodlightcontroller.packet.Data@da31eb25]
    
    展开全文
  • 手把手带你撸一个校园APP(五):新闻中心模块

    千次阅读 多人点赞 2020-02-09 15:35:45
    手把手带你撸一个校园APP(五):新闻中心模块 手把手带你撸一个校园APP(六):失物招领&二手交易模块 手把手带你撸一个校园APP(七):图说校园模块 手把手带你撸一个校园APP(八):校园通讯录模块 ...

    这个项目是很早之前在学校做的,如今再回首。很多代码很是粗糙,逻辑也不尽完善。还望各位看官海涵。

    前言

    通过上一篇文章的功能设计,我们可以发现新闻通知公告等是APP的最主要功能点。主要是聚合展示学校官网的通知公告,官方微信,微博的重要信息,学校社团的活动,以及学校优秀自媒体的文章等等。

    系列文章:

    1. 手把手带你撸一个校园APP(一):项目简介
    2. 手把手带你撸一个校园APP(二):应用启动和欢迎页面
    3. 手把手带你撸一个校园APP(三):用户模块(登录注册等)
    4. 手把手带你撸一个校园APP(四):APP框架及功能设计
    5. 手把手带你撸一个校园APP(五):新闻中心模块
    6. 手把手带你撸一个校园APP(六):失物招领&二手交易模块
    7. 手把手带你撸一个校园APP(七):图说校园模块
    8. 手把手带你撸一个校园APP(八):校园通讯录模块
    9. 手把手带你撸一个校园APP(九):课程表模块(模拟登陆爬取教务处课程信息)
    10. 手把手带你撸一个校园APP(十):APP通用模块(更新,意见反馈等)

    实现效果

    新闻部分主要是分了“通知公告”,“新闻速递”,“自媒体”,“校园文化”四个栏目,之间可以通过左右滑动进行切换。效果图如下:
    科师有约新闻模块

    分析

    其实这是挺常见的一个新闻资讯模块。我们也可以轻易得出以下内容:

    1. 新闻条目 一般都有标题,配图,作者,发表时间等组成。我们的新闻只是聚合展示使用,可以外加一个资讯链接;
    2. 配图数量并不一致,有无图的,1 张配图的,以及 3 张配图的。我们需要根据配图的数量进行不同布局的设置;
    3. 新闻列表应该拥有下拉刷新,上拉加载的功能。

    实现

    本项目基于Bmob进行开发,很多地方需要Bmob相关知识。大家如果没了解过的话,可先自行查看 Bmob开发文档

    数据库

    当初设计数据库字段的时候,很多东西都为了简单,没有做更合理的规划。字段如下:

    字段名 描述 类型 主键
    objectId 用户id String
    title 标题 String
    author 作者 String
    time 发布时间 String
    kind 栏目分类 String
    content 内容链接 String
    pic1 缩略图一 String
    pic2 缩略图二 String
    pic3 缩略图三 String
    tag 布局样式(图片数量) String

    大家如果自己从头来的话,建议适当更改部分字段的类型以及组合方式,会更合理些。比如time改为时间类型,图片改为列表等。本文暂且不表。

    安卓

    逻辑流程讲解

    本模块逻辑设计如下:

    1. 使用CoordinatorTabLayout + ViewPager + Fragment 完成新闻模块主页面的显示;
    2. Fragment 进行网络请求,获取新闻数据并展示,使用 RecyclerView 展示新闻列表,根据缩略图数量对应3种条目布局;
    3. 新闻详情页面使用WebView 用于展示新闻详情。

    代码实现

    在这里为了能快速开发,我们使用了 CoordinatorTabLayout 。

    文章:CoordinatorTabLayout组件库
    Github地址:CoordinatorTabLayout
    作者:hugeterry

    使用 CoordinatorTabLayout 搭建新闻主页面

    使用步骤如下:

    1. 在 app 的 build.gradle 中添加依赖
    dependencies {
        implementation 'cn.hugeterry.coordinatortablayout:coordinatortablayout:1.2.2'
    }
    
    1. 布局文件中使用
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <cn.hugeterry.coordinatortablayout.CoordinatorTabLayout
            android:id="@+id/cootablayout_news"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <android.support.v4.view.ViewPager
                android:id="@+id/vp_news"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:layout_behavior="@string/appbar_scrolling_view_behavior" />
        </cn.hugeterry.coordinatortablayout.CoordinatorTabLayout>
    
    </RelativeLayout>
    
    1. 在 java 代码中使用
    // 四个栏目标题
    String[] mTitles = {"通知公告", "新闻速递", "自媒体", "校园文化"}
    // 初始化 Fragment 列表
    ArrayList<Fragment> mFragments = new ArrayList<>();
    mFragments.add(MainFragment1.getInstance(mTitles[0]));
    mFragments.add(MainFragment2.getInstance(mTitles[1]));
    mFragments.add(MainFragment3.getInstance(mTitles[2]));
    mFragments.add(MainFragment4.getInstance(mTitles[3]));
    
    // 设置Viewpager
    mViewPager.setOffscreenPageLimit(4);
    mViewPager.setAdapter(new MyPagerAdapter(getChildFragmentManager(), mFragments, mTitles));
    
    // 设置顶部 展开后 4 张背景图
    mImageArray = new int[]{
            R.mipmap.keshi1,
            R.mipmap.keshi4,
            R.mipmap.img_bg_news3,
            R.mipmap.img_bg_news4};
    // 设置顶部 收缩后 4 种背景色
    mColorArray = new int[]{
            android.R.color.holo_blue_light,
            android.R.color.holo_red_light,
            android.R.color.holo_orange_light,
            android.R.color.holo_green_light};
    // 设置 CoordinatorTabLayout 属性
    mCoordinatorTabLayout.setTransulcentStatusBar(mActivity)
            .setTitle("")
            .setImageArray(mImageArray, mColorArray)
            .setupWithViewPager(mViewPager);
    
    网络请求,数据填充
    1. 建立数据库对应表 bean 类
    public class NewsBean extends BmobObject {
        private String title;
        private String author;
        private String time;
        private String tag;
        private String pic1;
        private String pic2;
        private String pic3;
        private String content;
        
        // ....get set 方法
    }
    
    1. 网络请求数据,并填充
    mAdapter = new NNNAdapter();
    newsBeanList = new ArrayList<>();
    BmobQuery<NewsBean> query = new BmobQuery<NewsBean>();
    query.order("-time");
    // kind: [a="通知公告", b="新闻速递", c="自媒体", d="校园文化"]
    query.addWhereEqualTo("kind", "a");
    query.setLimit(10);
    query.findObjects(new FindListener<NewsBean>() {
        @Override
        public void done(List<NewsBean> object, BmobException e) {
            if (e == null) {
                for (NewsBean newsBean : object) {
                    newsBeanList.add(newsBean);
                    LogUtils.e(newsBean.getAuthor());
                }
                mAdapter.setData(newsBeanList);
            } else {
            }
        }
    });
    mRecyclerView.setAdapter(mAdapter);
    
    1. 图片数量不同对应不同的布局
    public class NewsBean extends BmobObject implements IMultiItem {
    
        @Override
        public int getLayoutRes() {
            if ("3".equals(tag)) {
                return R.layout.item_news_type3;
            } else if ("2".equals(tag)) {
                return R.layout.item_news_type2;
            } else {
                return R.layout.item_news_type1;
            }
        }
        // 省略其它...
    }
    
    1. 新闻详情页面
      Fragment 中给 RecycleView 设置点击事件,传递网址到详情Activity
    mAdapter.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(@NonNull View view, int position) {
            Intent intent = new Intent(getActivity(), NewsWebActivity.class);
            intent.putExtra("url", newsBeanList.get(position).getContent());
            startActivity(intent);
        }
    });
    

    网页详情页面 NewsActivity 中只有一个WebView。接收上个页面传递过来的参数,并且展示页面。这里做了一些初始化操作,大家在别处需要的话,也可以直接复制过去

    String url = getIntent().getStringExtra("url");
    if (TextUtils.isEmpty(url)) {
        Toast.makeText(this, "该新闻已经失效!", Toast.LENGTH_SHORT).show();
        return;
    }
    MyWebViewClient myWebViewClient = new MyWebViewClient();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        wvNews.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
    }
    wvNews.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);//设置js可以直接打开窗口,如window.open(),默认为false
    wvNews.getSettings().setJavaScriptEnabled(true);//是否允许执行js,默认为false。设置true时,会提醒可能造成XSS漏洞
    wvNews.getSettings().setSupportZoom(true);//是否可以缩放,默认true
    wvNews.getSettings().setBuiltInZoomControls(true);//是否显示缩放按钮,默认false
    wvNews.getSettings().setUseWideViewPort(true);//设置此属性,可任意比例缩放。大视图模式
    wvNews.getSettings().setLoadWithOverviewMode(true);//和setUseWideViewPort(true)一起解决网页自适应问题
    wvNews.getSettings().setAppCacheEnabled(true);//是否使用缓存
    wvNews.getSettings().setDomStorageEnabled(true);//DOM Storage
    wvNews.setWebChromeClient(new WebChromeClient());
    wvNews.setWebViewClient(myWebViewClient);
    wvNews.loadUrl(url);
    
    // ....
    private class MyWebViewClient extends WebViewClient {
        //重写父类方法,让新打开的网页在当前的WebView中显示
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }
    }
    
    

    至此,新闻模块页面基本完成。还有就是本文挺长的,很感谢你可以看到这里。

    如果本文对你有所帮助,还望可以随手赏一个点赞哈 ~ ~

    展开全文
  • LDD3学习笔记(2):建立和运行模块

    千次阅读 2011-07-06 20:07:15
    1、建立开发环境在开始编写代码以及研究代码之前,你需要有一个开发环境,也就是一个linux系统。通常我们的做法是在windows下安装一个虚拟机软件,然后在虚拟机软件中安装一个linux系统的发行版本,在众多的发行版本...
  • 1_建立和运行一个简单的模块

    千次阅读 2011-08-15 00:04:50
    建立和运行一个简单的模块 1 源代码 hw.c文件 #include #include MODULE_LICENSE("Dual BSD/GPL"); static int __init init_hw(void) { printk(KERN_ALERT "Hello, I'm Octagram.\n"); return 0; } ...
  • 往往在pycharm中工作要创建很多文件,文件一多而且如果要连接数据库的话,有很多代码都是一样的,为了不必要的麻烦,可以新建一个模块...下面就讲讲连接mysql数据库时创建一个模块帮助处理数据库中表的数据。 1...
  • peewee通过Database类及其子类来建立数据库对象,目前peewee支持的数据库有Postgres, MySQL,MySQL,SQLite 以及BerkeleyDB。这里我们仅通过MySQL来进行了解,如果对其他数据库类型的相关内容感兴趣可以参见官方...
  • 我之前用的Gradle作为编译器,导致了开启服务器时,Tomcat找不到web模块,就会导致开启服务器时候报类似 XXXX.war not found for the web module 的错误 因为Gradle编译器不会给你自动创建exploded目录,但是Tomcat...
  • Odoo10 开发者文档(3)--建立一个模块·

    千次阅读 2017-05-13 22:40:06
    Odoo提供了一种机制来帮助建立一个新的模块,odoo-bin有一子命令scaffold 创建一个空的模块: odoo-bin scaffold name > < where to put it > 该命令为模块创建一个子目录,并自动为模块创建一堆...
  • 模块概念 对module的理解 Module的查找路径 与package关系 模块导入 导入 同一目录 不同目录 import、from module import packet使用规则示例 重新导入模块 包的概念 包的导入 包导入的几种情况 import语句...
  • Python模块大全

    万次阅读 2016-12-23 11:09:19
    Python模块
  • SAP各模块介绍

    万次阅读 2015-08-06 06:35:16
    希望对你了解SAP有所帮助。  (1)SAP MM模块(物料管理模块),主要有采购、库房与库存管理、MRP、供应商评价等管理功能。  (2)SAP SD模块(销售与分销模块),其中包括销售计划、询价报价、订单管理、运输发货...
  • 简述python模块

    万次阅读 2018-08-09 22:09:09
    1,模块和包 一个定义: 模块用来从逻辑上组织蟒代码(变量,函数,类,逻辑:实现一个功能),本质就是的.py结尾的蟒文件(例如:文件名:test.py,对应的模块名:试验) 包:用来从逻辑上组织模块的,本质就是...
  • simulink中创建自定义模块

    千次阅读 2019-03-26 17:32:00
    (这几天想要把几个常用模块添入Simulink Library Browser库,作为库模块调用,在网上查了很多相关帖子或者博文,结合matlab帮助文档,如愿搭好自己希望的库模块,记录下,有需要的可以看看) 1.simulink中创建...
  • 主要是方便tool、helper等模块建立各自的Logger(setup_helper_tool_logging和setup_tool_logging函数)。我们通过一个例子来对该文件中相关函数进行分析。 from gppylib import gplog logger = gplog.setup_tool_...
  • Oracle Apps(EBS)模块名称 & SAP模块名称

    千次阅读 2012-08-01 12:14:55
    Oracle EBS算是比较庞大,有着非常多的模块,这里列出一些模块的缩写以及模块全称 ABM - Activity Based Management AD - Applications DBA AHL - Oracle Advanced Service Online AK - Oracle Common ...
  • Air724UG_模块硬件设计手册_V2.2

    万次阅读 2021-03-12 16:12:15
    本文档定义了Air724UG模块及其硬件接口规范,电气特性和机械细节,通过此文档的帮助,结合我们的应用手册和用户指导书,客户可以快速应用Air724UG模块于无线应用。 2.综述 2.1 型号信息 表格1:模块支持频段列表 ...
  • CV2模块使用(详细教程)

    万次阅读 多人点赞 2019-05-09 14:52:35
    CV2模块使用(详细教程)
  • python的模块

    千次阅读 2016-11-20 00:01:29
    核心模块 1.1. 介绍1.2. _ _builtin_ _ 模块1.3. exceptions 模块1.4. os 模块1.5. os.path 模块1.6. stat 模块1.7. string 模块1.8. re 模块1.9. math 模块1.10. cmath 模块1.11. operator 模块
  • 深入了解Node-Http模块

    千次阅读 多人点赞 2019-04-08 17:04:19
    Node教程-了解并使用Http模块 http模块主要用于搭建HTTP服务。使用Node搭建HTTP服务器非常简单。 按理说,我们应该先讲讲NPM,package.json。但我觉得先讲讲Http模块实现两个小案例,可以让各位看官更有兴趣,能够...
  • 渗透之——Metasploit命令及模块

    万次阅读 2019-01-26 10:26:29
    列出metasploit框架中的所有渗透攻击模块。 show payloads 列出metasploit框架中的所有攻击载荷。 show auxiliary 列出metasploit框架中的所有辅助攻击载荷。 search name 查找metasploit框架中所有的渗透攻击和其他...
  • React-Native开发之原生模块封装(Android)升级版

    万次阅读 多人点赞 2016-10-19 21:10:37
    实现了RN复用原生代码,即将原生模块封装成一个接口,在RN中调用。并且可以封装更加复杂的方法,同时实现了数据回调,即将数据从原生模块中传递到RN前端。
  • 写这篇博客的初衷首先一句话概括:我想把这几个月做的事情记录下来,并且希望尽量详细,希望读者读了这篇文章能够知道模块化具体每个步骤都做什么,而不是大致的了解。 现在很多人都在谈模块化,网上有一大堆的...
  • python 模块大全

    千次阅读 2017-11-13 21:42:23
    Python 模块大全(很详细!)
  • Python 模块介绍

    万次阅读 2010-09-28 16:03:00
    如何联系我们核心模块1.1. 介绍1.2. _ _builtin_ _ 模块1.3. exceptions 模块1.4. os 模块1.5. os.path 模块1.6. stat 模块1.7. string 模块1.8. re 模块1.9. math 模块1.10. cmath 模块1.11. operator 模块1.12. ...
  • python 各种模块学习

    千次阅读 2017-04-24 10:25:46
    核心模块 1.1. 介绍1.2. _ _builtin_ _ 模块1.3. exceptions 模块1.4. os 模块1.5. os.path 模块1.6. stat 模块1.7. string 模块1.8. re 模块1.9. math 模块1.10. cmath 模块1.11. operator 模块
  • Routes模块详解

    千次阅读 2016-10-07 18:40:21
    大神博客,对我的基础只是补充起到很好的帮助。http:://blog.csdn.net/spch2008/article/details/  表示感谢。 开始启程!!! 一、开始routes模块之旅 例子1: 直接上代码: from routes import Mapper map = ...
  • 之前呢,也做过一个关于模块化业务分离的架构方案,这篇帖子想分享一下关于模块间的数据交互的方案。模块化架构,基础的可以通过创建多个module来把业务进行区分和代码的解耦。为了解耦,让module可拆卸,可移植,...
  • python模块大全

    万次阅读 多人点赞 2017-06-28 09:46:42
    转: ... ******************** PY核心模块方法 ******************** os模块: os.remove() 删除文件  os.unlink() 删除文件  os.rename() 重命名文件  os.listdir() 列出指定目录下所

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 213,509
精华内容 85,403
关键字:

帮助中心模块建立