安卓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
前言:移动智能设备的发展,推动了安卓另一个领域,包括智能电视和智能家居,以及可穿戴设备的大量使用,但是这些设备上的开发并不是和传统手机开发一样,特别是焦点控制和用户操作体验上有很大的区别,本系列博文主 ...
随机推荐
- ORACLE EBS 表空间控制
--1G=1024MB --1M=1024KB --1K=1024Bytes --1M=11048576Bytes --1G=1024*11048576Bytes=11313741824Bytes S ...
- Gazebo機器人仿真學習探索筆記(四)模型編輯
模型編輯主要是自定義編輯物體模型構建環境,也可以將多種模型組合爲新模型等,支持外部模型導入, 需要注意的導入模型格式有相應要求,否在無法導入成功, COLLADA (dae), STereoLitho ...
- Erlang application stop 调用死锁
Erlang application stop 调用死锁(金庆的专栏)在application行为模块的start()中启动bson应用,在stop()中停止bson,结果application:st ...
- 实现string到double的转换
分析:此题虽然类似于atoi函数,但毕竟double为64位, 而且支持小数,因而边界条件更加严格,写代码时需要更加注意. #include <errno.h> #include < ...
- shell-----sed命令详解
Table of Contents 1. Sed简介 2. 定址 3. Sed命令 4. 选项 5. 元字符集 6. 实例 7. 脚本 1. Sed简介 sed是一种在线编辑器,它一次处理 ...
- Dynamics CRM 通过RetrieveEntityRibbonRequest和RetrieveApplicationRibbonRequest导出实体的Ribbon XML
今天看到勇哥的博客介绍了两个request指令用来导出实体的Ribbon XML,在没有工具之前编辑ribbon都是手工导出xml然后编辑的对于很多一开始接触CRM就用工具的人可能不是很熟悉.查了下这 ...
- Xcode中为何要为设置bundle和App分别设置两份一样的图片资源
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 我们知道在App设置的bundle中有时也会用到图片资源,而在 ...
- Cocos2D实现RPG队伍菜单任意调整角色顺序的效果
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 前一篇我们实现了队伍实现拖尾效果,但是在实际游戏中我们往往需要 ...
- 为你的MacOS App添加开机自启动(Swift)
猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/52104828 ...
- 06 Activity隐式跳转
一,隐式跳转 某个Activity 需要在清单文件配置某个Activity如下信息: 注意:category要和action一起用 action:制定一个活动 在隐式跳转的可以用到 category ...