揭秘uc浏览器二
这节,四个议题:
①一个网页显示在webview控件中
②如何正常隐藏显示标题栏。
③如何用runnable来隐藏标题栏,这样子就更加的专业化。
④上节我们说道了QuickActionGrid,看他长得怎么样。
如何显示webview控件了,This is a question?这个除了上面的文章的支持外,主要是这个updateUI的方法。
/**
* Update the UI: Url edit text, previous/next button state,...
*/
private void updateUI() {
mUrlEditText.removeTextChangedListener(mUrlTextWatcher);
mUrlEditText.setText(mCurrentWebView.getUrl());
mUrlEditText.addTextChangedListener(mUrlTextWatcher); mPreviousButton.setEnabled(mCurrentWebView.canGoBack());
mNextButton.setEnabled(mCurrentWebView.canGoForward()); if (mCurrentWebView.getUrl() != null)
mRemoveTabButton.setEnabled((mViewFlipper.getChildCount() > 1 || !mCurrentWebView.getUrl().equals(Constants.URL_ABOUT_START)));
else
mRemoveTabButton.setEnabled(mViewFlipper.getChildCount() > 1); mProgressBar.setProgress(mCurrentWebView.getProgress()); updateGoButton(); updateTitle(); updateFavIcon();
}
这段代码是如此的熟悉,我们也来总结总结:
①我们需要更新URL文本框的数据,添加新的事件的监听。
②把前一步,后一步按钮设置是否禁用。
③把移去按钮,设置是否禁用。
④把进度条进度进行更新。
⑤更新去哪儿的按钮
⑥更新相应的标题
⑦更新相应的图标
这个webview视图进行显示了,相应视图也进行更新了。
如何正常显示标题栏,这个就是updateTitle方法做的事情,来瞧一瞧:
/**
* Update the application title.
*/
private void updateTitle() {
String value = mCurrentWebView.getTitle(); if ((value != null) &&
(value.length() > 0)) {
this.setTitle(String.format(getResources().getString(R.string.ApplicationNameUrl), value));
} else {
clearTitle();
}
}
这是一个更新标题的方法,我们可以得出来相应总结,
①我们可以获取当前webview的标题,如果是标题不为空的话,我们就设置相应的标题。否则就清空标题.
正常的隐藏标题栏,极大提高了用户体验,这是一个runnable接口功劳,那具体怎么做了:
/**
* Start a runnable to hide the tool bars after a user-defined delay.
*/
private void startToolbarsHideRunnable() { if (mHideToolbarsRunnable != null) {
mHideToolbarsRunnable.setDisabled();
} int delay = Integer.parseInt(Controller.getInstance().getPreferences().getString(Constants.PREFERENCES_GENERAL_BARS_DURATION, "3000"));
if (delay <= 0) {
delay = 3000;
} mHideToolbarsRunnable = new HideToolbarsRunnable(this, delay);
new Thread(mHideToolbarsRunnable).start();
} /**
* Hide the tool bars.
*/
public void hideToolbars() {
if (mUrlBarVisible) {
if ((!mUrlEditText.hasFocus()) &&
(!mToolsActionGridVisible)) { if (!mCurrentWebView.isLoading()) {
setToolbarsVisibility(false);
}
}
}
mHideToolbarsRunnable = null;
}
我这里能够得到这样的提示了:
①用到sharedpreference看用户设置时间,如果没有设置时间的话,默认是3秒就开启一条线程将其标题栏隐藏了。为什么会用到多线程了,这样不会更新主界面造成卡顿的现象。
②如果toolbar是隐藏的,就将其隐藏。
QuickActionGrid是一个自定义控件,为什么用自定义控件了,
①android自带的控件太多bug。
②自定义控件也非常的灵活。
源代码如下:
public class QuickActionGrid extends QuickActionWidget { // grid 控件
private GridView mGridView; /**
* grid 构造函数 数据的初始化
* @param context 上下文对象
*/
public QuickActionGrid(Context context) {
super(context); setContentView(R.layout.gd_quick_action_grid); final View v = getContentView();
mGridView = (GridView) v.findViewById(R.id.gdi_grid);
}
/**
* 弹出相应的action的方法
*/ @Override
protected void populateQuickActions(final List<QuickAction> quickActions) { mGridView.setAdapter(new BaseAdapter() { public View getView(int position, View view, ViewGroup parent) { TextView textView = (TextView) view; if (view == null) {
final LayoutInflater inflater = LayoutInflater.from(getContext());
textView = (TextView) inflater.inflate(R.layout.gd_quick_action_grid_item, mGridView, false);
} QuickAction quickAction = quickActions.get(position);
textView.setText(quickAction.mTitle);
textView.setCompoundDrawablesWithIntrinsicBounds(null, quickAction.mDrawable, null, null); return textView; } public long getItemId(int position) {
return position;
} public Object getItem(int position) {
return null;
} public int getCount() {
return quickActions.size();
}
}); mGridView.setOnItemClickListener(mInternalItemClickListener);
} /**
* 尺寸改变的事件
*/
@Override
protected void onMeasureAndLayout(Rect anchorRect, View contentView) { contentView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
contentView.measure(MeasureSpec.makeMeasureSpec(getScreenWidth(), MeasureSpec.EXACTLY),
LayoutParams.WRAP_CONTENT); int rootHeight = contentView.getMeasuredHeight(); int offsetY = getArrowOffsetY();
int dyTop = anchorRect.top;
int dyBottom = getScreenHeight() - anchorRect.bottom; boolean onTop = (dyTop > dyBottom);
int popupY = (onTop) ? anchorRect.top - rootHeight + offsetY : anchorRect.bottom - offsetY; setWidgetSpecs(popupY, onTop);
} /**
* 每项点击的事件
*/
private OnItemClickListener mInternalItemClickListener = new OnItemClickListener() {
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
getOnQuickActionClickListener().onQuickActionClicked(QuickActionGrid.this, position);
if (getDismissOnClick()) {
dismiss();
}
}
}; }
这个quickGrid控件是继承与quickWidget控件,这也是一个自定义控件。对于他这个方法,我们集中于populateQuickActions方法和onMeasureAndLayout方法。
①populateQuickActions方法其实就是一个填充相应数据的方法,就是把相应的数据通过baseAdapter填充与gridview控件,gridview控件用于显示相应数据项。
②mInternalItemClickListener方法了,就是为每一个item赋予点击事件,如果这个点击动作已经执行以后,就相应弹出的popwindow就进行了隐藏。
quickwidget控件在这个项目用的很多,这是许多控件的基类,怎么写的。
private static final int MEASURE_AND_LAYOUT_DONE = 1 << 1; private final int[] mLocation = new int[2];
private final Rect mRect = new Rect(); private int mPrivateFlags; private Context mContext; private boolean mDismissOnClick;
private int mArrowOffsetY; private int mPopupY;
private boolean mIsOnTop; private int mScreenHeight;
private int mScreenWidth;
private boolean mIsDirty; private OnQuickActionClickListener mOnQuickActionClickListener;
private ArrayList<QuickAction> mQuickActions = new ArrayList<QuickAction>(); /**
* Interface that may be used to listen to clicks on quick actions.
*
* @author Benjamin Fellous
* @author Cyril Mottier
*/
public static interface OnQuickActionClickListener {
/**
* Clients may implement this method to be notified of a click on a
* particular quick action.
*
* @param position Position of the quick action that have been clicked.
*/
void onQuickActionClicked(QuickActionWidget widget, int position);
} /**
* Creates a new QuickActionWidget for the given context.
*
* @param context The context in which the QuickActionWidget is running in
*/
public QuickActionWidget(Context context) {
super(context); mContext = context; initializeDefault(); setFocusable(true);
setTouchable(true);
setOutsideTouchable(true);
setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
setHeight(WindowManager.LayoutParams.WRAP_CONTENT); final WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
mScreenWidth = windowManager.getDefaultDisplay().getWidth();
mScreenHeight = windowManager.getDefaultDisplay().getHeight();
} /**
* Equivalent to {@link PopupWindow#setContentView(View)} but with a layout
* identifier.
*
* @param layoutId The layout identifier of the view to use.
*/
public void setContentView(int layoutId) {
setContentView(LayoutInflater.from(mContext).inflate(layoutId, null));
} private void initializeDefault() {
mDismissOnClick = true;
mArrowOffsetY = mContext.getResources().getDimensionPixelSize(R.dimen.gd_arrow_offset);
} /**
* Returns the arrow offset for the Y axis.
*
* @see {@link #setArrowOffsetY(int)}
* @return The arrow offset.
*/
public int getArrowOffsetY() {
return mArrowOffsetY;
} /**
* Sets the arrow offset to a new value. Setting an arrow offset may be
* particular useful to warn which view the QuickActionWidget is related to.
* By setting a positive offset, the arrow will overlap the view given by
* {@link #show(View)}. The default value is 5dp.
*
* @param offsetY The offset for the Y axis
*/
public void setArrowOffsetY(int offsetY) {
mArrowOffsetY = offsetY;
} /**
* Returns the width of the screen.
*
* @return The width of the screen
*/
protected int getScreenWidth() {
return mScreenWidth;
} /**
* Returns the height of the screen.
*
* @return The height of the screen
*/
protected int getScreenHeight() {
return mScreenHeight;
} /**
* By default, a {@link QuickActionWidget} is dismissed once the user
* clicked on a {@link QuickAction}. This behavior can be changed using this
* method.
*
* @param dismissOnClick True if you want the {@link QuickActionWidget} to
* be dismissed on click else false.
*/
public void setDismissOnClick(boolean dismissOnClick) {
mDismissOnClick = dismissOnClick;
} public boolean getDismissOnClick() {
return mDismissOnClick;
} /**
* @param listener
*/
public void setOnQuickActionClickListener(OnQuickActionClickListener listener) {
mOnQuickActionClickListener = listener;
} /**
* Add a new QuickAction to this {@link QuickActionWidget}. Adding a new
* {@link QuickAction} while the {@link QuickActionWidget} is currently
* being shown does nothing. The new {@link QuickAction} will be displayed
* on the next call to {@link #show(View)}.
*
* @param action The new {@link QuickAction} to add
*/
public void addQuickAction(QuickAction action) {
if (action != null) {
mQuickActions.add(action);
mIsDirty = true;
}
} /**
* Removes all {@link QuickAction} from this {@link QuickActionWidget}.
*/
public void clearAllQuickActions() {
if (!mQuickActions.isEmpty()) {
mQuickActions.clear();
mIsDirty = true;
}
} /**
* Call that method to display the {@link QuickActionWidget} anchored to the
* given view.
*
* @param anchor The view the {@link QuickActionWidget} will be anchored to.
*/
public void show(View anchor) { final View contentView = getContentView(); if (contentView == null) {
throw new IllegalStateException("You need to set the content view using the setContentView method");
} // Replaces the background of the popup with a cleared background
setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); final int[] loc = mLocation;
anchor.getLocationOnScreen(loc);
mRect.set(loc[0], loc[1], loc[0] + anchor.getWidth(), loc[1] + anchor.getHeight()); if (mIsDirty) {
clearQuickActions();
populateQuickActions(mQuickActions);
} onMeasureAndLayout(mRect, contentView); if ((mPrivateFlags & MEASURE_AND_LAYOUT_DONE) != MEASURE_AND_LAYOUT_DONE) {
throw new IllegalStateException("onMeasureAndLayout() did not set the widget specification by calling"
+ " setWidgetSpecs()");
} showArrow();
prepareAnimationStyle();
showAtLocation(anchor, Gravity.NO_GRAVITY, 0, mPopupY);
} protected void clearQuickActions() {
if (!mQuickActions.isEmpty()) {
onClearQuickActions();
}
} protected void onClearQuickActions() {
} protected abstract void populateQuickActions(List<QuickAction> quickActions); protected abstract void onMeasureAndLayout(Rect anchorRect, View contentView); protected void setWidgetSpecs(int popupY, boolean isOnTop) {
mPopupY = popupY;
mIsOnTop = isOnTop; mPrivateFlags |= MEASURE_AND_LAYOUT_DONE;
} private void showArrow() { final View contentView = getContentView();
final int arrowId = mIsOnTop ? R.id.gdi_arrow_down : R.id.gdi_arrow_up;
final View arrow = contentView.findViewById(arrowId);
final View arrowUp = contentView.findViewById(R.id.gdi_arrow_up);
final View arrowDown = contentView.findViewById(R.id.gdi_arrow_down); if (arrowId == R.id.gdi_arrow_up) {
arrowUp.setVisibility(View.VISIBLE);
arrowDown.setVisibility(View.INVISIBLE);
} else if (arrowId == R.id.gdi_arrow_down) {
arrowUp.setVisibility(View.INVISIBLE);
arrowDown.setVisibility(View.VISIBLE);
} ViewGroup.MarginLayoutParams param = (ViewGroup.MarginLayoutParams) arrow.getLayoutParams();
param.leftMargin = mRect.centerX() - (arrow.getMeasuredWidth()) / 2;
} private void prepareAnimationStyle() { final int screenWidth = mScreenWidth;
final boolean onTop = mIsOnTop;
final int arrowPointX = mRect.centerX(); if (arrowPointX <= screenWidth / 4) {
setAnimationStyle(onTop ? R.style.GreenDroid_Animation_PopUp_Left
: R.style.GreenDroid_Animation_PopDown_Left);
} else if (arrowPointX >= 3 * screenWidth / 4) {
setAnimationStyle(onTop ? R.style.GreenDroid_Animation_PopUp_Right
: R.style.GreenDroid_Animation_PopDown_Right);
} else {
setAnimationStyle(onTop ? R.style.GreenDroid_Animation_PopUp_Center
: R.style.GreenDroid_Animation_PopDown_Center);
}
} protected Context getContext() {
return mContext;
} protected OnQuickActionClickListener getOnQuickActionClickListener() {
return mOnQuickActionClickListener;
}
首先这个控件本质是Popwindow,对于这个控件我们要探讨的有这么几点:
①show这个方法中了,主要是根据相应的锚基点来弹出来了,并且在指定的位置弹出相应的窗口。
②在showarrow这个方法,我们需要根据是否向上还是向下显示相应的箭头,给用户一个很好的提示。
③在动画的操作方法中,我们要根据其坐标是否小于全频宽度的四分之一位置,从左边的位置弹出来,其坐标从全频宽度四分之三的位置,从右侧位置弹出来了。
有了这篇文章介绍,主界面应该了解了把?下节介绍收藏和历史界面。
揭秘uc浏览器二的更多相关文章
- 揭秘uc浏览器一
首先,看一下项目完成后的,最终效果是这样的: 一.主界面 二,书签界面 三.主界面 四.操作对话框界面 这几个界面你是否看到了uc浏览器的影子了,其实我说你也可以了,在接下来篇幅中,我将手把手叫大家完 ...
- 揭秘uc浏览器四
请问大家用过uc浏览器,他收藏一个网页是怎么操作的? 是不是这样,按菜单键——弹出添加网页,收藏网页等等的菜单操作,这个菜单操作很人性化了,并且在前面的篇幅已经说过了,这里不做太多的赘述了. 我这里只 ...
- 揭秘uc浏览器三
这节我们主要讨论收藏与历史记录页面的边边角角. 首先,看看他的最终的效果图了: 照例了,我们先看看他的布局文件: <!-- tab布局文件 --> <TabHost xmlns:an ...
- 小说接入UC浏览器内核技术对话(二)
质辛@灿岩 质辛跟我们说一下那个删除文件的逻辑吧质辛@灿岩 应该不是删除cache下所有文件吧?质辛质辛@智鹰 提供一下我们的临时文件完整路径给 灿岩吧质辛@智鹰 是负责我们ucsdk的 技术对 ...
- 小说接入UC浏览器内核技术对话(一)
质辛@灿岩 质辛跟我们说一下那个删除文件的逻辑吧质辛@灿岩 应该不是删除cache下所有文件吧?质辛@智鹰 提供一下我们的临时文件完整路径给 灿岩吧质辛@智鹰 是负责我们ucsdk的 技术对接灿 ...
- 手机端UC浏览器,在java开发的下载功能中存在的问题?
在java web开发中,不同浏览器对下载文件的格式有不同的要求,有时会出现视频,音频等文件无法下载的问题.我在开发中,也遇到类似的问题,觉得很苦恼. 经过百度和请教学习,得到2个解决方案. 首先得到 ...
- 让你在PC上调试Web App,UC浏览器发布开发者版
目前,在手机上使用浏览器访问网页,无法便捷地进行网页语言调试.手机屏幕相对较小且操作不便,直接在手机上进行网页数据调试不太现实. 因此,UC使用技术将手机网页调试信息分离,实现一种能在大屏幕.高配置P ...
- 解决UC浏览器或微信浏览器上flex兼容问题
在UC浏览器上使用display:flex;时会不起作用,要加上兼容性写法,如下 display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ disp ...
- UC浏览器 分享到朋友圈和微信好友 分类: JavaScript 2015-04-28 14:45 615人阅读 评论(1) 收藏
用手机UC浏览器访问新浪微博,会注意到有这样的两个分享按钮: 在手机端浏览器里,点击分享按钮,就可以启动微信客户端并分享到微信.研究了下其源代码,存在这样的一个js:http://mjs.sinaim ...
随机推荐
- [CF580E]Kefa and Watch
题目大意: 维护一个由'0'~'9'构成的字符串,支持以下两种操作: 1.将指定区间内的所有字符修改为同一指定字符. 2.询问$x$是否为指定区间内的循环节. 思路: 建立一棵线段树,维护每个子串的哈 ...
- [原创]浅谈H5页面测试介绍
[原创]浅谈H5页面测试介绍 目前移动互联网非常火热,除了各种App,H5也是非常热,由于H5跨平台,且版本更新容易,做为引流或获客是非常好的一种简单低成本平台:今天来谈谈H5页面测试都要测试什么? ...
- Sed&awk笔记之sed篇(转)
Sed是什么 <sed and awk>一书中(1.2 A Stream Editor)是这样解释的: Sed is a "non-interactive" strea ...
- ADO.NET理论+实践
题记: 每一事物的产生和存在都有其特定的理由. 理论:ADO.NET是一组与数据源进行交互的面向对象类库.通常情况下数据源就是数据库,当然同样也能是文本文件,Excel表格或XML文件,我们知道的数 ...
- log4j deadlock
用了这么久的Log4j这次倒下了,而且官方也还没有给出解决方案. 描述:tomcat 经过一天多时间的访问,出现了hang ,使用 Jstack 查看堆栈后,发现现成 blocked ,主要是 Log ...
- Windows/Linux下引用jar包,并用javac/java编译运行
Windows/Linux下引用jar包,并用javac/java编译运行,有需要的朋友可以参考下. 1> Windows 假设要引用的jar放在D:/test目录下,名字为t1.jar, ja ...
- python测试开发django-42.auth模块登陆认证
前言 在开发一个网站时,经常会用到用户的注册和登陆相关的账号管理功能,auth模块是Django提供的标准权限管理系统,可以提供用户身份认证, 用户组和权限管理. 像用户注册.用户登录.用户认证.注销 ...
- linux内核netfilter模块分析之:HOOKs点的注册及调用
转自;http://blog.csdn.net/suiyuan19840208/article/details/19684883 -1: 为什么要写这个东西?最近在找工作,之前netfilter 这一 ...
- Swift - 多个mask的动画效果
Swift - 多个mask的动画效果 效果 源码 https://github.com/YouXianMing/Swift-Animations // // TranformFadeView.swi ...
- 真爱如血第七季/全集True Blood迅雷下载
第七季 True Blood Season 7(2014)看点:由于日本科学家合成了一种人造血,一夜之间,吸血鬼不再是人们心中那富有传奇色彩的怪物,而是能与人类和平相处的朋友.已经播出五年的HBO吸血 ...