项目上有个奇葩需求,一个网页的扭蛋游戏,需要半屏展示,并且需要最小化。

1、半屏展示可以用dialogfragment,加载webview,把加载的webview设置半屏的高度就行。当然,webview,最好以java代码创建,再add到布局里面,不然会内存泄漏。

class HalfSizeWebViewFragment : DialogFragment() {
var activity: YYSGroupKRoomActivity? = null
private val mWebView by lazy {
RoundWebView(Sheng.getInstance())
}
private val window by lazy {
dialog!!.window
}
private var http:String? = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NO_TITLE, R.style.Theme_AppCompat_Dialog)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_half_size_web_view, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
http = arguments?.getString("http")
initWebView()
initView()
showH5(http)
}
@SuppressLint("NewApi")
private fun initView() {
mNullView?.setOnClickListener {
dismissAllowingStateLoss()
}
}
override fun onStart() {
super.onStart()
if(dialog !=null) {
window!!.setGravity(Gravity.BOTTOM)
window.setWindowAnimations(R.style.luck_box_dialog_theme)
window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
val params: WindowManager.LayoutParams = window.attributes
params.dimAmount = 0.0f
params.flags = params.flags or WindowManager.LayoutParams.FLAG_DIM_BEHIND
window.attributes = params
}
}
private fun initWebView() {
mWebView.settings.javaScriptEnabled = true
if(activity!=null){
mWebView.webViewClient = MyWebViewClient(this)
}
mWebView.settings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
mWebView.settings.textZoom = 100
//设置支持脚本
mWebView.settings.javaScriptEnabled = true
//设置支持DOM Storage
mWebView.settings.domStorageEnabled = true
解决图片不显示
mWebView.settings.blockNetworkImage = false
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//解决引用http地址的图片不显示
mWebView.settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
}
// 加快HTML网页装载完成的速度 故在WebView初始化时设置如下代码:
mWebView.settings.loadsImagesAutomatically = Build.VERSION.SDK_INT >= 19
// 修改ua使得web端正确判断
mWebView.settings.userAgentString = "mchangapp/android"
//设置webview支持插件
// mWebView.getSettings().setPluginsEnabled(true);
mWebView.settings.cacheMode = WebSettings.LOAD_NO_CACHE
// 将一个对象起一个别名传入,在JS代码中用这个别名代替这个对象,可以调用这个对象的一些方法
mWebView.addJavascriptInterface(WebJSInterface(this, mUser), "webJsInstence")
mWebViewBox?.let {
it.addView(mWebView, ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
}
mWebView.setRadius(resources.getDimension(R.dimen.dp_15), resources.getDimension(R.dimen.dp_15), 0f, 0f)
}
override fun onDestroy() {
try {
// 如果先调用destroy()方法,则会命中if (isDestroyed()) return;这一行代码,需要先onDetachedFromWindow(),再
val parent = mWebView.parent
if (parent != null) {
(parent as ViewGroup).removeView(mWebView)
}
mWebView.stopLoading()
// 退出时调用此方法,移除绑定的服务,否则某些特定系统会报错
// 退出时调用此方法,移除绑定的服务,否则某些特定系统会报错
mWebView.settings.javaScriptEnabled = false
mWebView.clearHistory()
mWebView.clearView()
mWebView.removeAllViews()
mWebView.destroy()
}catch (e: java.lang.Exception){
e.printStackTrace()
}
super.onDestroy()
}
public fun hide(){
dialog.hide()
}
删除了业务代码
2、webview的圆角
public class RoundWebView extends WebView {
private Path mPath;
private Paint mPaint;
private RectF mRectF;
private final float[] mRadius = new float[8];
public RoundWebView(@NonNull Context context) {
this(context, null);
}
public RoundWebView(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public RoundWebView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPath = new Path();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mRectF = new RectF();
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
}
@SuppressLint("MissingSuperCall")
@Override
public void draw(Canvas canvas) {
int scrollX = this.getScrollX();
int scrollY = this.getScrollY();
mRectF.set(0, scrollY, scrollX + getWidth(), scrollY + getHeight());
canvas.save();
canvas.clipPath(genPath());
super.draw(canvas);
canvas.restore();
}
private Path genPath() {
mPath.reset();
mPath.addRoundRect(mRectF, mRadius, Path.Direction.CW);
return mPath;
}
public void setRadius(float topLeft, float topRight, float bottomRight, float bottomLeft) {
mRadius[0] = topLeft;
mRadius[1] = topLeft;
mRadius[2] = topRight;
mRadius[3] = topRight;
mRadius[4] = bottomRight;
mRadius[5] = bottomRight;
mRadius[6] = bottomLeft;
mRadius[7] = bottomLeft;
invalidate();
}
}
然后使用它
HalfSizeWebViewFragment mHalfSizeWebViewFragment = HalfSizeWebViewFragment.newInstance(mBean.getActionUrl());
mHalfSizeWebViewFragment.show(transaction, mHalfSizeWebViewFragment.getTag());
当我们调用HalfSizeWebViewFragment 里面的hide后,fragment会最小化,但是我们的自动扭蛋游戏变慢了,原本4秒一次,变成了5分钟。我们也没有对webview进行resumeTimers和pauseTimers的操作,那为什么这样呢?
造成这个的原因是webview没有在前台展示,系统会降低webview对cpu的使用频率。所以,解决办法就是,hide后将webview放入一个可见的布局中,show的时候再放回到Fragment里面,我这里是选择了悬浮窗。
public class HideWebViewService extends GroupRoomService {
private WindowManager mWindowManager;
private View mRootView;
private static FrameLayout mHideWebView;
public HideWebViewService() {
}
@Override
public void onCreate() {
super.onCreate();
EventBus.getDefault().register(this);
}
@Override
public void onDestroy() {
EventBus.getDefault().unregister(this);
try {
if (mWindowManager != null && mRootView != null) {
mWindowManager.removeView(mRootView);
}
if(mHideWebView!=null){
mHideWebView.removeAllViews();
}
} catch (Exception e) {
Log.i("exist", "destory");
}
super.onDestroy();
}
public static void addHideWebView(RoundWebView webView) {
try {
if(webView!=null){
ViewParent parent = webView.getParent();
((ViewGroup) parent).removeView(webView);
mHideWebView.addView(webView,new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));
}
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
int command = super.onStartCommand(intent, flags, startId);
return command;
}
public void showHideView(){
try {
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mRootView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.view_flow_window3, null);
mHideWebView = mRootView.findViewById(R.id.hide_web_views);
WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
//小于的时候不能接收点击事件,所以用申请权限的方式开启 TYPE_PHONE
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//8.0
mParams.type = TYPE_APPLICATION_OVERLAY;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//6.0
mParams.type = TYPE_PHONE;
} else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2) {//4.3以下toast没有触摸事件
mParams.type = TYPE_PHONE;
} else {
if (PermissionUtils.isMiPhone()) {//小米手机
mParams.type = TYPE_PHONE;
} else {
mParams.type = TYPE_TOAST;
}
}
mParams.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
mParams.format = PixelFormat.RGBA_8888;
mParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
int width = 1;//设置大小
int height = 1;
mParams.width = width;
mParams.height = height;
// mParams.x = (int) mCurrentX;
// mParams.y = (int) mCurrentY;
mParams.x = MATCH_PARENT;
mParams.y = WRAP_CONTENT;
mWindowManager.addView(mRootView, mParams);
}catch (Exception e){
e.printStackTrace();
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMoonEvent(MessageEvent messageEvent) {
//判断消息类型
switch (messageEvent.getState()) {
case MessageEvent.STATE_TYPE_SHOW_HIDE_WINDOW://更新悬浮窗信息
showHideView();
break;
}
}
}

悬浮窗一定要经过用户授权后才能设置布局,所以我这里再用户点击hide时请求权限,有权限了才通过EventBus初始化悬浮窗的布局。这里我们把宽高都设为1,这样就能最小化。当hide时调用addHideWebView,将webview放入进来就行啦。