精华内容
下载资源
问答
  • 1. 概述  The intent of the STATE pattern is to distribute state-specific logic across ... STATE 设计模式的目的 是:将特定状态相关的逻辑分散到一些类的状态类中。   2. 实例  旋转门: Consid

    1. 概述

        The intent of the STATE pattern is to distribute state-specific logic across classes that represent an object’s state.

        STATE 设计模式的目的 是:将特定状态相关的逻辑分散到一些类的状态类中。

     

    2. 实例

        旋转门: Consider the model of the state of a carousel door(revolving door). A carousel is a large, smart rack that accepts material through a doorway and stores the material according to a bar code ID on it. The door operates with a single button. See the state diagram below for some detail.

     

        旋转门的状态图:(状态图细节见 4. )


     

    3. 状态模型的两种实现方法

        3.1 方法一: switch

      

    Observable是java.util中的类^^居然以前都不晓得哦,该打!

     

    Door的具体实现如下:

    Java代码  收藏代码
    1. import java.util.Observable;  
    2.   
    3. /** 
    4.  * This class provides an initial model of a carousel door 
    5.  * that manages its state without moving state-specific 
    6.  * logic out to state classes. 
    7.  */  
    8. public class Door extends Observable {  
    9.     public final int CLOSED = -1;  
    10.     public final int OPENING = -2;  
    11.     public final int OPEN = -3;  
    12.     public final int CLOSING = -4;  
    13.     public final int STAYOPEN = -5;  
    14.   
    15.     private int state = CLOSED;  
    16.   
    17.     /** 
    18.      * The carousel user has touched the carousel button. This "one touch" 
    19.      * button elicits different behaviors, depending on the state of the door. 
    20.      */  
    21.     public void touch() {  
    22.         switch (state)  
    23.         {  
    24.             case OPENING:  
    25.             case STAYOPEN:  
    26.                 setState(CLOSING);  
    27.                 break;  
    28.             case CLOSING:  
    29.             case CLOSED:  
    30.                 setState(OPENING);  
    31.                 break;  
    32.             case OPEN:  
    33.                 setState(STAYOPEN);  
    34.                 break;  
    35.             default:  
    36.                 throw new Error("can't happen");  
    37.         }  
    38.     }  
    39.   
    40.     /**  
    41.      * This is a notification from the mechanical carousel that  
    42.      * the door finished opening or shutting. 
    43.      */  
    44.     public void complete() {  
    45.         if (state == OPENING)  
    46.             setState(OPEN);  
    47.         else if (state == CLOSING)  
    48.             setState(CLOSED);  
    49.     }  
    50.   
    51.     /** 
    52.      * This is a notification from the mechanical carousel that the 
    53.      * door got tired of being open. 
    54.      */  
    55.         public void timeout() {  
    56.             setState(CLOSING);  
    57.         }  
    58.        
    59.     /** 
    60.      * @return a textual description of the door's state 
    61.      */  
    62.     public String status()  
    63.     {  
    64.         switch (state)  
    65.         {  
    66.             case OPENING:  
    67.                 return "Opening";  
    68.             case OPEN:  
    69.                 return "Open";  
    70.             case CLOSING:  
    71.                 return "Closing";  
    72.             case STAYOPEN:  
    73.                 return "StayOpen";  
    74.             default:  
    75.                 return "Closed";  
    76.         }  
    77.     }  
    78.   
    79.     private void setState(int state)  
    80.     {  
    81.         this.state = state;  
    82.         setChanged();  
    83.         notifyObservers();  
    84.     }  
    85. }  
     

    但是采用这种实现,有一个缺陷:state变量在Door类的实现中浑身扩散,就像癌症一般!

     

     

        3.2 方法二: State Pattern

     

        A. 基本的 State Pattern 实现


     

        以上设计方式要求每个状态子类实例内部“ hold 住”一个 Door2 实例的引用,这样才能完成 Door2 实例和它的各个状态实例时间的互相通信。这种设计要求一个状态实例对应一个 Door2 实例,这样一来,一个状态实例就只能为一个 Door2 实例服务╮ ( ╯▽╰ ) ╭

        客户端这样调用:

    Java代码  收藏代码
    1. public static void main(String[] args){  
    2.         Door2 door=new Door2();  
    3.           
    4.         //1. 初始状态  
    5.         System.out.println(door.status());  
    6.           
    7.         //2. 转移到Opening状态  
    8.         door.touch();  
    9.         System.out.println(door.status());  
    10.           
    11.         //3. 转移到Open状态  
    12.         door.complete();  
    13.         System.out.println(door.status());  
    14.           
    15.         //4. 转移到Closing状态  
    16.         door.timeout();  
    17.         System.out.println(door.status());  
    18.           
    19.         //5. 回到Closed状态  
    20.         door.complete();  
    21.         System.out.println(door.status());  
    22.     }  

     

     

    下面给出Door2类、DoorState抽象类、DoorStayOpen类的实现:

    Door2:

    Java代码  收藏代码
    1. public class Door2 extends Observable {  
    2.     public final DoorState CLOSED = new DoorClosed(this);  
    3.     public final DoorState CLOSING = new DoorClosing(this);  
    4.     public final DoorState OPEN = new DoorOpen(this);  
    5.     public final DoorState OPENING = new DoorOpening(this);  
    6.     public final DoorState STAYOPEN = new DoorStayOpen(this);  
    7.   
    8.     private DoorState state = CLOSED;  
    9.   
    10.     public void touch() {  
    11.         state.touch();  
    12.     }  
    13.   
    14.     public void complete() {  
    15.         state.complete();  
    16.     }  
    17.   
    18.     public void timeout() {  
    19.         state.timeout();  
    20.     }  
    21.   
    22.     public String status() {  
    23.         return state.status();  
    24.     }  
    25.   
    26.     protected void setState(DoorState state) {  
    27.         this.state = state;  
    28.         setChanged();  
    29.         notifyObservers();  
    30.     }  

     

    DoorState抽象类:

    Java代码  收藏代码
    1. public abstract class DoorState {  
    2.     protected Door2 door;  
    3.   
    4.     public abstract void touch();  
    5.   
    6.     public void complete() {  
    7.     }  
    8.   
    9.     public void timeout() {  
    10.     }  
    11.   
    12.     public String status() {  
    13.         String s = getClass().getName();  
    14.         return s.substring(s.lastIndexOf('.') + 1);  
    15.     }  
    16.   
    17.     public DoorState(Door2 door) {  
    18.         this.door = door;  
    19.     }  
    20. }  
     

    DoorStayOpen类:

    Java代码  收藏代码
    1. public class DoorStayOpen extends DoorState {  
    2.     public DoorStayOpen(Door2 door) {  
    3.         super(door);  
    4.     }  
    5.   
    6.     public void touch() {  
    7.         door.setState(door.CLOSING);  
    8.     }  
    9. }  
     

     

        B. State Pattern 实现 2 ——让状态实例( DoorState 的子类实例)为多个 Door2 实例服务

        子状态 DoorOpen 实现转移时只负责返回下目标状态是什么,将状态转移的 action 留给 Door2 实例自己来做;而不是像“ A. 基本的 State Pattern 实现”那样在 DoorOpen 内部保存一个 Door2 实例的引用 door ,亲自调用door.setState(door.STAYOPEN); 来实现状态转移

        改进后的关键代码:

       

    Java代码  收藏代码
    1. public class DoorOpen extends DoorState{  
    2.        public DoorState touch(){  
    3.            return DoorState.STAYOPEN;  
    4.            // 以前是 door.setState(door.STAYOPEN);  
    5.        }  
    6.        ...  
    7. }  
    8.   
    9.    
    10.   
    11.     public class Door2 extends Observable{  
    12.        public void touch(){  
    13.            state=state.touch();  
    14.            // 以前是 state.touch();  
    15.            // 即将转移状态的工作留给状态实例来做,事不关己高高挂起  
    16.        }  
    17. }   

     

     

        C. State Pattern 实现 3 ——让状态实例( DoorState 的子类实例)为多个 Door2 实例服务

        另一种实现这种效果的方法是:将 Door2 实例作为参数传递给 DoorState 的状态转移方法,而非建立Composite 的关联关系(将 DoorState 的子类对象作为 Door2 的属性)。

        也即,用“ Dependency 依赖”(弱依赖,如调用)代替了“ Association 关联”(强依赖,如作为属性进行组合)。

     

     

     

    4. 状态图细节

        何谓 State 状态 : Generally speaking, the state of an object depends on the collective value of the object ’ s instance variables. In some cases, most of an object ’ s attributes are fairly static once set, and one attribute is dynamic and plays a prominent role in the class ’ s logic. This attribute may represent the state of the entire object and may even be named state.



     

        4.1 State

        You can subdivide a state icon into areas that show the state  s name and activities活动 .

        3 frequently used categories of activities are entry (what happens when the system enters the state), exit (what happens when the system leaves the state), and do (what happens while the system is in the state).


     

        4.2 Transition s (Details: Event[Guard Condition]/Action)

        You can also add some details to the transition lines. You can indicate an event that causes a transition to occur (atrigger event ) and the computation (the action ) that executes and makes the state change happen.

        A guard condition : when it’s met, the transition takes place. 通常将超时作为监护条件,∵可以认为此时没有任何event.


    •源状态 Source State :即受转换影响的状态

    •目标状态 Target State :当转换完成后,对象的状态

    •触发事件 (Trigger) Event :用来为转换定义一个事件,包括调用、改变、信号、时间四类事件

    •监护条件 (Guard Condition) :布尔表达式,决定是否激活转换、

    •动作 (Action) :转换激活时的操作

     

    几个实例:



     

     


     

    展开全文
  • 下图是从 TestTrace Pro 软件中摘录的一附经典“缺陷状态转换图”,可能能够为软件企业的缺陷管理提供参考。
    下图是从 TestTrace Pro 软件中摘录的一附经典“缺陷状态转换图”,可能能够为软件企业的缺陷管理提供参考。
    展开全文
  • 我想车跑得更好怎么办?

    声明在前:本系列以程序设计为主,适用于刚学会32,想完成一个基本项目却不知道怎么上手的小伙伴。想学习硬件方面如:电路、画板等内容的朋友请不要在本系列耽误您的时间,关闭即可。

    经过 第一天.与第二天.的基础内容讲解,本系列终于迎来了最后一期:避障、磁铁、停车元素的方案设计,以及——如何让车跑得更好?

    避障元素:

    原理

    首选红外模块/光电对管。简单朴实不枯燥,又不像超声波花里胡哨。
    左图为在第一期中,说到过一个平价版的红外模块;右图为光电对管(圆柱体,长得像个小号手电筒):
    在这里插入图片描述
    装车的时候只要让他们都朝前就能充当避障的传感器:(光电对管的距离更远一些,但速度没达到一定程度的话,没必要那么远就作出响应)
    光电对管的用法和红外模块几乎是相同的:)
    在这里插入图片描述
    在没有障碍物的时候,红外模块返回值为“黑色”;当障碍进入检测范围时,返回值为“白”,而程序就对其返回值作出响应,这便是红外避障的原理。所以,如果用红外避障的话,障碍物不能是黑色,否则返回值永远都是“黑色”。
    原理讲完,接下来我们看看程序:

    方案一:if else

    最直接的方法就是用if else语句:

    初始化balabala
    while(1){
    	if(有障碍){
    		避障();}
    	else {
    		Run();}
    }
    

    方案二:外部中断

    外部中断,就是当特定引脚发生改变的时候,触发中断。
    我们可以把连避障的引脚设置为外部中断,上升沿或下降沿触发,这里就不细讲了,感兴趣的可以自己回去研究

    避障程序

    其实无论是用if else 还是外部中断,我们都希望把“避障”作为一个突发事件来优先处理的。避障程序该怎么写呢?
    推荐一种最简单直接的方法:固定路线,最多分一下往左还是往右拐出两种情况:
    即:(右转为例)

    void Avoid(){
    	右转2S——怎么转在昨天文末写了,就不在这里浪费空间了
    	左转2s
    }
    

    这就是最基本的固定程序避障方案,但是在实际上,这种写法可能会产生以下几种结果:

    1. 正常拐出,正常回归
    2. 拐出不及时
    3. 回归时车前进方向与赛道夹角过大
    4. 拐出不及时,回归角度又过大

    第一种自然是我们最希望发生的,但是理想往往都只能是理想;
    ** 都包含一个问题:拐弯异常。**

    拐出不及时

    在这里插入图片描述

    我们可以适当增加拐出的角度与速度:(向右拐出,TIM4通道一连左电机,通道二连右电机)

    TIM4->CCR1 = 56000
    TIM4->CCR2 = 36000
    High_Set = 右转大角度
    delay_s(1.5)
    

    回归角太大:

    在这里插入图片描述
    我们可以适当减缓回归时的角度与速度:(向左回归,TIM4通道一连左电机,通道二连右电机)

    TIM4->CCR1 = 36000
    TIM4->CCR2 = 48000
    High_Set = 左转小角度
    delay_s(2.5)
    

    通过以上方法,若是能让车的避障曲线达到这种效果是比较稳妥的:
    (不排除有厉害的小伙伴能做到闪现的可能性)
    在这里插入图片描述

    除非速度快到每秒三四米,不要把检测距离提得太高,否则就是纯粹给别人找机会超越自己了。

    磁铁检测:

    磁铁检测同样提供两种方案:

    独立电路

    电路如图:纽扣电池提供电源,干簧管为开关,唯一的用电器是蜂鸣器
    在这里插入图片描述
    这样就能够在周围有磁铁的时候直接触发了。
    一般的干簧管都是没有磁场的时候断开,有磁场的时候闭合。而且还需要讲究放置方向的,如果可以的话,最好能多准备一些,在车上多装几个,互相垂直放置,再多留几个备用。(这是放在底盘的,想支出去也没问题)
    在这里插入图片描述

    因为干簧管本身比较娇贵,又特别小,如果一不小心没拿住掉地上了就不用找了:一是找不到,二是就算找到了十有八九也摔坏了。。。所以建议多准备一些留着备用。毕竟单独的干簧管非常便宜。

    干簧管模块

    第一次感受到了鼠绘的艰辛,画出来这玩意我能吹一年
    在这里插入图片描述
    这是我曾用过的一种干簧管模块,在没有检测到磁铁时,返回值是0;在检测到磁铁时,返回值是1.。既然返回值只有0和1的分别,那用法就跟红外模块基本无二——或者说这都是一类的模块。
    我们只需要把一个引脚初始化为输入后不断读取它的电平值就好了。
    然后另一个引脚设为输出,连接蜂鸣器;甚至有想法的同学可以放一块屏幕+MP3播放器,当检测到磁铁的时候,来个互动。
    ——————————
    我记得我学长当时做这个同样的比赛的时候,车上就是有一块彩屏,还有MP3播放器,每检测到磁铁或避障等元素就放个笑脸,还放不同的音乐,车跑得又比其他所有人都快,真是,节目效果拉满:) 这一点我还是远远不如当时的学长的。不过我们的车属于重量级寻迹车。大概是什么感觉?就像掠夺者,无法阻挡:)同样是寻迹车,一旦跟别的组的不小心接触了,一定是其他组的被我们的车撞飞或碾过,对,撞飞或碾过:)又撞不过,又追不上,节目效果同样爆炸:)

    (给你们看下掠夺者,自行体会)
    在这里插入图片描述

    ————————————
    注:蜂鸣器是分有源跟无源的,这一点各位就根据需要自行决定选择哪一种好了。

    停车线:

    我们再来回顾一下赛道:
    在这里插入图片描述
    我们看到:停车线比赛道线要粗一些,这就为我们的检测提供了极大的便利:我们可以再安置一个不和寻迹模块在同一水平线上的红外模块,让这个点到寻迹模块线的距离,小于停车线宽度,大于赛道线宽度就好。
    在这里插入图片描述
    然后让这个额外的电感和五个寻迹的一部分全都为“黑”时,立刻停车,PWMAB=0,舵机复位。
    不过要注意的是:停车线和十字线都有可能触发停车条件,尤其是当停车线不够宽甚至本就跟赛道线一样宽的时候,更容易增加误判的几率,导致十字线停车。
    对于这种情况,要考虑到停车线是否有别的条件,比如多条横线作为停车线时,可以用计数的方式,当计数达到一定数量,就停车;或者是停车线上有磁铁,这就要用干簧管模块+计数了——还有赛道上的磁铁呢等等等等,各位见招拆招即可。

    接下来,终于到了最重要的一点:

    如何让车跑得更好?

    调车

    实践出真知,斗争长才干。只有多调车,才能找到最适合于这辆车的PWM、舵机角度。有用到编码器的还有一组或多组pid,或者有实力的使用比pid更高级的模型控制方法等等,除非它能自己学习,当然学习也不是万能的,而且会学习的前提是有大量的数据积累。所以,还是要调车,调车,再调车。

    弯道

    高手过招,弯道超车。真正厉害的赛车手都是在弯道超过了对手——真正厉害的车不是直线快,而是过弯不减速。最能直接反映一辆车调得好不好的,就是弯道。

    • 首先舵机的角度是最重要的,找到合适的档位时,转弯就不再是问题
    • 其次就是电机,当转弯时,若车模本身没有机械差速,我们可以用程序来控制它,让他在转弯的时候有个主动的差速以辅助转弯。虽然这个系列用的赛道非常简单,可能用不上,但是实际情况可能会是下面这种友好的画面:)

    在这里插入图片描述
    第一个直角弯和平滑直角弯的区别就会难住不少人,更何况后面的弯道了。如有雷同,不胜荣幸/斜眼笑
    说实话如果明年是我出题,我倒挺想用这个的/doge

    直线加速

    质量上乘的赛车不光要足够灵活,兼顾速度才是最重要的。放着好好的直线不加速,难道等着被超越吗?
    直线加速的方案很简单,最基本的就是11011的时候加速。虽然有可能发生出赛道的情况,但这不就来了?

    出赛道怎么办?保持上一个状态!

    出赛道是很正常的事情,谁还没出个道了/doge。不过就算真出道了也不要怕,我们还有机会,先看图:
    在这里插入图片描述
    虽然它拐弯不及时,虽然它出道了,虽然它现在是11111,虽然程序里没有写这种情况怎么办。但是没事,它出道之前的状态是 01111,即左转大角度。那么,最直接的保持上一个状态的写法就是:

    if(01111){
    	左转大角度
    	if(11111){
    	左转大角度}}
    else if(10111){
    	左转小角度
    	if(11111){
    	左转小角度)
    else if...
    }
    

    这就是最简单的保持上一个状态的方案,如此便能在发生意外的情况下力挽狂澜。

    再加一对或两对电感

    同为寻迹车,只有两个电感的和五个的肯定不一样。单论排列组合的话,双电感的组合多少,五电感的组合又是多少?每多考虑到一种情况,跑得稳-跑得快的几率就越大。
    虽然我一直在用的都是一整块五电感的模块,完整的模块带来的好处也很多,但是,它也是限制我们的因素。因为它的左右宽度是限定的,只能检测到一小块范围,如果我们再在其两边各加一个,或者在车身、车尾等,检测到的情况就更多了,车对赛道的判断力就更强了。

    调车!依然是调车

    在第一期中写的Run函数只有5个条件,但很明显它是远远不够的,在实际开始跑车的时候,经常会发生除了这五个情况以外的事情,就比如刚刚说的出赛道,还有停车,总不能全都放到else 里面做相同处理吧,所以剩下的判断条件就需要各位在调车的时候自己完善了。

    ——————————————————————
    到此为止,这个短篇系列就算是完结了。本系列只是为各位刚刚入门32的同学提供一个思考的方向,至于32,甚至嵌入式本身仍需要各位亲自深耕,而且32也不是三天就能精通的。而通过这三天的文章,如果大概知晓了一个工程从0到逐渐完善是怎样一个过程,就足够了:)若是您能从中吸取到了什么经验,并以此让您的车跑得更快更稳,那真是我的荣幸。
    ——————
    我是康.,希望做一名能够帮助到各位的博主!除了这个短篇系列,我也在持续更新学Python的系列,欢迎感兴趣的小伙伴关注我的频道!在Python更新完后,根据时间安排,我会再开机器学习或者算法系列,随时欢迎各位与我共同学习,一起进步!

    展开全文
  • Android状态栏微技巧,带你真正理解沉浸式模式

    万次阅读 多人点赞 2016-08-23 07:32:55
    记得之前有朋友在留言里我写一篇关于沉浸式状态栏的文章,正巧我确实有这个打算,那么本篇就给大家带来一次沉浸式状态栏的微技巧讲解。 其实说到沉浸式状态栏这个名字我也是感到很无奈,真不知道这种叫法是谁先...

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/51763825

    本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 郭霖 即可关注,每天都有文章更新。

    记得之前有朋友在留言里让我写一篇关于沉浸式状态栏的文章,正巧我确实有这个打算,那么本篇就给大家带来一次沉浸式状态栏的微技巧讲解。

    其实说到沉浸式状态栏这个名字我也是感到很无奈,真不知道这种叫法是谁先发起的。因为Android官方从来没有给出过沉浸式状态栏这样的命名,只有沉浸式模式(Immersive Mode)这种说法。而有些人在没有完全了解清楚沉浸模式到底是什么东西的情况下,就张冠李戴地认为一些系统提供的状态栏操作就是沉浸式的,并且还起了一个沉浸式状态栏的名字。

    比如之前就有一个QQ群友问过我,像饿了么这样的沉浸式状态栏效果该如何实现?

    这个效果其实就是让背景图片可以利用系统状态栏的空间,从而能够让背景图和状态栏融为一体。

    本篇文章当中我会教大家如何实现这样的效果,但这个真的不叫沉浸式状态栏。因此,这算是一篇技术+普及的文章吧,讲技术的同时也纠正一下大家之前错误的叫法。

    什么是沉浸式?

    先来分析一下叫错的原因吧,之所以很多人会叫错,是因为根本就不了解沉浸式是什么意思,然后就人云亦云跟着叫了。那么沉浸式到底是什么意思呢?

    根据百度百科上的定义,沉浸式就是要给用户提供完全沉浸的体验,使用户有一种置身于虚拟世界之中的感觉。

    比如说现在大热的VR就是主打的沉浸式体验。

    那么对应到Android操作系统上面,怎样才算是沉浸式体验呢?这个可能在大多数情况下都是用不到的,不过在玩游戏或者看电影的时候就非常重要了。因为游戏或者影视类的应用都希望能让用户完全沉浸在其中,享受它们提供的娱乐内容,但如果这个时候在屏幕的上方还显示一个系统状态栏的话,可能就会让用户分分钟产生跳戏的感觉。

    那么我们来看一下比较好的游戏都是怎么实现的,比如说海岛奇兵:

    海岛奇兵的这种模式就是典型的沉浸式模式,它的整个屏幕中显示都是游戏的内容,没有状态栏也没有导航栏,用户玩游戏的时候就可以完全沉浸在游戏当中,而不会被一些系统的界面元素所打扰。

    然后我们再来看一下爱奇艺的实现:

    同样也是类似的,爱奇艺将整个屏幕作为影视的展示区,用户在看电影的时候眼中就只会有电影的内容,这样就不会被其他一些无关的东西所分心。

    这才是沉浸式模式的真正含义,而所谓的什么沉浸式状态栏纯粹就是在瞎叫,完全都没搞懂“沉浸式” 这三个字是什么意思。

    不过虽然听上去好像是很高大上的沉浸式效果,实际看上去貌似就是将内容全屏化了而已嘛。没错,Android沉浸式模式的本质就是全屏化,不过我们今天的内容并不仅限于此,因为还要实现饿了么那样的状态栏效果。那么下面我们就开始来一步步学习吧。

    隐藏状态栏

    一个Android应用程序的界面上其实是有很多系统元素的,观察下图:

    可以看到,有状态栏、ActionBar、导航栏等。而打造沉浸式模式的用户体验,就是要将这些系统元素全部隐藏,只留下主体内容部分。

    比如说我现在新建了一个空项目,然后修改布局文件中的代码,在里面加入一个ImageView,如下所示:

    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/bg"
            android:scaleType="centerCrop" />
    
    </RelativeLayout>

    这里将ImageView的宽和高都设置成match_parent,让图片充满屏幕。现在运行一下程序,效果如下图所示。

    如果你将图片理解成游戏或者电影界面的话,那这个体验离沉浸式就差得太远了,至少状态栏和ActionBar得要隐藏起来了吧?没关系,我们一步步进行优化,并且在优化中学习。

    隐藏状态栏和ActionBar的方式在4.1系统之上和4.1系统之下还是不一样的,这里我就不准备考虑4.1系统之下的兼容性了,因为过于老的系统根本就没有提供沉浸式体验的支持。

    修改MainActivity中的代码,如下所示:

    public class MainActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            View decorView = getWindow().getDecorView();
            int option = View.SYSTEM_UI_FLAG_FULLSCREEN;
            decorView.setSystemUiVisibility(option);
            ActionBar actionBar = getSupportActionBar();
            actionBar.hide();
        }
    }

    这里先调用getWindow().getDecorView()方法获取到了当前界面的DecorView,然后调用它的setSystemUiVisibility()方法来设置系统UI元素的可见性。其中,SYSTEM_UI_FLAG_FULLSCREEN表示全屏的意思,也就是会将状态栏隐藏。另外,根据Android的设计建议,ActionBar是不应该独立于状态栏而单独显示的,因此状态栏如果隐藏了,我们同时也需要调用ActionBar的hide()方法将ActionBar也进行隐藏。

    现在重新运行一下程序,效果如下图所示。

    这样看上去就有点沉浸式效果的模样了。

    虽说这才是正统的沉浸式含义,但有些朋友可能想实现的就是饿了么那样的状态栏效果,而不是直接把整个系统状态栏给隐藏掉,那么又该如何实现呢?

    其实也很简单,只需要借助另外一种UI Flag就可以了,如下所示:

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (Build.VERSION.SDK_INT >= 21) {
        View decorView = getWindow().getDecorView();
        int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
        decorView.setSystemUiVisibility(option);
        getWindow().setStatusBarColor(Color.TRANSPARENT);
    }
    ActionBar actionBar = getSupportActionBar();
    actionBar.hide();

    首先需要注意,饿了么这样的效果是只有5.0及以上系统才支持,因此这里先进行了一层if判断,只有系统版本大于或等于5.0的时候才会执行下面的代码。

    接下来我们使用了SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN和SYSTEM_UI_FLAG_LAYOUT_STABLE,注意两个Flag必须要结合在一起使用,表示会让应用的主体内容占用系统状态栏的空间,最后再调用Window的setStatusBarColor()方法将状态栏设置成透明色就可以了。

    现在重新运行一下代码,效果如下图所示。

    可以看到,类似于饿了么的状态栏效果就成功实现了。

    再声明一次,这种效果不叫沉浸式状态栏,也完全没有沉浸式状态栏这种说法,我们估且可以把它叫做透明状态栏效果吧。

    隐藏导航栏

    现在我们已经成功实现隐藏状态栏的效果了,不过屏幕下方的导航栏还比较刺眼,接下来我们就学习一下如何将导航栏也进行隐藏。

    其实实现的原理都是一样的,隐藏导航栏也就是使用了不同的UI Flag而已,修改MainActivity中的代码,如下所示:

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    View decorView = getWindow().getDecorView();
    int option = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_FULLSCREEN;
    decorView.setSystemUiVisibility(option);
    ActionBar actionBar = getSupportActionBar();
    actionBar.hide();

    这里我们同时使用了SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_FULLSCREEN,这样就可以将状态栏和导航栏同时隐藏了。现在重新运行一下程序,效果如图所示。

    这次看上去好像终于是完全全屏化了,但其实上这离真正的沉浸式模式还差得比较远,因为在这种模式下,我们触摸屏幕的任意位置都会退出全屏。

    这显然不是我们想要的效果,因此这种模式的使用场景比较有限。

    除了隐藏导航栏之外,我们同样也可以实现和刚才透明状态栏类似的效果,制作一个透明导航栏:

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (Build.VERSION.SDK_INT >= 21) {
        View decorView = getWindow().getDecorView();
        int option = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
        decorView.setSystemUiVisibility(option);
        getWindow().setNavigationBarColor(Color.TRANSPARENT);
        getWindow().setStatusBarColor(Color.TRANSPARENT);
    }
    ActionBar actionBar = getSupportActionBar();
    actionBar.hide();

    这里使用了SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,表示会让应用的主体内容占用系统导航栏的空间,然后又调用了setNavigationBarColor()方法将导航栏设置成透明色。现在重新运行一下程序,效果如下图所示。

    真正的沉浸式模式

    虽说沉浸式导航栏这个东西是被很多人误叫的一种称呼,但沉浸式模式的确是存在的。那么我们如何才能实现像海岛奇兵以及爱奇艺那样的沉浸式模式呢?

    首先你应该确定自己是否真的需要这个功能,因为除了像游戏或者视频软件这类特殊的应用,大多数的应用程序都是用不到沉浸式模式的。

    当你确定要使用沉浸式模式,那么只需要重写Activity的onWindowFocusChanged()方法,然后加入如下逻辑即可:

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        @Override
        public void onWindowFocusChanged(boolean hasFocus) {
            super.onWindowFocusChanged(hasFocus);
            if (hasFocus && Build.VERSION.SDK_INT >= 19) {
                View decorView = getWindow().getDecorView();
                decorView.setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
            }
        }
    
    }

    沉浸式模式的UI Flag就这些,也没什么好解释的,如果你需要实现沉浸式模式,直接将上面的代码复制过去就行了。需要注意的是,只有在Android 4.4及以上系统才支持沉浸式模式,因此这里也是加入了if判断。

    另外,为了让我们的界面看上去更像是游戏,这里我将MainActivity设置成了横屏模式:

    <activity android:name=".MainActivity" 
              android:screenOrientation="landscape">
        ...
    </activity>

    这样我们就实现类似于海岛奇兵和爱奇艺的沉浸式模式效果了,如下图所示。

    可以看到,界面默认情况下是全屏的,状态栏和导航栏都不会显示。而当我们需要用到状态栏或导航栏时,只需要在屏幕顶部向下拉,或者在屏幕右侧向左拉,状态栏和导航栏就会显示出来,此时界面上任何元素的显示或大小都不会受影响。过一段时间后如果没有任何操作,状态栏和导航栏又会自动隐藏起来,重新回到全屏状态。

    这就是最标准的沉浸式模式。


    关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。

    微信扫一扫下方二维码即可关注:

    20160507110203928         20161011100137978

    展开全文
  • 状态

    千次阅读 2015-04-10 13:50:01
    有限状态机(Finite State Machine或者Finite State Automata)是软件领域中一种重要的工具,很多东西的模型实际上就是有限状态机。 最近看了一些游戏编程AI的材料,感觉游戏中的AI,第一要说的就是有限状态机来...
  • 状态和无状态的区别

    千次阅读 2018-07-27 14:05:33
    基本概念:  有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象 ,可以保存数据,是非线程安全的。在不同方法调用间不保留任何...代码更好理解: Java代码   public class Statef...
  • NFS或iSCSI哪个更好

    万次阅读 2012-09-10 16:49:21
    难以做出的抉择:NFS或iSCSI哪个更好? 2012-05-31 16:05 来源:网界网 Matt Prigge http://tech.watchstor.com/storage-network-138184.htm 摘要:与NFS和iSCSI是虚拟化所使用的两大IP存储协议。而与...
  • 菜鸟学Java——如何更好的进行单元测试——JUnit

    万次阅读 多人点赞 2014-06-18 21:23:32
    那么今天我们就来说说什么是单元测试,为什么要进行单元测试,以及如更好的何进行单元测试。   什么是单元测试? 单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。比如我们可以...
  • JAVA设计模式--状态模式

    万次阅读 2017-02-11 11:18:13
    一、什么是状态模式 二、状态模式的结构 三、状态模式应用举例 四、理解状态模式 五、状态模式的适用性 六、状态模式的优缺点 一、什么是状态模式 状态(State))模式,又称状态对象(Pattern of Objects for ...
  • 如果你不熟悉 App 定制型状态通道的话,先读本系列 Part-2,它能给你提供一个很的概览。 什么是广义状态通道? 广义状态通道的意思是,用户可以用同一个通道做多种不同的事情。 广义状态通道有何意义...
  • HTTP状态码分类(常用HTTP状态码和HTTP状态码大全)

    千次阅读 多人点赞 2018-03-07 18:07:30
    http状态码有什么用?http状态码的核心作用是Web Server服务器用来告诉客户端,当前的网页请求发生了什么事,或者说当前Web服务器的响应状态。所以HTTP状态码常用来判断和分析...了,下面就我们来了解一下比较常...
  • 本文主要讲一些系统简单,容易维护的东西——「易伸缩」,首当其冲的主题就是「stateless」,也叫「无状态」。 服务的“状态” 无状态的服务 客户端的每次请求必须具备自描述信息,通过这些信息识别客户端身份...
  • Java 设计模式——状态模式

    万次阅读 2016-06-06 16:46:00
    很多人在说状态模式的时候总拿策略模式来进行对比,可能他们的类图会有一点类似,可我却不认为他们有多么相像。你可以阅读《Java设计模式——策略模式》这篇博客,并与本文对比,以找到蛛丝马迹。 他们最根本的差异...
  • 状态和无状态(@stateless/@stateful)

    千次阅读 2018-01-25 10:29:15
    基本概念:  有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态...代码更好理解: /** * 有状态bean,有state,us
  • Android沉浸式状态栏(透明状态栏)最佳实现 ...为了提供更好的界面交互,google在Android4.4以后提供了设置沉浸式状态栏的方法,对于沉浸式状态栏这个名字存在争议,我们不做讨论,实际的效果其实就是透明的状态栏,然后
  • [快速搞定]android 状态栏一体化 沉浸式状态栏 本文总结出一个最简单、最快的状态栏一体化方案,只要三步你的app就将有更好的用户体验了。
  • 说起状态模式游戏开发者们第一个想到的一定是AI的有限状态机FSMs,状态模式确实是实现有限状态机的一种方法。在有限状态机中,一般都是观察者模式与状态模式连用,状态模式把每个状态封装成类,来对每个输入消息...
  • 作者:龚麒,广发证券信息技术部高级前端工程师,负责广发证券金钥匙项目的React ... 2017 年 7 月 8 日(星期六),「“CSDN前端开发”在线峰会」将在 CSDN 学院召开,龚麒已受邀参加,并围绕前端状态管理,深度分...
  • TCP连接的状态详解以及故障排查

    万次阅读 多人点赞 2014-08-20 07:06:38
    我们通过了解TCP各个状态,可以排除和定位网络或系统故障时大有帮助。(总结网络上的内容) 1、TCP状态 了解TCP之前,先了解几个命令: linux查看tcp的状态命令: 1)、netstat -nat 查看TCP各个状态的数量 2)...
  • 详解以太坊世界状态

    万次阅读 2019-05-12 09:21:15
    以太坊是由多个组成部分构成的。这篇文章旨在解构以太坊,使你能...本文同时和一篇手把手学习指引相关联,它能指导你安装并配置好自己的以太坊私有网络(包括挖矿)。学习之后你将能够执行交易,并且探索以太坊的“...
  • UML图详解(八)状态机(状态图和活动图)

    万次阅读 热门讨论 2016-06-15 13:56:52
    状态图和活动图是状态机的两种表现形式。利用状态机可以精确地描述对象的行为。 从对象的初始状态起,开始响应事件并执行某些动作,这些事件引起状态的转换;对象在新状态下又开始响应事件和执行动作,如此连续进行...
  • 【Linux】选择哪种 Linux版本更好一些?

    万次阅读 多人点赞 2018-09-12 09:51:12
    你想挑战自己,想要通过实践来强迫自己学习。这很,这也正是我所做的。 如果你想挑战自我并学习一些东西,我的建议是: Slackware Linux Arch Linux Gentoo Linux FreeBSD...
  • 游戏开发过程中,各种游戏状态的切换无处不在。但很多时候,简单粗暴的if else加标志位的方式并不能很地道地解决问题,这时,就可以运用到状态模式以及状态机来高效地完成任务。状态模式与状态机,因为他们关联紧密...
  • 更坏就是更好(Worse Is Better)

    千次阅读 2007-03-26 00:32:00
    我非常愿意将这个观点介绍给大家,第一是它并不被很多人所知,重要的是它有非常深刻的内涵道理。发展历史这是Richard P. Gabriel 先生根据自己的亲身经历得出的著名论断。Gabiel在Lisp编程语言特别是Common Lisp上...
  • 处理系统配置变化 很多设备可以在运行时改变系统配置,比如屏幕方向,键盘布局以及语言等。当类似的变化发生时,系统会把运行的activity...那么如何应付这些变化呢,最好的办法就是写好状态保存/恢复方法们。比如on
  • Android透明状态栏或者渐变色状态

    千次阅读 2017-05-27 15:01:13
    一、透明状态栏: 我们应用的正常状态栏都是黑乎乎的,就像下面这样(模拟器版本Android4.4.2): 不好看,我们希望的是向这样的: 这样感觉比黑黑的statusBar好看多了。 实现方法: 1.去/res/values...
  • Android开发技巧——设置系统状态栏颜色

    万次阅读 多人点赞 2016-06-22 15:55:24
    如何实现实现设置系统状态栏颜色需要至少在Android 4.4.2(API 19)以上。这是因为,在这个版本以下,没有任何的API可以帮助我们来实现。那么具体如何设置呢?Android 4.4.2实现Android 4.4.2新增了一个特性,即可以...
  • 设计模式-状态模式实现状态

    千次阅读 2016-05-31 13:34:51
    1.概述 在软件开发过程中,...但是对复杂状态的判断就显得“力不从心了”。随着增加新的状态或者修改一个状体(if else(或switch case)语句的增多或者修改)可能会引起很大的修改,而程序的可读性,扩展性也会变

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,625,058
精华内容 650,023
关键字:

怎么让自己状态更好