├── .gitignore
├── .idea
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── debug.keystore
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ ├── gamelist.json
│ └── help.html
│ ├── java
│ ├── com
│ │ └── example
│ │ │ └── gamebrowser
│ │ │ ├── AboutActivity.java
│ │ │ ├── FrmBrowser.java
│ │ │ ├── FullScreenActivity.java
│ │ │ ├── LauncherActivity.java
│ │ │ ├── PluginActivity.java
│ │ │ ├── SettingActivity.java
│ │ │ ├── WebGameBoostEngine.java
│ │ │ └── WindowService.java
│ └── wei
│ │ └── mark
│ │ └── standout
│ │ ├── StandOutWindow.java
│ │ ├── Utils.java
│ │ ├── WindowCache.java
│ │ ├── constants
│ │ └── StandOutFlags.java
│ │ └── ui
│ │ ├── TouchInfo.java
│ │ └── Window.java
│ └── res
│ ├── drawable-hdpi
│ ├── close.png
│ ├── corner.png
│ ├── hide.png
│ ├── ic_menu_capture.png
│ └── maximize.png
│ ├── drawable-xhdpi
│ ├── ic_notification_icon.png
│ └── shadow.9.png
│ ├── drawable
│ ├── bg_btn_close.xml
│ ├── bg_btn_cmd.xml
│ ├── bg_frame.xml
│ └── ic.png
│ ├── layout
│ ├── about.xml
│ ├── activity_plugin.xml
│ ├── activity_setting.xml
│ ├── adapter_app.xml
│ ├── drop_down_list_item.xml
│ ├── fullscreen.xml
│ ├── fwd.xml
│ ├── launcher.xml
│ └── system_window_decorators.xml
│ └── values
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── plugin_template.apk
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
17 |
22 |
27 |
→ 转到 设置 -> 选择游戏
5 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/gamebrowser/AboutActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.gamebrowser; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.content.Intent; 6 | import android.net.Uri; 7 | import android.os.Bundle; 8 | import android.view.View; 9 | import android.widget.Toast; 10 | 11 | import wei.mark.standout.Utils; 12 | 13 | public class AboutActivity extends Activity { 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | setContentView(R.layout.about); 19 | } 20 | 21 | 22 | public void introduce(View view) { 23 | String msg="电竞浏览器\n" + 24 | "\n(窗口模式下,选中文本需要点左上角图标复制)\n" + 25 | "-最大化/最小化隐藏/自由调整大小(需要悬浮窗权限)\n" + 26 | "-随手研发(可能)加速引擎,游戏载入更快,更省流量\n" + 27 | "-半透明窗口功能\n" + 28 | "-全屏启动,沉浸模式,退出确认,客户端级体验(全屏模式下支持分屏)\n" + 29 | "\n" + 30 | "\n" + 31 | "本软件通过系统浏览器实现,部分太老的系统和安卓模拟器可能打不开\n" + 32 | "若您正在玩的游戏有Android版客户端,推荐使用官方客户端而不是浏览器\n" + 33 | "如果你喜欢这个项目,请在github为我点个star(如果你不知道什么是github就算了)"; 34 | AlertDialog ald = new AlertDialog.Builder(this).setTitle("功能介绍").setMessage(msg).setPositiveButton(android.R.string.ok,null).create(); 35 | ald.show(); 36 | Utils.setDialogVersion(this,"firstrun",2); 37 | } 38 | 39 | public void github(View view) { 40 | openUrl("https://github.com/ZYFDroid/android-webgame-browser"); 41 | } 42 | 43 | public void update(View view) { 44 | openUrl("https://github.com/ZYFDroid/android-webgame-browser/releases"); 45 | } 46 | 47 | void openUrl(String url){ 48 | try { 49 | Intent intent = new Intent(Intent.ACTION_VIEW); 50 | Uri uri = Uri.parse(url); 51 | intent.setData(uri); 52 | startActivity(intent); 53 | }catch (Exception ex){ 54 | Toast.makeText(this, "建议先安装一个浏览器", Toast.LENGTH_SHORT).show(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/gamebrowser/FrmBrowser.java: -------------------------------------------------------------------------------- 1 | package com.example.gamebrowser; 2 | 3 | import android.app.Notification; 4 | import android.app.NotificationChannel; 5 | import android.app.NotificationManager; 6 | import android.app.PendingIntent; 7 | import android.content.ClipData; 8 | import android.content.ClipboardManager; 9 | import android.content.Context; 10 | import android.content.Intent; 11 | import android.graphics.Bitmap; 12 | import android.os.Build; 13 | import android.os.Handler; 14 | import android.util.Log; 15 | import android.view.Gravity; 16 | import android.view.MotionEvent; 17 | import android.view.View; 18 | import android.view.animation.AlphaAnimation; 19 | import android.view.animation.Animation; 20 | import android.view.animation.AnimationSet; 21 | import android.view.animation.ScaleAnimation; 22 | import android.view.animation.TranslateAnimation; 23 | import android.webkit.JavascriptInterface; 24 | import android.webkit.WebView; 25 | import android.widget.FrameLayout; 26 | import android.widget.Toast; 27 | 28 | import java.util.ArrayList; 29 | import java.util.HashMap; 30 | import java.util.List; 31 | 32 | import wei.mark.standout.StandOutWindow; 33 | import wei.mark.standout.Utils; 34 | import wei.mark.standout.constants.StandOutFlags; 35 | import wei.mark.standout.ui.Window; 36 | 37 | /** 38 | * Created by WorldSkills2020 on 10/23/2019. 39 | */ 40 | 41 | public class FrmBrowser extends StandOutWindow { 42 | 43 | public static boolean isRunning = false; 44 | 45 | 46 | public HashMap30 | * This flag also sets {@link #FLAG_DECORATION_SYSTEM}. 31 | */ 32 | public static final int FLAG_DECORATION_CLOSE_DISABLE = FLAG_DECORATION_SYSTEM 33 | | 1 << flag_bit++; 34 | 35 | /** 36 | * Setting this flag indicates that the window decorator should NOT provide 37 | * a resize handle. 38 | * 39 | *
40 | * This flag also sets {@link #FLAG_DECORATION_SYSTEM}. 41 | */ 42 | public static final int FLAG_DECORATION_RESIZE_DISABLE = FLAG_DECORATION_SYSTEM 43 | | 1 << flag_bit++; 44 | 45 | /** 46 | * Setting this flag indicates that the window decorator should NOT provide 47 | * a resize handle. 48 | * 49 | *
50 | * This flag also sets {@link #FLAG_DECORATION_SYSTEM}. 51 | */ 52 | public static final int FLAG_DECORATION_MAXIMIZE_DISABLE = FLAG_DECORATION_SYSTEM 53 | | 1 << flag_bit++; 54 | 55 | /** 56 | * Setting this flag indicates that the window decorator should NOT provide 57 | * a resize handle. 58 | * 59 | *
60 | * This flag also sets {@link #FLAG_DECORATION_SYSTEM}. 61 | */ 62 | public static final int FLAG_DECORATION_MOVE_DISABLE = FLAG_DECORATION_SYSTEM 63 | | 1 << flag_bit++; 64 | 65 | /** 66 | * Setting this flag indicates that the window can be moved by dragging the 67 | * body. 68 | * 69 | *
70 | * Note that if {@link #FLAG_DECORATION_SYSTEM} is set, the window can 71 | * always be moved by dragging the titlebar regardless of this flag. 72 | */ 73 | public static final int FLAG_BODY_MOVE_ENABLE = 1 << flag_bit++; 74 | 75 | /** 76 | * Setting this flag indicates that windows are able to be hidden, that 77 | * {@link StandOutWindow#getHiddenIcon(int)}, 78 | * {@link StandOutWindow#getHiddenTitle(int)}, and 79 | * {@link StandOutWindow#getHiddenMessage(int)} are implemented, and that 80 | * the system window decorator should provide a hide button if 81 | * {@link #FLAG_DECORATION_SYSTEM} is set. 82 | */ 83 | public static final int FLAG_WINDOW_HIDE_ENABLE = 1 << flag_bit++; 84 | 85 | /** 86 | * Setting this flag indicates that the window should be brought to the 87 | * front upon user interaction. 88 | * 89 | *
90 | * Note that if you set this flag, there is a noticeable flashing of the 91 | * window during {@link MotionEvent#ACTION_UP}. This the hack that allows 92 | * the system to bring the window to the front. 93 | */ 94 | public static final int FLAG_WINDOW_BRING_TO_FRONT_ON_TOUCH = 1 << flag_bit++; 95 | 96 | /** 97 | * Setting this flag indicates that the window should be brought to the 98 | * front upon user tap. 99 | * 100 | *
101 | * Note that if you set this flag, there is a noticeable flashing of the 102 | * window during {@link MotionEvent#ACTION_UP}. This the hack that allows 103 | * the system to bring the window to the front. 104 | */ 105 | public static final int FLAG_WINDOW_BRING_TO_FRONT_ON_TAP = 1 << flag_bit++; 106 | 107 | /** 108 | * Setting this flag indicates that the system should keep the window's 109 | * position within the edges of the screen. If this flag is not set, the 110 | * window will be able to be dragged off of the screen. 111 | * 112 | *
113 | * If this flag is set, the window's {@link Gravity} is recommended to be 114 | * {@link Gravity#TOP} | {@link Gravity#LEFT}. If the gravity is anything 115 | * other than TOP|LEFT, then even though the window will be displayed within 116 | * the edges, it will behave as if the user can drag it off the screen. 117 | * 118 | */ 119 | public static final int FLAG_WINDOW_EDGE_LIMITS_ENABLE = 1 << flag_bit++; 120 | 121 | /** 122 | * Setting this flag indicates that the system should keep the window's 123 | * aspect ratio constant when resizing. 124 | * 125 | *
126 | * The aspect ratio will only be enforced in 127 | * {@link StandOutWindow#onTouchHandleResize(int, Window, View, MotionEvent)} 128 | * . The aspect ratio will not be enforced if you set the width or height of 129 | * the window's LayoutParams manually. 130 | * 131 | * @see StandOutWindow#onTouchHandleResize(int, Window, View, MotionEvent) 132 | */ 133 | public static final int FLAG_WINDOW_ASPECT_RATIO_ENABLE = 1 << flag_bit++; 134 | 135 | /** 136 | * Setting this flag indicates that the system should resize the window when 137 | * it detects a pinch-to-zoom gesture. 138 | * 139 | * @see Window#onInterceptTouchEvent(MotionEvent) 140 | */ 141 | public static final int FLAG_WINDOW_PINCH_RESIZE_ENABLE = 1 << flag_bit++; 142 | 143 | /** 144 | * Setting this flag indicates that the window does not need focus. If this 145 | * flag is set, the system will not take care of setting and unsetting the 146 | * focus of windows based on user touch and key events. 147 | * 148 | *
149 | * You will most likely need focus if your window contains any of the 150 | * following: Button, ListView, EditText. 151 | * 152 | *
153 | * The benefit of disabling focus is that your window will not consume any 154 | * key events. Normally, focused windows will consume the Back and Menu 155 | * keys. 156 | * 157 | * @see {@link StandOutWindow#focus(int)} 158 | * @see {@link StandOutWindow#unfocus(int)} 159 | * 160 | */ 161 | public static final int FLAG_WINDOW_FOCUSABLE_DISABLE = 1 << flag_bit++; 162 | 163 | /** 164 | * Setting this flag indicates that the system should not change the 165 | * window's visual state when focus is changed. If this flag is set, the 166 | * implementation can choose to change the visual state in 167 | * {@link StandOutWindow#onFocusChange(int, Window, boolean)}. 168 | * 169 | * @see {@link Window#onFocus(boolean)} 170 | * 171 | */ 172 | //public static final int FLAG_WINDOW_FOCUS_INDICATOR_DISABLE = 1 << flag_bit++; 173 | 174 | /** 175 | * Setting this flag indicates that the system should disable all 176 | * compatibility workarounds. The default behavior is to run 177 | * {@link Window#fixCompatibility(View, int)} on the view returned by the 178 | * implementation. 179 | * 180 | * @see {@link Window#fixCompatibility(View, int)} 181 | */ 182 | public static final int FLAG_FIX_COMPATIBILITY_ALL_DISABLE = 1 << flag_bit++; 183 | 184 | /** 185 | * Setting this flag indicates that the system should disable all additional 186 | * functionality. The default behavior is to run 187 | * {@link Window#addFunctionality(View, int)} on the view returned by the 188 | * implementation. 189 | * 190 | * @see {@link StandOutWindow#addFunctionality(View, int)} 191 | */ 192 | public static final int FLAG_ADD_FUNCTIONALITY_ALL_DISABLE = 1 << flag_bit++; 193 | 194 | /** 195 | * Setting this flag indicates that the system should disable adding the 196 | * resize handle additional functionality to a custom View R.id.corner. 197 | * 198 | *
199 | * If {@link #FLAG_DECORATION_SYSTEM} is set, the user will always be able 200 | * to resize the window with the default corner. 201 | * 202 | * @see {@link Window#addFunctionality(View, int)} 203 | */ 204 | public static final int FLAG_ADD_FUNCTIONALITY_RESIZE_DISABLE = 1 << flag_bit++; 205 | 206 | /** 207 | * Setting this flag indicates that the system should disable adding the 208 | * drop down menu additional functionality to a custom View 209 | * R.id.window_icon. 210 | * 211 | *
212 | * If {@link #FLAG_DECORATION_SYSTEM} is set, the user will always be able
213 | * to show the drop down menu with the default window icon.
214 | *
215 | * @see {@link Window#addFunctionality(View, int)}
216 | */
217 | public static final int FLAG_ADD_FUNCTIONALITY_DROP_DOWN_DISABLE = 1 << flag_bit++;
218 |
219 |
220 | }
--------------------------------------------------------------------------------
/app/src/main/java/wei/mark/standout/ui/TouchInfo.java:
--------------------------------------------------------------------------------
1 | package wei.mark.standout.ui;
2 |
3 | import java.util.Locale;
4 |
5 | /**
6 | * This class holds temporal touch and gesture information. Mainly used to hold
7 | * temporary data for onTouchEvent(MotionEvent).
8 | *
9 | * @author Mark Wei
364 | * The system window decorations support hiding, closing, moving, and
365 | * resizing.
366 | *
367 | * @return The frame view containing the system window decorations.
368 | */
369 | private View getSystemDecorations() {
370 | final View decorations = mLayoutInflater.inflate(
371 | getDecorationStyle(), null);
372 |
373 | // icon
374 | final ImageView icon = (ImageView) decorations
375 | .findViewById(R.id.window_icon);
376 | icon.setImageResource(mContext.getAppIcon());
377 | icon.setOnClickListener(new OnClickListener() {
378 |
379 | @Override
380 | public void onClick(View v) {
381 | PopupWindow dropDown = mContext.getDropDown(id);
382 | if (dropDown != null) {
383 | dropDown.showAsDropDown(icon);
384 | }
385 | }
386 | });
387 |
388 | // title
389 | TextView title = (TextView) decorations.findViewById(R.id.title);
390 | title.setText(mContext.getTitle(id));
391 |
392 | // hide
393 | View hide = decorations.findViewById(R.id.hide);
394 | hide.setOnClickListener(new OnClickListener() {
395 |
396 | @Override
397 | public void onClick(View v) {
398 | mContext.hide(id);
399 | }
400 | });
401 | hide.setVisibility(View.GONE);
402 |
403 | // maximize
404 | View maximize = decorations.findViewById(R.id.maximize);
405 | maximize.setOnClickListener(new OnClickListener() {
406 |
407 | @Override
408 | public void onClick(View v) {
409 | StandOutLayoutParams params = getLayoutParams();
410 | boolean isMaximized = data
411 | .getBoolean(WindowDataKeys.IS_MAXIMIZED);
412 | if (isMaximized && params.width == displayWidth
413 | && params.height == displayHeight && params.x == 0
414 | && params.y == 0) {
415 | data.putBoolean(WindowDataKeys.IS_MAXIMIZED, false);
416 | int oldWidth = data.getInt(
417 | WindowDataKeys.WIDTH_BEFORE_MAXIMIZE, -1);
418 | int oldHeight = data.getInt(
419 | WindowDataKeys.HEIGHT_BEFORE_MAXIMIZE, -1);
420 | int oldX = data
421 | .getInt(WindowDataKeys.X_BEFORE_MAXIMIZE, -1);
422 | int oldY = data
423 | .getInt(WindowDataKeys.Y_BEFORE_MAXIMIZE, -1);
424 | edit().setSize(oldWidth, oldHeight).setPosition(oldX, oldY)
425 | .commit();
426 | } else {
427 | data.putBoolean(WindowDataKeys.IS_MAXIMIZED, true);
428 | data.putInt(WindowDataKeys.WIDTH_BEFORE_MAXIMIZE,
429 | params.width);
430 | data.putInt(WindowDataKeys.HEIGHT_BEFORE_MAXIMIZE,
431 | params.height);
432 | data.putInt(WindowDataKeys.X_BEFORE_MAXIMIZE, params.x);
433 | data.putInt(WindowDataKeys.Y_BEFORE_MAXIMIZE, params.y);
434 | edit().setSize(1f, 1f).setPosition(0, 0).commit();
435 | }
436 |
437 | mContext.onWindowStateChanged(mContext.getUniqueId(),Window.this,body);
438 | }
439 | });
440 |
441 | // close
442 |
443 |
444 |
445 | View close = decorations.findViewById(R.id.close);
446 | close.setOnClickListener(new OnClickListener() {
447 |
448 | @Override
449 | public void onClick(View v) {
450 |
451 | Utils.Confirm(mContext, "是否退出?", new Runnable() {
452 | @Override
453 | public void run() {
454 | mContext.close(id);
455 | }
456 | });
457 | }
458 | });
459 |
460 |
461 |
462 |
463 | View custom = decorations.findViewById(R.id.custom);
464 | custom.setOnClickListener(new OnClickListener() {
465 |
466 | @Override
467 | public void onClick(View v) {
468 | mContext.onCustomButton1Click(id);
469 | }
470 | });
471 |
472 |
473 | // move
474 | View titlebar = decorations.findViewById(R.id.titlebar);
475 | titlebar.setOnTouchListener(new OnTouchListener() {
476 |
477 | @Override
478 | public boolean onTouch(View v, MotionEvent event) {
479 | // handle dragging to move
480 | boolean consumed = mContext.onTouchHandleMove(id, Window.this,
481 | v, event);
482 | return consumed;
483 | }
484 | });
485 |
486 | // resize
487 | View corner = decorations.findViewById(R.id.corner);
488 | corner.setOnTouchListener(new OnTouchListener() {
489 |
490 | @Override
491 | public boolean onTouch(View v, MotionEvent event) {
492 | // handle dragging to move
493 | boolean consumed = mContext.onTouchHandleResize(id,
494 | Window.this, v, event);
495 |
496 | return consumed;
497 | }
498 | });
499 |
500 | // set window appearance and behavior based on flags
501 | if (Utils.isSet(flags, StandOutFlags.FLAG_WINDOW_HIDE_ENABLE)) {
502 | hide.setVisibility(View.VISIBLE);
503 | }
504 | if (Utils.isSet(flags, StandOutFlags.FLAG_DECORATION_MAXIMIZE_DISABLE)) {
505 | maximize.setVisibility(View.GONE);
506 | }
507 | if (Utils.isSet(flags, StandOutFlags.FLAG_DECORATION_CLOSE_DISABLE)) {
508 | close.setVisibility(View.GONE);
509 | }
510 | if (Utils.isSet(flags, StandOutFlags.FLAG_DECORATION_MOVE_DISABLE)) {
511 | titlebar.setOnTouchListener(null);
512 | }
513 | if (Utils.isSet(flags, StandOutFlags.FLAG_DECORATION_RESIZE_DISABLE)) {
514 | corner.setVisibility(View.GONE);
515 | }
516 |
517 | return decorations;
518 | }
519 |
520 |
521 |
522 |
523 |
524 | /**
525 | * Implement StandOut specific additional functionalities.
526 | *
527 | *
528 | * Currently, this method does the following:
529 | *
530 | *
531 | * Attach resize handles: For every View found to have id R.id.corner,
532 | * attach an OnTouchListener that implements resizing the window.
533 | *
534 | * @param root
535 | * The view hierarchy that is part of the window.
536 | */
537 | void addFunctionality(View root) {
538 | // corner for resize
539 | if (!Utils.isSet(flags,
540 | StandOutFlags.FLAG_ADD_FUNCTIONALITY_RESIZE_DISABLE)) {
541 | View corner = root.findViewById(R.id.corner);
542 | if (corner != null) {
543 | corner.setOnTouchListener(new OnTouchListener() {
544 |
545 | @Override
546 | public boolean onTouch(View v, MotionEvent event) {
547 | // handle dragging to move
548 | boolean consumed = mContext.onTouchHandleResize(id,
549 | Window.this, v, event);
550 |
551 | return consumed;
552 | }
553 | });
554 | }
555 | }
556 |
557 | // window_icon for drop down
558 | if (!Utils.isSet(flags,
559 | StandOutFlags.FLAG_ADD_FUNCTIONALITY_DROP_DOWN_DISABLE)) {
560 | final View icon = root.findViewById(R.id.window_icon);
561 | if (icon != null) {
562 | icon.setOnClickListener(new OnClickListener() {
563 |
564 | @Override
565 | public void onClick(View v) {
566 | PopupWindow dropDown = mContext.getDropDown(id);
567 | if (dropDown != null) {
568 | dropDown.showAsDropDown(icon);
569 | }
570 | }
571 | });
572 | }
573 | }
574 | }
575 |
576 | /**
577 | * Iterate through each View in the view hiearchy and implement StandOut
578 | * specific compatibility workarounds.
579 | *
580 | *
581 | * Currently, this method does the following:
582 | *
583 | *
584 | * Nothing yet.
585 | *
586 | * @param root
587 | * The root view hierarchy to iterate through and check.
588 | */
589 | void fixCompatibility(View root) {
590 | Queue
631 | * The anchor point effects the following methods:
632 | *
633 | *
634 | * {@link #setSize(float, float)}, {@link #setSize(int, int)},
635 | * {@link #setPosition(int, int)}, {@link #setPosition(int, int)}.
636 | *
637 | * The window will move, expand, or shrink around the anchor point.
638 | *
639 | *
640 | * Values must be between 0 and 1, inclusive. 0 means the left/top, 0.5
641 | * is the center, 1 is the right/bottom.
642 | */
643 | float anchorX, anchorY;
644 |
645 | public Editor() {
646 | mParams = getLayoutParams();
647 | anchorX = anchorY = 0;
648 | }
649 |
650 | public Editor setAnchorPoint(float x, float y) {
651 | if (x < 0 || x > 1 || y < 0 || y > 1) {
652 | throw new IllegalArgumentException(
653 | "Anchor point must be between 0 and 1, inclusive.");
654 | }
655 |
656 | anchorX = x;
657 | anchorY = y;
658 |
659 | return this;
660 | }
661 |
662 | /**
663 | * Set the size of this window as percentages of max screen size. The
664 | * window will expand and shrink around the top-left corner, unless
665 | * you've set a different anchor point with
666 | * {@link #setAnchorPoint(float, float)}.
667 | *
668 | * Changes will not applied until you {@link #commit()}.
669 | *
670 | * @param percentWidth
671 | * @param percentHeight
672 | * @return The same Editor, useful for method chaining.
673 | */
674 | public Editor setSize(float percentWidth, float percentHeight) {
675 | return setSize((int) (displayWidth * percentWidth),
676 | (int) (displayHeight * percentHeight));
677 | }
678 |
679 | /**
680 | * Set the size of this window in absolute pixels. The window will
681 | * expand and shrink around the top-left corner, unless you've set a
682 | * different anchor point with {@link #setAnchorPoint(float, float)}.
683 | *
684 | * Changes will not applied until you {@link #commit()}.
685 | *
686 | * @param width
687 | * @param height
688 | * @return The same Editor, useful for method chaining.
689 | */
690 | public Editor setSize(int width, int height) {
691 | return setSize(width, height, false);
692 | }
693 |
694 | /**
695 | * Set the size of this window in absolute pixels. The window will
696 | * expand and shrink around the top-left corner, unless you've set a
697 | * different anchor point with {@link #setAnchorPoint(float, float)}.
698 | *
699 | * Changes will not applied until you {@link #commit()}.
700 | *
701 | * @param width
702 | * @param height
703 | * @param skip
704 | * Don't call {@link #setPosition(int, int)} to avoid stack
705 | * overflow.
706 | * @return The same Editor, useful for method chaining.
707 | */
708 | private Editor setSize(int width, int height, boolean skip) {
709 | if (mParams != null) {
710 | if (anchorX < 0 || anchorX > 1 || anchorY < 0 || anchorY > 1) {
711 | throw new IllegalStateException(
712 | "Anchor point must be between 0 and 1, inclusive.");
713 | }
714 |
715 | int lastWidth = mParams.width;
716 | int lastHeight = mParams.height;
717 |
718 | if (width != UNCHANGED) {
719 | mParams.width = width;
720 | }
721 | if (height != UNCHANGED) {
722 | mParams.height = height;
723 | }
724 |
725 | // set max width/height
726 | int maxWidth = mParams.maxWidth;
727 | int maxHeight = mParams.maxHeight;
728 |
729 | if (Utils.isSet(flags,
730 | StandOutFlags.FLAG_WINDOW_EDGE_LIMITS_ENABLE)) {
731 | maxWidth = (int) Math.min(maxWidth, displayWidth);
732 | maxHeight = (int) Math.min(maxHeight, displayHeight);
733 | }
734 |
735 | // keep window between min and max
736 | mParams.width = Math.min(
737 | Math.max(mParams.width, mParams.minWidth), maxWidth);
738 | mParams.height = Math.min(
739 | Math.max(mParams.height, mParams.minHeight), maxHeight);
740 |
741 | // keep window in aspect ratio
742 | if (Utils.isSet(flags,
743 | StandOutFlags.FLAG_WINDOW_ASPECT_RATIO_ENABLE)) {
744 | int ratioWidth = (int) (mParams.height * touchInfo.ratio);
745 | int ratioHeight = (int) (mParams.width / touchInfo.ratio);
746 | if (ratioHeight >= mParams.minHeight
747 | && ratioHeight <= mParams.maxHeight) {
748 | // width good adjust height
749 | mParams.height = ratioHeight;
750 | } else {
751 | // height good adjust width
752 | mParams.width = ratioWidth;
753 | }
754 | }
755 |
756 | if (!skip) {
757 | // set position based on anchor point
758 | setPosition((int) (mParams.x + lastWidth * anchorX),
759 | (int) (mParams.y + lastHeight * anchorY));
760 | }
761 | }
762 |
763 | return this;
764 | }
765 |
766 | /**
767 | * Set the position of this window as percentages of max screen size.
768 | * The window's top-left corner will be positioned at the given x and y,
769 | * unless you've set a different anchor point with
770 | * {@link #setAnchorPoint(float, float)}.
771 | *
772 | * Changes will not applied until you {@link #commit()}.
773 | *
774 | * @param percentWidth
775 | * @param percentHeight
776 | * @return The same Editor, useful for method chaining.
777 | */
778 | public Editor setPosition(float percentWidth, float percentHeight) {
779 | return setPosition((int) (displayWidth * percentWidth),
780 | (int) (displayHeight * percentHeight));
781 | }
782 |
783 | /**
784 | * Set the position of this window in absolute pixels. The window's
785 | * top-left corner will be positioned at the given x and y, unless
786 | * you've set a different anchor point with
787 | * {@link #setAnchorPoint(float, float)}.
788 | *
789 | * Changes will not applied until you {@link #commit()}.
790 | *
791 | * @param x
792 | * @param y
793 | * @return The same Editor, useful for method chaining.
794 | */
795 | public Editor setPosition(int x, int y) {
796 | return setPosition(x, y, false);
797 | }
798 |
799 | /**
800 | * Set the position of this window in absolute pixels. The window's
801 | * top-left corner will be positioned at the given x and y, unless
802 | * you've set a different anchor point with
803 | * {@link #setAnchorPoint(float, float)}.
804 | *
805 | * Changes will not applied until you {@link #commit()}.
806 | *
807 | * @param x
808 | * @param y
809 | * @param skip
810 | * Don't call {@link #setPosition(int, int)} and
811 | * {@link #setSize(int, int)} to avoid stack overflow.
812 | * @return The same Editor, useful for method chaining.
813 | */
814 | private Editor setPosition(int x, int y, boolean skip) {
815 | if (mParams != null) {
816 | if (anchorX < 0 || anchorX > 1 || anchorY < 0 || anchorY > 1) {
817 | throw new IllegalStateException(
818 | "Anchor point must be between 0 and 1, inclusive.");
819 | }
820 |
821 | // sets the x and y correctly according to anchorX and
822 | // anchorY
823 | if (x != UNCHANGED) {
824 | mParams.x = (int) (x - mParams.width * anchorX);
825 | }
826 | if (y != UNCHANGED) {
827 | mParams.y = (int) (y - mParams.height * anchorY);
828 | }
829 |
830 | if (Utils.isSet(flags,
831 | StandOutFlags.FLAG_WINDOW_EDGE_LIMITS_ENABLE)) {
832 | // if gravity is not TOP|LEFT throw exception
833 | if (mParams.gravity != (Gravity.TOP | Gravity.LEFT)) {
834 | throw new IllegalStateException(
835 | "The window "
836 | + id
837 | + " gravity must be TOP|LEFT if FLAG_WINDOW_EDGE_LIMITS_ENABLE or FLAG_WINDOW_EDGE_TILE_ENABLE is set.");
838 | }
839 |
840 | // keep window inside edges
841 | mParams.x = Math.min(Math.max(mParams.x, 0), displayWidth
842 | - mParams.width);
843 | mParams.y = Math.min(Math.max(mParams.y, 0), displayHeight
844 | - mParams.height);
845 | }
846 | }
847 |
848 | return this;
849 | }
850 |
851 | /**
852 | * Commit the changes to this window. Updates the layout. This Editor
853 | * cannot be used after you commit.
854 | */
855 | public void commit() {
856 | if (mParams != null) {
857 | mContext.updateViewLayout(id, mParams);
858 | mParams = null;
859 | }
860 | }
861 | }
862 |
863 | public static class WindowDataKeys {
864 | public static final String IS_MAXIMIZED = "isMaximized";
865 | public static final String WIDTH_BEFORE_MAXIMIZE = "widthBeforeMaximize";
866 | public static final String HEIGHT_BEFORE_MAXIMIZE = "heightBeforeMaximize";
867 | public static final String X_BEFORE_MAXIMIZE = "xBeforeMaximize";
868 | public static final String Y_BEFORE_MAXIMIZE = "yBeforeMaximize";
869 | }
870 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZYFDroid/android-webgame-browser/3b21e0439696ee68b6b04856c10f305b23c7e5ec/app/src/main/res/drawable-hdpi/close.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/corner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZYFDroid/android-webgame-browser/3b21e0439696ee68b6b04856c10f305b23c7e5ec/app/src/main/res/drawable-hdpi/corner.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/hide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZYFDroid/android-webgame-browser/3b21e0439696ee68b6b04856c10f305b23c7e5ec/app/src/main/res/drawable-hdpi/hide.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_menu_capture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZYFDroid/android-webgame-browser/3b21e0439696ee68b6b04856c10f305b23c7e5ec/app/src/main/res/drawable-hdpi/ic_menu_capture.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/maximize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZYFDroid/android-webgame-browser/3b21e0439696ee68b6b04856c10f305b23c7e5ec/app/src/main/res/drawable-hdpi/maximize.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_notification_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZYFDroid/android-webgame-browser/3b21e0439696ee68b6b04856c10f305b23c7e5ec/app/src/main/res/drawable-xhdpi/ic_notification_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/shadow.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZYFDroid/android-webgame-browser/3b21e0439696ee68b6b04856c10f305b23c7e5ec/app/src/main/res/drawable-xhdpi/shadow.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_btn_close.xml:
--------------------------------------------------------------------------------
1 |
2 |