安卓TV开发(九) Android模拟事件 遥控器变身成鼠标来操作TV
本文出处:http://blog.csdn.net/sk719887916/article/details/40348853,作者:skay
一 自定义鼠标视图
public MouseView(Context context) { super(context); } public MouseView(Context context, MouseManager mMouseMrg) { super(context); init( mMouseMrg); } public OnMouseListener getOnMouseListener() { return mOnMouseListener; } public void setOnMouseListener(OnMouseListener mOnMouseListener) { this.mOnMouseListener = mOnMouseListener; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (mMouseView != null && mMouseBitmap != null) { mMouseView.measure(MeasureSpec.makeMeasureSpec(mMouseBitmap.getWidth(), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(mMouseBitmap.getHeight(), MeasureSpec.EXACTLY)); } } private void init(MouseManager manager) { mMouseManager = manager; Drawable drawable = getResources().getDrawable( R.drawable.shubiao); mMouseBitmap = drawableToBitamp(drawable); mMouseView = new ImageView(getContext()); mMouseView.setImageBitmap(mMouseBitmap); addView(mMouseView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); mOffsetX = (int)((mMouseBitmap.getWidth())); mOffsetY = (int)((mMouseBitmap.getHeight())); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { if(mMouseView != null) { mMouseView.layout(mMouseX, mMouseY, mMouseX + mMouseView.getMeasuredWidth(), mMouseY + mMouseView.getMeasuredHeight()); } }
二 鼠标控制器
/** * @param parent * @param type */ public void init(ViewGroup parentView, int type) { mParentView = parentView; mContext = parentView.getContext(); mMouseView = new MouseView(mContext, this); mMouseView.setOnMouseListener(this); mCurrentType = type; } /** * @return */ public boolean getMouseType() { return isMouseType; } /** * @return */ public int getCurrentActivityType() { return mCurrentType; } /** * showmouse */ public void showMouseView() { ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT); if(mMouseView != null) { mParentView.addView(mMouseView, lp); } } public boolean onDpadClicked(KeyEvent event) { if(!isMouseType) { return false; } if(event.getKeyCode() == KEYCODE_CENTER) { dispatchKeyEventToMouse(event); } else { if(event.getAction() == KeyEvent.ACTION_DOWN) { if(!isKeyEventCousumed) { if(event.getDownTime() - mLastEventTime < defTimes) { if(mSpeed < defMaxSpeed) { mSpeed ++; } } else { mSpeed = 1; } } mLastEventTime = event.getDownTime(); dispatchKeyEventToMouse(event); isKeyEventCousumed = true; } else if(event.getAction() == KeyEvent.ACTION_UP) { if(!isKeyEventCousumed){ dispatchKeyEventToMouse(event); } isKeyEventCousumed = false; } } return true; } public void sendCenterClickEvent(int x, int y, int action) { sendMotionEvent(x, y, action); } @SuppressLint("InlinedApi") public void sendMouseHoverEvent(int downx, int downy) { sendMotionEvent(downx, downy, MotionEvent.ACTION_HOVER_MOVE); } @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) @SuppressLint("NewApi") private void sendMotionEvent(int x, int y, int action) { MotionEvent motionEvent = getMotionEvent( x, y ,action) ; if(action == MotionEvent.ACTION_HOVER_MOVE) { motionEvent.setSource(InputDevice.SOURCE_CLASS_POINTER); mMouseView.dispatchGenericMotionEvent(motionEvent); //mParentView.dispatchGenericMotionEvent(motionEvent); } else { //mParentView.dispatchTouchEvent(motionEvent); mMouseView.dispatchTouchEvent(motionEvent); } } private MotionEvent getMotionEvent(int downx, int downy, int action) { // TODO Auto-generated method stub long downTime = SystemClock.uptimeMillis(); long eventTime = SystemClock.uptimeMillis(); int metaState = 0; return MotionEvent.obtain( downTime, eventTime, action, downx, downy, metaState ); } @Override public boolean onclick(View v, KeyEvent et) { if (getMouseType()) { return onDpadClicked(et); } return mParentView.dispatchKeyEvent(et); }
三 当前页面加入鼠标
public class MainActivity extends Activity { WindowManager wm; WindowManager.LayoutParams params; private MouseManager mMouseManager; public static ViewGroup contentView; private WebView webView; private View mLoginStatusView; private TextView mLoaddingMessageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LayoutInflater inflater = getLayoutInflater(); contentView = (ViewGroup) inflater.inflate(R.layout.test, null); setContentView(contentView); init(); initMouse(); showMouse(); } private void init() { webView = (WebView) contentView.findViewById(R.id.web); mLoginStatusView = this.findViewById(R.id.login_status); mLoaddingMessageView = (TextView) this .findViewById(R.id.login_status_message); Button button = (Button) contentView.findViewById(R.id.btn_onclick); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "onclicked ", 1).show(); showProgress(true); webView.setVisibility(View.VISIBLE); webView.loadUrl("https://www.baidu.com/"); WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true); webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { Toast.makeText(MainActivity.this, "加载失败 ", Toast.LENGTH_LONG).show(); super.onReceivedError(view, errorCode, description, failingUrl); } }); webView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { // TODO Auto-generated method stub if (newProgress == 100) { showProgress(false); } else { } } }); } }); } @SuppressLint("NewApi") private void showProgress(final boolean show) { // On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow // for very easy animations. If available, use these APIs to fade-in // the progress spinner. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { int shortAnimTime = getResources().getInteger( android.R.integer.config_shortAnimTime); mLoginStatusView.setVisibility(View.VISIBLE); mLoginStatusView.animate().setDuration(shortAnimTime) .alpha(show ? 1 : 0) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { webView.setVisibility(show ? View.VISIBLE : View.GONE); } }); webView.setVisibility(View.VISIBLE); webView.animate().setDuration(shortAnimTime).alpha(show ? 0 : 1) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { webView.setVisibility(show ? View.GONE : View.VISIBLE); } }); } else { // The ViewPropertyAnimator APIs are not available, so simply show // and hide the relevant UI components. mLoginStatusView.setVisibility(show ? View.VISIBLE : View.GONE); webView.setVisibility(show ? View.GONE : View.VISIBLE); } } private void showMouse() { mMouseManager.showMouseView(); } public void initMouse() { initMouseMrg(); } public void initMouseMrg() { mMouseManager = new MouseManager(); mMouseManager.init(contentView, MouseManager.MOUSE_TYPE); mMouseManager.setshowMouse(true); } }
简单三步,代码就可以实现简单的用于遥控器操作的TV的浏览器,本次demo只是用户手动模拟点击,至于实现自动化模拟点击,以上方式显得极为笨拙,
具体逻辑是当我的app启动时 。就可以用全局的Instrumentation来监控到底当前在哪个界面,提前将点击的入口定义OK后,接下来的点击事件就如同用户主动点击一样,包括跳转逻辑不再需要考虑。
安卓TV开发(九) Android模拟事件 遥控器变身成鼠标来操作TV的更多相关文章
- STC8H开发(九): STC8H8K64U模拟USB HID外设
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- 安卓Tv开发(二)移动智能电视之焦点控制(按键事件)
原文:http://blog.csdn.net/sk719887916/article/details/44781475 skay 前言:移动智能设备的发展,推动了安卓另一个领域,包括智能电视和智能家 ...
- 安卓Tv开发(一)移动智能电视之焦点控制(触控事件)
前言:移动智能设备的发展,推动了安卓另一个领域,包括智能电视和智能家居,以及可穿戴设备的大量使用,但是这些设备上的开发并不是和传统手机开发一样,特别是焦点控制和用户操作体验风格上有很大的区别,本系列博 ...
- Android TV开发中所有的遥控器按键监听及注意事项,新增home键监听
原文:Android TV开发中所有的遥控器按键监听及注意事项,新增home键监听 简单记录下android 盒子开发遥控器的监听 ,希望能帮到新入门的朋友们 不多说,直接贴代码 public cla ...
- 安卓TV开发(前言)— AndroidTV模拟器初识与搭建
原文:http://blog.csdn.net/sk719887916/article/details/39612577skay 前言:移动智能设备的发展,推动了安卓另一个领域,包括智能电视和智能家居 ...
- Android TV开发总结(三)构建一个TV app的焦点控制及遇到的坑
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52835829 前言:上篇中,&l ...
- 安卓TV开发(五) 移动智能终端UI之实现主流TV焦点可控UI
载请标明出处:http://blog.csdn.net/sk719887916,作者:skay 由于其他网站收录,导致你无法查看本系列原创文章请点击此处 安卓TV开发(四)实现主流智能T ...
- 安卓TV开发(四) 实现主流智能TV视频播放器UI
前言:移动智能设备的发展,推动了安卓另一个领域,包括智能电视和智能家居,以及可穿戴设备的大量使用,但是这些设备上的开发并不是和传统手机开发一样,特别是焦点控制和用户操作体验上有很大的区别,本系列博文主 ...
- 安卓TV开发(三) 移动智能设备之实现主流TV电视盒子焦点可控UI
前言:移动智能设备的发展,推动了安卓另一个领域,包括智能电视和智能家居,以及可穿戴设备的大量使用,但是这些设备上的开发并不是和传统手机开发一样,特别是焦点控制和用户操作体验上有很大的区别,本系列博文主 ...
随机推荐
- activiti 配置节点 连线信息获取
1.1.1. 前言 当使用eclipse插件进行流程设计的时候,部署流程之后,我们如何获取我们定义的所有的节点.连线.关口等配置信息呢?有的人看到这个需求,不免窃喜,这不很简单嘛,重新打来bmpn中定 ...
- SpriteKit给游戏弹跳角色添加一个高度标示器
这是一个类似于跳跃涂鸦的小游戏,主角不断吃能量球得到跳跃能量向更高的地方跳跃,如果图中碰到黑洞就挂了- 在游戏调试过程中如果能实时知道主角的高度就好了,这将有助于程序猿动态的判断游戏胜败逻辑. 你可以 ...
- [tornado]websocket 最简单demo
想法 前两天想看看django 长轮询或者是websocket的方案,发现都不太好使. tornado很适合做这个工作,于是找了些资料,参照了做了个最简单demo,以便备用. 具体的概念就不说了,to ...
- 关于Android PullTorefreshScrollview回到顶部实例
列表滑动下面显示按钮,点击按钮回到顶部的功能,一般scrollview会有滑动监听的事件,通过setOnScrollChangeListener()滑动监听滑动的距离来判断是否显示按钮就好了,但是Pu ...
- 关于activitygroup过时,用frament替换操作
现在Fragment的应用真的是越来越广泛了,之前Android在3.0版本加入Fragment的时候,主要是为了解决Android Pad屏幕比较大,空间不能充分利用的问题,但现在即使只是在手机上, ...
- FFmpeg源代码简单分析:avcodec_encode_video()
===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...
- 与MP3相关的技术总结
MP3文件格式解析 Peter Lee 2008-06-05 目录 33 B7 00 0001 02 FF FF FF F4 E1 2F FF FF FFFF DF FF FF FB52 8C 12 ...
- Android摄像头照相机技术-android学习之旅(八)
简介 Android SDK支持Android设备内置的照相机.从Android2.3开始支持多个摄像头(主要指前置摄像头和后置摄像头).通过照片相可以拍照和录像. 需要考虑的问题 是否支持照相机 快 ...
- ubuntu14.04 server ftp 服务安装配置详解
ubuntu14.04 server ftp 服务安装配置详解 cheungmine 2016-01-27 http://wiki.ubuntu.com.cn/Vsftpd 0 安装好vsftpd服务 ...
- 关于android app签名文件获取sha1和MD值
最近在做百度地图的嵌入,因为从同事接手的android app,所以第一次接触android的签名. 总的来说签名还比较简单,我用的是eclipse ADT自带的签名工具来做的签名,方法如下: 选择项 ...