这节,四个议题:

①一个网页显示在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浏览器二的更多相关文章

  1. 揭秘uc浏览器一

    首先,看一下项目完成后的,最终效果是这样的: 一.主界面 二,书签界面 三.主界面 四.操作对话框界面 这几个界面你是否看到了uc浏览器的影子了,其实我说你也可以了,在接下来篇幅中,我将手把手叫大家完 ...

  2. 揭秘uc浏览器四

    请问大家用过uc浏览器,他收藏一个网页是怎么操作的? 是不是这样,按菜单键——弹出添加网页,收藏网页等等的菜单操作,这个菜单操作很人性化了,并且在前面的篇幅已经说过了,这里不做太多的赘述了. 我这里只 ...

  3. 揭秘uc浏览器三

    这节我们主要讨论收藏与历史记录页面的边边角角. 首先,看看他的最终的效果图了: 照例了,我们先看看他的布局文件: <!-- tab布局文件 --> <TabHost xmlns:an ...

  4. 小说接入UC浏览器内核技术对话(二)

    质辛@灿岩 质辛跟我们说一下那个删除文件的逻辑吧质辛@灿岩  应该不是删除cache下所有文件吧?质辛质辛@智鹰  提供一下我们的临时文件完整路径给 灿岩吧质辛@智鹰  是负责我们ucsdk的 技术对 ...

  5. 小说接入UC浏览器内核技术对话(一)

    质辛@灿岩 质辛跟我们说一下那个删除文件的逻辑吧质辛@灿岩  应该不是删除cache下所有文件吧?质辛@智鹰  提供一下我们的临时文件完整路径给 灿岩吧质辛@智鹰  是负责我们ucsdk的 技术对接灿 ...

  6. 手机端UC浏览器,在java开发的下载功能中存在的问题?

    在java web开发中,不同浏览器对下载文件的格式有不同的要求,有时会出现视频,音频等文件无法下载的问题.我在开发中,也遇到类似的问题,觉得很苦恼. 经过百度和请教学习,得到2个解决方案. 首先得到 ...

  7. 让你在PC上调试Web App,UC浏览器发布开发者版

    目前,在手机上使用浏览器访问网页,无法便捷地进行网页语言调试.手机屏幕相对较小且操作不便,直接在手机上进行网页数据调试不太现实. 因此,UC使用技术将手机网页调试信息分离,实现一种能在大屏幕.高配置P ...

  8. 解决UC浏览器或微信浏览器上flex兼容问题

    在UC浏览器上使用display:flex;时会不起作用,要加上兼容性写法,如下 display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ disp ...

  9. UC浏览器 分享到朋友圈和微信好友 分类: JavaScript 2015-04-28 14:45 615人阅读 评论(1) 收藏

    用手机UC浏览器访问新浪微博,会注意到有这样的两个分享按钮: 在手机端浏览器里,点击分享按钮,就可以启动微信客户端并分享到微信.研究了下其源代码,存在这样的一个js:http://mjs.sinaim ...

随机推荐

  1. noip2008普及组4题题解-rLq

    (啊啊啊终于补到了今天的作业了) 本题地址:http://www.luogu.org/problem/show?pid=1058 题目描述 小渊是个聪明的孩子,他经常会给周围的小朋友们将写自己认为有趣 ...

  2. PostgreSql安装

    官网:http://www.postgresql.org/download/linux/redhat/ 一.安装 由于我的机子是centos6.2,所以选择RedHat的. 按照官网所说的进行安装: ...

  3. Java 中的构造方法

    首先创建一个Transport类,定义好类的属性和方法,并且写好构造方法,先看下无参数的构造方法: public class Transport { //名字 public String name; ...

  4. Oracle左连接、右连接示例

    建表: create table a ( id ), name ) ); create table b ( name ), age ) ); create table c ( name ), dept ...

  5. HDU 2040 亲和数

    Problem Description 古希腊数学家毕达哥拉斯在自然数研究中发现,220的所有真约数(即不是自身的约数)之和为: 1+2+4+5+10+11+20+22+44+55+110=284. ...

  6. .NET Core2.0+MVC 用session,cookie实现的sso单点登录

    博主刚接触.NET Core2.0,想做一个单点登录的demo,所以参考了一些资料,这里给上链接: 1.http://www.cnblogs.com/baibaomen/p/sso-sequence- ...

  7. 安卓之必须了解的实时通信(Socket)

    Socket: 有服务器和客户端之分,其是对TCP/IP的封装,使用IP地址加端口,确定一个唯一的点.在Internet上的主机一般运行了多个服务软件,同时提供几种服务.每种服务都打开一个Socket ...

  8. 方法join()使用详解

    在线程的常见方法一节中,已经接触过join()方法的使用. 在很多情况下,主线程创建并启动子线程,如果子线程中要进行大量的耗时运算,主线程将早于子线程结束.这时,如果主线程想等子线程执行完成才结束,比 ...

  9. python学习Day3 变量、格式化输出、注释、基本数据类型、运算符

    今天复习内容(7项) 1.语言的分类 -- 机器语言:直接编写0,1指令,直接能被硬件执行 -- 汇编语言:编写助记符(与指令的对应关系),找到对应的指令直接交给硬件执行 -- 高级语言:编写人能识别 ...

  10. jQuery属性--attr(name|properties|key,value|fn)和removeAttr(name)

       attr(name|properties|key,value|fn) 概述     设置或返回被选元素的属性值 参数 key,function(index, attr)  1:属性名称:2:返回 ...