移动智能电视之焦点控制(按键事件)

 原文:http://blog.csdn.net/sk719887916/article/details/44781475 skay

     TV项目源码:https://github.com/Tamicer/TvResource-Android


前言:移动智能设备的发展,推动了安卓另一个领域,包括智能电视和智能家居,以及可穿戴设备的大量使用,但是这些设备上的开发并不是和传统手机开发一样,特别是焦点控制和用户操作体验上有很大的区别,本系列博文主要用移动智能电视(TV)上实现视频播放器的去了解下在智能设备上的开发的相关技术。本系列将实现遥控器焦点控制,模拟鼠标点击,视频在线直播,和手机当遥控器等功能,带给你不一样的开发体验。

上篇文章中说道了触控事件,(安卓Tv开发(一)焦点控制(触控事件))但是只对MotionEvent做了细说,很多东西还是不懂怎么用触控事件,现在就做对上篇的补充吧   本文出处:http://blog.csdn.net/sk719887916

在view重写onTouchEvent方法,通过event.getAction()对不同的enent就可以处理了,代码如下

  1. public boolean onTouchEvent(MotionEvent event)  
  2.     {  
  3.         int events[] = {MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE,  
  4.                 MotionEvent.ACTION_UP, MotionEvent.ACTION_MOVE, MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_OUTSIDE,  
  5.                 MotionEvent.ACTION_POINTER_DOWN,MotionEvent.ACTION_POINTER_UP,  
  6.                 MotionEvent.EDGE_TOP,MotionEvent.EDGE_BOTTOM,MotionEvent.EDGE_LEFT,MotionEvent.EDGE_RIGHT};  
  7.           
  8.         String szEvents[]={"ACTION_DOWN""ACTION_MOVE",  
  9.         "ACTION_UP""ACTION_MOVE""ACTION_CANCEL""ACTION_OUTSIDE",  
  10.         "ACTION_POINTER_DOWN","ACTION_POINTER_UP",  
  11.         "EDGE_TOP","EDGE_BOTTOM","EDGE_LEFT","EDGE_RIGHT"};  
  12.         for(int i=0; i < events.length; i++)  
  13.         {  
  14.             if(events[i] == event.getAction())  
  15.             {  
  16.                 if(oldevent != event.getAction())  
  17.                 {  
  18.                     DisplayEventType(szEvents[i]);  
  19.                     oldevent = event.getAction();  
  20.                 }  
  21.                 break;  
  22.             }  
  23.         }  
  24.         return super.onTouchEvent(event);  
  25.     }  
好了 ,今天言归正传,接着说键盘事件:keyevent.

KeyEvent事件


一  keyEvent:

   
 源码位于android.view下,包装管理所有按键有关输入的事件体系,KeyEvent和MotionEvent的分发流程一样,都是InputEvent的子类,都是从Activity开始的,KeyEvent主要有以下事件类型:



   KeyEvent.KEYCODE_DPAD_UP; 上
   KeyEvent.KEYCODE_DPAD_DOWN; 下
   KeyEvent.KEYCODE_DPAD_LEFT;左
   KeyEvent.KEYCODE_DPAD_RIGHT;右
   KeyEvent.KEYCODE_DPAD_CENTER;确定键
   KeyEvent.KEYCODE_DPAD_RIGHT; 右
   KeyEvent.KEYCODE_XXX:数字键 (xx表示你按了数字几)
   KeyEvent.KEYCODE_BACK; 返回键
   KeyEvent.KEYCODE_HOME;房子键

   KeyEvent.KEYCODE_A: A-Z,26个字母

   KeyEvent.KEYCODE_MENU菜单键。

   谷歌提供了260种keyEvent,其他类型可以去源码查看,一个最基本的构造函数:

       
[java]  view plain  copy
  1. public KeyEvent(long downTime, long eventTime, int action,  
  2.     int code, int repeat, int metaState,  
  3.     int deviceId, int scancode, int flags, int source) {  
  4.     mDownTime = downTime;  
  5.     mEventTime = eventTime;  
  6.     mAction = action;  
  7.     mKeyCode = code;  
  8.     mRepeatCount = repeat;  
  9.     mMetaState = metaState;  
  10.     mDeviceId = deviceId;  
  11.     mScanCode = scancode;  
  12.     mFlags = flags;  
  13.     mSource = source;  
  14.     }  



   仔细观察,发现一个按键事件,会包含以上很多属性, 按键Id,设备ID, 按键坐标,按键资源,按键标记位,按键action(Up,down),响应次数,按下的时间等。


   一般我们处理按键事件可以这样做:
[java]  view plain  copy
  1. public boolean onKeyDown(int keyCode, KeyEvent event) {  
  2.  switch (keyCode) {  
  3.      case KeyEvent.KEYCODE_DPAD_CENTER:  
  4.          Toast("你按下中间键");  
  5.          break;  
  6.   
  7.      case KeyEvent.KEYCODE_DPAD_DOWN:  
  8.          Toast("你按下下方向键");  
  9.      break;  
  10.   
  11.      case KeyEvent.KEYCODE_DPAD_LEFT:  
  12.          Toast("你按下左方向键");  
  13.          break;  
  14.   
  15.      case KeyEvent.KEYCODE_DPAD_RIGHT:  
  16.          Toast("你按下右方向键");  
  17.          break;  
  18.   
  19.      case KeyEvent.KEYCODE_DPAD_UP:  
  20.          Toast("你按下上方向键");  
  21.          break;  
  22.  }  
  23.  return super.onKeyDown(keyCode, event);  

      
   复写onKeyDown()或者onKeyUp();

   不管是触控和按键事件,我们在Java代码中凭空创建,API提供了obtain()函数,来让开发者模拟事件,让系统处理。

KeyEvent事件分发

   上一篇文中介绍了触控事件的机制,其实按键事件和他很相似,基本也传递和分发(拦截不存在,你无法阻止实际物理键的按下去),主要有dispatchKeyEvent(KeyEvent event),onKeyUp和onKeyDown,

**dispatchKeyEvent()**

  主要处理按键的分发。avtivity和view都拥有此方法,两种有所区别的,实际都是交给DecorView来处理。

  
[java]  view plain  copy
  1. public boolean dispatchKeyEvent(KeyEvent event) {  
  2.       onUserInteraction();  
  3.   
  4.       // Let action bars open menus in response to the menu key prioritized over  
  5.       // the window handling it  
  6.       if (event.getKeyCode() == KeyEvent.KEYCODE_MENU &&  
  7.               mActionBar != null && mActionBar.onMenuKeyEvent(event)) {  
  8.           return true;  
  9.       }  
  10.   
  11.       Window win = getWindow();  
  12.       if (win.superDispatchKeyEvent(event)) {  
  13.           return true;  
  14.       }  
  15.       View decor = mDecor;  
  16.       if (decor == null) decor = win.getDecorView();  
  17.       return event.dispatch(this, decor != null  
  18.               ? decor.getKeyDispatcherState() : nullthis);  
  19.   }  


 上层拦截可以复写就可以了,

   
[java]  view plain  copy
  1. @Override      
  2.     public boolean dispatchKeyEvent(KeyEvent event) {  
  3.            Log.i("dispatchKeyEvent",  
  4.                    "dispatchKeyEvent(), action=" + event.getAction() + " keycode="  
  5.                            + event.getKeyCode());  
  6.              
  7.            return super.dispatchKeyEvent(event);  
  8.              
  9.        }  


  
   
 如果我们想消费某个按键事件我们可以复写onKeyDown()或者onKeyUp();

    
[java]  view plain  copy
  1. @Override  
  2.     public boolean onKeyUp(int keyCode, KeyEvent event) {  
  3.         return super.onKeyUp(keyCode, event);  
  4.           
  5.         // // TODO: 2014-10-30    
  6.     }  



**总结下整个流程:**

首先触发dispatchKeyEvent()
再次onKeyDown 如果按下紧接着松开,则是俩步

紧跟着触发dispatchKeyEvent 
然后触发onUserInteraction 
再次onKeyUp


本文出 http://blog.csdn.net/sk719887916 处:


Focus


 requestFocus():强制设置一个焦点到指定的view或它的一个子类,(前提是android:focusable为true能够获得焦点)
 
-    android:focusable:设置一个控件能否获得焦点
-    android:background:设置在作为背景的drawable
-    android:nextFocusDown:定义下一个获得焦点的控件当按下键时
-    android:nextFocusUp:定义下一个获得焦点的控件当按上键时
-    android:nextFocusLeft:定义下一个获得焦点的控件当按左键时
-    android:nextFocusRight:定义下一个获得焦点的控件当按右键时


可以通过焦点事件变化操作view,    View.setFocusable(true);   设置控件是否可以获得焦点,同时会触发 setOnFocusChangeListener() 

[java]  view plain  copy
  1. view.setOnFocusChangeListener(){     
  2.          public void onFocus(boolean Focus){     
  3.                   if( Focus ){    
  4.                    //获得焦点  
  5.                    } else{    
  6.                       //失去焦点  
  7.                    }       



三 instrumentation


   Instrumentation和Activity有点类似,只不过Activity是需要一个界面的,而Instrumentation并不是这样的,我们可以将它理解为一种没有图形界面的,具有启动能力的,用于监控其他类(用Target Package声明)的工具类。Instrumentation,开发者可以构建一个独立于应用程序的代理程序(Agent),用来监测和协助运行在 JVM 上的程序,甚至能够替换和修改某些类的定义。有了这样的功能,开发者就可以实现更为灵活的运行时虚拟机监控和 Java 类操作,代替认为操作,主要用于自动测试框架。

        instrumentation发送键盘鼠标事件:Instrumentation提供了丰富的以send开头的函数接口来实现模拟键盘和鼠标,如下所述:

    sendCharacterSync(int keyCode)            //用于发送指定KeyCode的按键

   sendKeyDownUpSync(int key)                //用于发送指定KeyCode的按键

   sendPointerSync(MotionEvent event)     //用于模拟Touch

   sendStringSync(String text)                   //用于发送字符串

 

   

[java]  view plain  copy
  1. Instrumentation inst=new Instrumentation();  
  2. inst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 10100));  
  3. inst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 10100));  
  本文出 处:http://blog.csdn.net/sk719887916/article/details/44781475

但是TV的遥控器模拟鼠标并非需要此类,也没这么复杂,具体可以拦截事件,发送模拟事件即可,欢迎阅读。

 安卓实现遥控器模拟鼠标请阅读:《安卓TV开发(九) Android之模拟事件点击并实现遥控器模模拟鼠标操作

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要支持键盘输入焦点按键事件,QGraphicsItem需要继承自QGraphicsItem类,并且重写下列方法: 1. void keyPressEvent(QKeyEvent *event):重写keyPressEvent方法处理按键事件; 2. QVariant itemChange(GraphicsItemChange change, const QVariant &value):重写itemChange方法处理焦点事件。 在重写keyPressEvent方法时,需要注意: 1. QGraphicsItem没有默认的键盘焦点,因此需要使用setFlag()方法将QGraphicsItem的ItemIsFocusable标志设置为true,才能接收键盘事件; 2. 在keyPressEvent方法中,需要通过QKeyEvent的key()方法获取按下的键,并根据需要进行处理。 在重写itemChange方法时,需要注意: 1. 当焦点状态改变时,会触发GraphicsItemChange类型的change参数为QGraphicsItem::ItemFocusHasChanged的信号,可以在itemChange方法中重写处理该信号; 2. 在itemChange方法中,可以通过value参数获取焦点状态的改变,并根据需要进行处理。 举例来说,以下代码是QGraphicsItem的一个子类,在该类中实现了键盘输入焦点按键事件的支持: ```c++ class MyItem : public QGraphicsItem { public: MyItem(QGraphicsItem *parent = nullptr) : QGraphicsItem(parent) { setFlag(ItemIsFocusable, true); } QRectF boundingRect() const override { return QRectF(0, 0, 100, 100); } void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override { painter->drawRect(boundingRect()); } void keyPressEvent(QKeyEvent *event) override { switch (event->key()) { case Qt::Key_Up: setPos(pos() + QPointF(0, -10)); break; case Qt::Key_Down: setPos(pos() + QPointF(0, 10)); break; case Qt::Key_Left: setPos(pos() + QPointF(-10, 0)); break; case Qt::Key_Right: setPos(pos() + QPointF(10, 0)); break; default: break; } } QVariant itemChange(GraphicsItemChange change, const QVariant &value) override { if (change == QGraphicsItem::ItemFocusHasChanged) { if (value.toBool()) { qDebug() << "Item has gained focus!"; } else { qDebug() << "Item has lost focus!"; } } return QGraphicsItem::itemChange(change, value); } }; ``` 在上述代码中,MyItem类重写了QGraphicsItem的keyPressEvent和itemChange方法,实现了键盘输入焦点按键事件的支持。具体地,该类在构造函数中将ItemIsFocusable标志设置为true,使其能够接受键盘焦点;在keyPressEvent方法中,根据按下的键进行移动;在itemChange方法中,处理焦点状态的改变。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值