首先,看一下项目完成后的,最终效果是这样的:

一.主界面

二,书签界面

三、主界面

四.操作对话框界面

这几个界面你是否看到了uc浏览器的影子了,其实我说你也可以了,在接下来篇幅中,我将手把手叫大家完成这个浏览器。

首先,我们从主界面开始吧,这是一个主线,项目的一些开始由他开始了。

从图一中,我们可以看出其布局文件主要的布局文件以线性布局为主,而同时了他嵌套了相对布局,有图有真相,下图就是我对主页布局文件一种说明:

从上图的布局文件,我们可以清晰的看出来了,中间viewflipper这个翻页控件有大作用的,里面的一些网页内容将展现如此。

android布局文件固然重要,但只有了代码控制,才能使一个app变得"有血有肉",我们来看看这个主页面的控制文件。

照例了,我们先介绍了一些常量的声明:这些在下面的代码中将会大量的使用,源代码如下:

//滑动像素的入口常量
private static final int FLIP_PIXEL_THRESHOLD = 200;
//滑动时间的入口常量
private static final int FLIP_TIME_THRESHOLD = 400;
// 添加标签的菜单常量
private static final int MENU_ADD_BOOKMARK = Menu.FIRST;
//展示标签的菜单常量
private static final int MENU_SHOW_BOOKMARKS = Menu.FIRST + 1;
//展示下载的菜单常量
private static final int MENU_SHOW_DOWNLOADS = Menu.FIRST + 2;
//喜爱的菜单常量
private static final int MENU_PREFERENCES = Menu.FIRST + 3;
//退出的菜单常量
private static final int MENU_EXIT = Menu.FIRST + 4;
//打开的上下文菜单常量
private static final int CONTEXT_MENU_OPEN = Menu.FIRST + 10;
//打开新的菜单常量
private static final int CONTEXT_MENU_OPEN_IN_NEW_TAB = Menu.FIRST + 11;
//下载的上下文菜单常量
private static final int CONTEXT_MENU_DOWNLOAD = Menu.FIRST + 12;
//拷贝的菜单常量
private static final int CONTEXT_MENU_COPY = Menu.FIRST + 13;
//发送具体的上下文菜单常量
private static final int CONTEXT_MENU_SEND_MAIL = Menu.FIRST + 14;
//分享上下文菜单常量
private static final int CONTEXT_MENU_SHARE = Menu.FIRST + 15;
//打开标签历史记录的页面常量
private static final int OPEN_BOOKMARKS_HISTORY_ACTIVITY = 0;
//打开下载的页面常量
private static final int OPEN_DOWNLOADS_ACTIVITY = 1;
//打开文件选择的界面的常量
private static final int OPEN_FILE_CHOOSER_ACTIVITY = 2; //全频的常量
protected static final FrameLayout.LayoutParams COVER_SCREEN_PARAMS =
new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);

观察上面各个变量,我们可以得出来这样的结论:

①程序将会利用一些菜单,上下文菜单进行添加书签,书签,退出的操作。

②主界面全屏形式将会大量利用。

接下来,是一些控件变量的声明,源代码如下:

//    填充器
protected LayoutInflater mInflater = null;
//顶部的线性布局文件
private LinearLayout mTopBar;
//底部 线性布局文件
private LinearLayout mBottomBar; private LinearLayout mFindBar;
//前一步按钮
private ImageButton mFindPreviousButton;
//下一步按钮
private ImageButton mFindNextButton;
//关闭的按钮
private ImageButton mFindCloseButton;
//文本框
private EditText mFindText;
//前一步视图
private ImageView mPreviousTabView;
//下一步的视图
private ImageView mNextTabView;
//工具按钮
private ImageButton mToolsButton;
//自动匹配文本框
private AutoCompleteTextView mUrlEditText;
//前往的按钮
private ImageButton mGoButton;
//进度条
private ProgressBar mProgressBar;
//右边imageviw
private ImageView mBubbleRightView;
//左边的imageview
private ImageView mBubbleLeftView;
//当前的web视图
private CustomWebView mCurrentWebView;
//所有的打开的web的视图
private List<CustomWebView> mWebViews;
//前面按钮
private ImageButton mPreviousButton;
//下一步的按钮
private ImageButton mNextButton;
//开启一个tab按钮
private ImageButton mNewTabButton;
//移去tab的按钮
private ImageButton mRemoveTabButton;
//快速进入的按钮
private ImageButton mQuickButton;
//当前的背景
private Drawable mCircularProgress;
//url 是否显示
private boolean mUrlBarVisible;
//工具grid 是否显示
private boolean mToolsActionGridVisible = false;
//对话框是否显示
private boolean mFindDialogVisible = false;
//url的监听者
private TextWatcher mUrlTextWatcher;
//开启的多线程
private HideToolbarsRunnable mHideToolbarsRunnable;
//翻页的控件
private ViewFlipper mViewFlipper;
//手势的监听者
private GestureDetector mGestureDetector; //换tab的枚举
private SwitchTabsMethod mSwitchTabsMethod = SwitchTabsMethod.BOTH;
//action的grid
private QuickActionGrid mToolsActionGrid;
//消息URL
private ValueCallback<Uri> mUploadMessage;
//改变的监听者
private OnSharedPreferenceChangeListener mPreferenceChangeListener; private View mCustomView;
//当前的
private Bitmap mDefaultVideoPoster = null; private View mVideoProgressView = null;
//桢不具
private FrameLayout mFullscreenContainer;
//相应回调
private WebChromeClient.CustomViewCallback mCustomViewCallback;
//改变tab的枚举
private enum SwitchTabsMethod {
BUTTONS,
FLING,
BOTH
}

通过上述一些变量的声明,我们应该明白这么几点了

①主要控件声明是一些上局布局文件中的控件的声明。

②取此之外,一些判断其是否显示隐藏的变量,一些保存当前webview的变量,一些保存当前webview视图也在此申明了,相应回调的接口。

③此外,还有一个tab页改变方式的申明。

接下来,重头戏——方法实现就来了。首先是一个oncreate方法,是进行数据的初始化。

    /**
* 数据的初始化
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); INSTANCE = this; Constants.initializeConstantsFromResources(this); Controller.getInstance().setPreferences(PreferenceManager.getDefaultSharedPreferences(this)); if (Controller.getInstance().getPreferences().getBoolean(Constants.PREFERENCES_SHOW_FULL_SCREEN, false)) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
} if (Controller.getInstance().getPreferences().getBoolean(Constants.PREFERENCES_GENERAL_HIDE_TITLE_BARS, true)) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
} setProgressBarVisibility(true); setContentView(R.layout.main); mCircularProgress = getResources().getDrawable(R.drawable.spinner); EventController.getInstance().addDownloadListener(this); mHideToolbarsRunnable = null; mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); buildComponents(); mViewFlipper.removeAllViews(); updateSwitchTabsMethod();
updateBookmarksDatabaseSource(); registerPreferenceChangeListener(); Intent i = getIntent();
if (i.getData() != null) {
// App first launch from another app.
addTab(false);
navigateToUrl(i.getDataString());
} else {
// Normal start.
int currentVersionCode = ApplicationUtils.getApplicationVersionCode(this);
int savedVersionCode = PreferenceManager.getDefaultSharedPreferences(this).getInt(Constants.PREFERENCES_LAST_VERSION_CODE, -1); // If currentVersionCode and savedVersionCode are different, the application has been updated.
if (currentVersionCode != savedVersionCode) {
// Save current version code.
Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
editor.putInt(Constants.PREFERENCES_LAST_VERSION_CODE, currentVersionCode);
editor.commit(); // Display changelog dialog.
Intent changelogIntent = new Intent(this, ChangelogActivity.class);
startActivity(changelogIntent);
} boolean lastPageRestored = false;
if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREFERENCES_BROWSER_RESTORE_LAST_PAGE, false)) {
if (savedInstanceState != null) {
String savedUrl = savedInstanceState.getString(Constants.EXTRA_SAVED_URL);
if (savedUrl != null) {
addTab(false);
navigateToUrl(savedUrl);
lastPageRestored = true;
}
}
} if (!lastPageRestored) {
addTab(true);
}
} initializeWebIconDatabase(); startToolbarsHideRunnable(); }

从上述的源代码,我们可以清楚看出啦:

①,相应的初始化的内容,是从sharedprefrence这个xml文件中读取相应是否全屏啊,是否有标题这些所谓变量,来决定他显示显示相应的内容。

②,在这里进行相应数据化的初始化。

③,找到相应的控件。

④,未控件赋予相应事件的监听。

⑤,导航到相应的界面

接下来的源代码了,主要是解决退出销毁数据,保存数据的方法,开启新意图的方法。

    /**
* 销毁界面
*/
@Override
protected void onDestroy() {
WebIconDatabase.getInstance().close(); if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREFERENCES_PRIVACY_CLEAR_CACHE_ON_EXIT, false)) {
mCurrentWebView.clearCache(true);
} EventController.getInstance().removeDownloadListener(this); PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(mPreferenceChangeListener); super.onDestroy();
} /**
* 保存相应的数据
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString(Constants.EXTRA_SAVED_URL, mCurrentWebView.getUrl());
super.onSaveInstanceState(outState);
} /**
* Handle url request from external apps.
* @param intent The intent.
*/
@Override
protected void onNewIntent(Intent intent) {
if (intent.getData() != null) {
addTab(false);
navigateToUrl(intent.getDataString());
} setIntent(intent); super.onNewIntent(intent);
}

我们得出来这样的结论了,功能有三

①保存数据,将相应的URL数据保存起来。

②退出时候,判断这个是否需要清空相应的缓存,将相应的sharedpreference的监听者移除。

③开启新的一个意图的时候,导航到相应URL的页面,开始新的意图。

在上面oncreate的方法中,我们说到了他有初始化控件的方法,那长成了什么样子了,我们来瞧一瞧:

    /**
* Create main UI.
*/
private void buildComponents() { mToolsActionGrid = new QuickActionGrid(this);
mToolsActionGrid.addQuickAction(new QuickAction(this, R.drawable.ic_btn_home, R.string.QuickAction_Home));
mToolsActionGrid.addQuickAction(new QuickAction(this, R.drawable.ic_btn_share, R.string.QuickAction_Share));
mToolsActionGrid.addQuickAction(new QuickAction(this, R.drawable.ic_btn_find, R.string.QuickAction_Find));
mToolsActionGrid.addQuickAction(new QuickAction(this, R.drawable.ic_btn_select, R.string.QuickAction_SelectText));
mToolsActionGrid.addQuickAction(new QuickAction(this, R.drawable.ic_btn_mobile_view, R.string.QuickAction_MobileView)); mToolsActionGrid.setOnQuickActionClickListener(new OnQuickActionClickListener() {
@Override
public void onQuickActionClicked(QuickActionWidget widget, int position) {
switch (position) {
case 0:
navigateToHome();
break;
case 1:
ApplicationUtils.sharePage(MainActivity.this, mCurrentWebView.getTitle(), mCurrentWebView.getUrl());
break;
case 2:
// Somewhat dirty hack: when the find dialog was shown from a QuickAction,
// the soft keyboard did not show... Hack is to wait a little before showing
// the file dialog through a thread.
startShowFindDialogRunnable();
break;
case 3:
swithToSelectAndCopyTextMode();
break;
case 4:
String currentUrl = mUrlEditText.getText().toString(); // Do not reload mobile view if already on it.
if (!currentUrl.startsWith(Constants.URL_GOOGLE_MOBILE_VIEW_NO_FORMAT)) {
String url = String.format(Constants.URL_GOOGLE_MOBILE_VIEW, mUrlEditText.getText().toString());
navigateToUrl(url);
}
break;
}
}
}); mToolsActionGrid.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
mToolsActionGridVisible = false;
startToolbarsHideRunnable();
}
}); mGestureDetector = new GestureDetector(this, new GestureListener()); mUrlBarVisible = true; mWebViews = new ArrayList<CustomWebView>();
Controller.getInstance().setWebViewList(mWebViews); mBubbleRightView = (ImageView) findViewById(R.id.BubbleRightView);
mBubbleRightView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setToolbarsVisibility(true);
}
});
mBubbleRightView.setVisibility(View.GONE); mBubbleLeftView = (ImageView) findViewById(R.id.BubbleLeftView);
mBubbleLeftView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setToolbarsVisibility(true);
}
});
mBubbleLeftView.setVisibility(View.GONE); mViewFlipper = (ViewFlipper) findViewById(R.id.ViewFlipper); mTopBar = (LinearLayout) findViewById(R.id.BarLayout);
mTopBar.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Dummy event to steel it from the WebView, in case of clicking between the buttons.
}
}); mBottomBar = (LinearLayout) findViewById(R.id.BottomBarLayout);
mBottomBar.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Dummy event to steel it from the WebView, in case of clicking between the buttons.
}
}); mFindBar = (LinearLayout) findViewById(R.id.findControls);
mFindBar.setVisibility(View.GONE); mPreviousTabView = (ImageView) findViewById(R.id.PreviousTabView);
mPreviousTabView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showPreviousTab(true);
}
});
mPreviousTabView.setVisibility(View.GONE); mNextTabView = (ImageView) findViewById(R.id.NextTabView);
mNextTabView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showNextTab(true);
}
});
mNextTabView.setVisibility(View.GONE); String[] from = new String[] {UrlSuggestionCursorAdapter.URL_SUGGESTION_TITLE, UrlSuggestionCursorAdapter.URL_SUGGESTION_URL};
int[] to = new int[] {R.id.AutocompleteTitle, R.id.AutocompleteUrl}; UrlSuggestionCursorAdapter adapter = new UrlSuggestionCursorAdapter(this, R.layout.url_autocomplete_line, null, from, to); adapter.setCursorToStringConverter(new CursorToStringConverter() {
@Override
public CharSequence convertToString(Cursor cursor) {
String aColumnString = cursor.getString(cursor.getColumnIndex(UrlSuggestionCursorAdapter.URL_SUGGESTION_URL));
return aColumnString;
}
}); adapter.setFilterQueryProvider(new FilterQueryProvider() {
@Override
public Cursor runQuery(CharSequence constraint) {
if ((constraint != null) &&
(constraint.length() > 0)) {
return BookmarksProviderWrapper.getUrlSuggestions(getContentResolver(),
constraint.toString(),
PreferenceManager.getDefaultSharedPreferences(MainActivity.this).getBoolean(Constants.PREFERENCE_USE_WEAVE, false));
} else {
return BookmarksProviderWrapper.getUrlSuggestions(getContentResolver(),
null,
PreferenceManager.getDefaultSharedPreferences(MainActivity.this).getBoolean(Constants.PREFERENCE_USE_WEAVE, false));
}
}
}); mUrlEditText = (AutoCompleteTextView) findViewById(R.id.UrlText);
mUrlEditText.setThreshold(1);
mUrlEditText.setAdapter(adapter); mUrlEditText.setOnKeyListener(new View.OnKeyListener() { @Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_ENTER) {
navigateToUrl();
return true;
} return false;
} }); mUrlTextWatcher = new TextWatcher() {
@Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { } @Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { } @Override
public void afterTextChanged(Editable arg0) {
updateGoButton();
}
}; mUrlEditText.addTextChangedListener(mUrlTextWatcher); mUrlEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override
public void onFocusChange(View v, boolean hasFocus) {
// Select all when focus gained.
if (hasFocus) {
mUrlEditText.setSelection(0, mUrlEditText.getText().length());
}
}
}); mUrlEditText.setCompoundDrawablePadding(5); mGoButton = (ImageButton) findViewById(R.id.GoBtn);
mGoButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { if (mCurrentWebView.isLoading()) {
mCurrentWebView.stopLoading();
} else if (!mCurrentWebView.isSameUrl(mUrlEditText.getText().toString())) {
navigateToUrl();
} else {
mCurrentWebView.reload();
}
}
}); mToolsButton = (ImageButton) findViewById(R.id.ToolsBtn);
mToolsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mToolsActionGridVisible = true;
mToolsActionGrid.show(v);
}
}); mProgressBar = (ProgressBar) findViewById(R.id.WebViewProgress);
mProgressBar.setMax(100); mPreviousButton = (ImageButton) findViewById(R.id.PreviousBtn);
mNextButton = (ImageButton) findViewById(R.id.NextBtn); mPreviousButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
navigatePrevious();
}
}); mNextButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
navigateNext();
}
}); mNewTabButton = (ImageButton) findViewById(R.id.NewTabBtn);
mNewTabButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
addTab(true);
}
}); mRemoveTabButton = (ImageButton) findViewById(R.id.RemoveTabBtn);
mRemoveTabButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if (mViewFlipper.getChildCount() == 1 && !mCurrentWebView.getUrl().equals(Constants.URL_ABOUT_START)) {
navigateToHome();
updateUI();
updatePreviousNextTabViewsVisibility();
}
else
removeCurrentTab();
}
}); mQuickButton = (ImageButton) findViewById(R.id.QuickBtn);
mQuickButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
onQuickButton();
}
}); mFindPreviousButton = (ImageButton) findViewById(R.id.find_previous);
mFindPreviousButton.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
mCurrentWebView.findNext(false);
hideKeyboardFromFindDialog();
}
}); mFindNextButton = (ImageButton) findViewById(R.id.find_next);
mFindNextButton.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
mCurrentWebView.findNext(true);
hideKeyboardFromFindDialog();
}
}); mFindCloseButton = (ImageButton) findViewById(R.id.find_close);
mFindCloseButton.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
closeFindDialog();
}
}); mFindText = (EditText) findViewById(R.id.find_value);
mFindText.addTextChangedListener(new TextWatcher() { @Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
doFind();
} @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override
public void afterTextChanged(Editable s) { }
}); }

由这一大堆源代码,我们可以总结出这样的功能特点:

①我们为了满足自己的代码的需求初始化了QuickActionGrid这个控件,这个控件添加了主页,标签,添加标签功能到这个控件中。

②为了QuickActionGrid这个控件,赋予相应的事件,不同的事件做不同的动作。

③监听了相应动作手势的变化。

④找到相应的按钮控件,赋予相应的按钮控件的点击事件。

⑤实例化相应progressbar,使他的最大值是100.

⑥找到相应的匹配的文本框,从而为其监听文本变化的事件,从而完全实现匹配的效果。

⑦声明一个adapter,把相应数据填充出来。

这个重头戏介绍完成以后,我们在看看sharedpreference中处理方法,这些处理方法,主要是处理一些配置类的信息。

/**
* 注册一个preference的监听者
*/
private void registerPreferenceChangeListener() {
mPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(Constants.PREFERENCE_BOOKMARKS_DATABASE)) {
updateBookmarksDatabaseSource();
}
}
}; PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(mPreferenceChangeListener);
} /**
* Apply preferences to the current UI objects.
*/
public void applyPreferences() {
// To update to Bubble position.
setToolbarsVisibility(false); updateSwitchTabsMethod(); for (CustomWebView view : mWebViews) {
view.initializeOptions();
}
}

这段代码给予我们起始有这么几点:

①读取相应的数据库配置信息,更新标签的数据源。为相应的数据类注册一个监听者。

②为相应ui 对象赋值一些数据信息。

浏览器中webview是一个浏览器重中之重,我们在下面篇幅中,主要来自己初始化一个webview,源代码如下:

    /**
* Initialize a newly created WebView.
*/
private void initializeCurrentWebView() { mCurrentWebView.setWebViewClient(new CustomWebViewClient(this));
mCurrentWebView.setOnTouchListener(this); mCurrentWebView.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() { @Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
HitTestResult result = ((WebView) v).getHitTestResult(); int resultType = result.getType();
if ((resultType == HitTestResult.ANCHOR_TYPE) ||
(resultType == HitTestResult.IMAGE_ANCHOR_TYPE) ||
(resultType == HitTestResult.SRC_ANCHOR_TYPE) ||
(resultType == HitTestResult.SRC_IMAGE_ANCHOR_TYPE)) { Intent i = new Intent();
i.putExtra(Constants.EXTRA_ID_URL, result.getExtra()); MenuItem item = menu.add(0, CONTEXT_MENU_OPEN, 0, R.string.Main_MenuOpen);
item.setIntent(i); item = menu.add(0, CONTEXT_MENU_OPEN_IN_NEW_TAB, 0, R.string.Main_MenuOpenNewTab);
item.setIntent(i); item = menu.add(0, CONTEXT_MENU_COPY, 0, R.string.Main_MenuCopyLinkUrl);
item.setIntent(i); item = menu.add(0, CONTEXT_MENU_DOWNLOAD, 0, R.string.Main_MenuDownload);
item.setIntent(i); item = menu.add(0, CONTEXT_MENU_SHARE, 0, R.string.Main_MenuShareLinkUrl);
item.setIntent(i); menu.setHeaderTitle(result.getExtra());
} else if (resultType == HitTestResult.IMAGE_TYPE) {
Intent i = new Intent();
i.putExtra(Constants.EXTRA_ID_URL, result.getExtra()); MenuItem item = menu.add(0, CONTEXT_MENU_OPEN, 0, R.string.Main_MenuViewImage);
item.setIntent(i); item = menu.add(0, CONTEXT_MENU_COPY, 0, R.string.Main_MenuCopyImageUrl);
item.setIntent(i); item = menu.add(0, CONTEXT_MENU_DOWNLOAD, 0, R.string.Main_MenuDownloadImage);
item.setIntent(i); item = menu.add(0, CONTEXT_MENU_SHARE, 0, R.string.Main_MenuShareImageUrl);
item.setIntent(i); menu.setHeaderTitle(result.getExtra()); } else if (resultType == HitTestResult.EMAIL_TYPE) { Intent sendMail = new Intent(Intent.ACTION_VIEW, Uri.parse(WebView.SCHEME_MAILTO + result.getExtra())); MenuItem item = menu.add(0, CONTEXT_MENU_SEND_MAIL, 0, R.string.Main_MenuSendEmail);
item.setIntent(sendMail); Intent i = new Intent();
i.putExtra(Constants.EXTRA_ID_URL, result.getExtra()); item = menu.add(0, CONTEXT_MENU_COPY, 0, R.string.Main_MenuCopyEmailUrl);
item.setIntent(i); item = menu.add(0, CONTEXT_MENU_SHARE, 0, R.string.Main_MenuShareEmailUrl);
item.setIntent(i); menu.setHeaderTitle(result.getExtra());
}
} }); mCurrentWebView.setDownloadListener(new DownloadListener() { @Override
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimetype,
long contentLength) {
doDownloadStart(url, userAgent, contentDisposition, mimetype, contentLength);
} }); final Activity activity = this;
mCurrentWebView.setWebChromeClient(new WebChromeClient() { @SuppressWarnings("unused")
// This is an undocumented method, it _is_ used, whatever Eclipse may think :)
// Used to show a file chooser dialog.
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
MainActivity.this.startActivityForResult(
Intent.createChooser(i, MainActivity.this.getString(R.string.Main_FileChooserPrompt)),
OPEN_FILE_CHOOSER_ACTIVITY);
} @Override
public Bitmap getDefaultVideoPoster() {
if (mDefaultVideoPoster == null) {
mDefaultVideoPoster = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.drawable.default_video_poster);
} return mDefaultVideoPoster;
} @Override
public View getVideoLoadingProgressView() {
if (mVideoProgressView == null) {
LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
mVideoProgressView = inflater.inflate(R.layout.video_loading_progress, null);
} return mVideoProgressView;
} public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
showCustomView(view, callback);
} @Override
public void onHideCustomView() {
hideCustomView();
} // @Override
// public void onShowCustomView(View view, CustomViewCallback callback) {
// super.onShowCustomView(view, callback);
//
// if (view instanceof FrameLayout) {
// mCustomViewContainer = (FrameLayout) view;
// mCustomViewCallback = callback;
//
// mContentView = (LinearLayout) findViewById(R.id.MainContainer);
//
// if (mCustomViewContainer.getFocusedChild() instanceof VideoView) {
// mCustomVideoView = (VideoView) mCustomViewContainer.getFocusedChild();
// // frame.removeView(video);
// mContentView.setVisibility(View.GONE);
// mCustomViewContainer.setVisibility(View.VISIBLE);
//
// setContentView(mCustomViewContainer);
// //mCustomViewContainer.bringToFront();
//
// mCustomVideoView.setOnCompletionListener(new OnCompletionListener() {
// @Override
// public void onCompletion(MediaPlayer mp) {
// mp.stop();
// onHideCustomView();
// }
// });
//
// mCustomVideoView.setOnErrorListener(new OnErrorListener() {
// @Override
// public boolean onError(MediaPlayer mp, int what, int extra) {
// onHideCustomView();
// return true;
// }
// });
//
// mCustomVideoView.start();
// }
//
// }
// }
//
// @Override
// public void onHideCustomView() {
// super.onHideCustomView();
//
// if (mCustomVideoView == null) {
// return;
// }
//
// mCustomVideoView.setVisibility(View.GONE);
// mCustomViewContainer.removeView(mCustomVideoView);
// mCustomVideoView = null;
//
// mCustomViewContainer.setVisibility(View.GONE);
// mCustomViewCallback.onCustomViewHidden();
//
// mContentView.setVisibility(View.VISIBLE);
// setContentView(mContentView);
// } @Override
public void onProgressChanged(WebView view, int newProgress) {
((CustomWebView) view).setProgress(newProgress);
mProgressBar.setProgress(mCurrentWebView.getProgress());
} @Override
public void onReceivedIcon(WebView view, Bitmap icon) {
new Thread(new FaviconUpdaterRunnable(MainActivity.this, view.getUrl(), view.getOriginalUrl(), icon)).start();
updateFavIcon(); super.onReceivedIcon(view, icon);
} @Override
public boolean onCreateWindow(WebView view, final boolean dialog, final boolean userGesture, final Message resultMsg) { WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj; addTab(false, mViewFlipper.getDisplayedChild()); transport.setWebView(mCurrentWebView);
resultMsg.sendToTarget(); return true;
} @Override
public void onReceivedTitle(WebView view, String title) {
setTitle(String.format(getResources().getString(R.string.ApplicationNameUrl), title)); startHistoryUpdaterRunnable(title, mCurrentWebView.getUrl(), mCurrentWebView.getOriginalUrl()); super.onReceivedTitle(view, title);
} @Override
public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
new AlertDialog.Builder(activity)
.setTitle(R.string.Commons_JavaScriptDialog)
.setMessage(message)
.setPositiveButton(android.R.string.ok,
new AlertDialog.OnClickListener()
{
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
})
.setCancelable(false)
.create()
.show(); return true;
} @Override
public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
new AlertDialog.Builder(MainActivity.this)
.setTitle(R.string.Commons_JavaScriptDialog)
.setMessage(message)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
})
.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which) {
result.cancel();
}
})
.create()
.show(); return true;
} @Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final JsPromptResult result) { final LayoutInflater factory = LayoutInflater.from(MainActivity.this);
final View v = factory.inflate(R.layout.javascript_prompt_dialog, null);
((TextView) v.findViewById(R.id.JavaScriptPromptMessage)).setText(message);
((EditText) v.findViewById(R.id.JavaScriptPromptInput)).setText(defaultValue); new AlertDialog.Builder(MainActivity.this)
.setTitle(R.string.Commons_JavaScriptDialog)
.setView(v)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String value = ((EditText) v.findViewById(R.id.JavaScriptPromptInput)).getText()
.toString();
result.confirm(value);
}
})
.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
result.cancel();
}
})
.setOnCancelListener(
new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
result.cancel();
}
})
.show(); return true; } });
}

对于这个方法,我们需要对其进行讨论,

①他需要对其相应按键做出正常的处理,判断他是按键不同,进行不同操作。

②对其相应的下载的接口进行了监听,进行webclient下载的处理。

③对其文件上传,作起处理,跳转到文件上传的页面。

④对其view进行了处理,使其相应progress的view文件进行填充。

⑤创建一个窗体,使其显示是该指定的webview。

⑥对弹出来js源代码进行处理,使其页面上的js代码在webview能够正常的显示。

在该浏览器中添加相应的tab页,是一个重要的功能,因此我们分析分析,源代码如下:

    /**
* Add a new tab.
* @param navigateToHome If True, will load the user home page.
* @param parentIndex The index of the new tab.
*/
private void addTab(boolean navigateToHome, int parentIndex) {
if (mFindDialogVisible) {
closeFindDialog();
} RelativeLayout view = (RelativeLayout) mInflater.inflate(R.layout.webview, mViewFlipper, false); mCurrentWebView = (CustomWebView) view.findViewById(R.id.webview); initializeCurrentWebView(); synchronized (mViewFlipper) {
if (parentIndex != -1) {
mWebViews.add(parentIndex + 1, mCurrentWebView);
mViewFlipper.addView(view, parentIndex + 1);
} else {
mWebViews.add(mCurrentWebView);
mViewFlipper.addView(view);
}
mViewFlipper.setDisplayedChild(mViewFlipper.indexOfChild(view));
} updateUI();
updatePreviousNextTabViewsVisibility(); mUrlEditText.clearFocus(); if (navigateToHome) {
navigateToHome();
}
} /**
* Remove the current tab.
*/
private void removeCurrentTab() { if (mFindDialogVisible) {
closeFindDialog();
} int removeIndex = mViewFlipper.getDisplayedChild(); mCurrentWebView.doOnPause(); synchronized (mViewFlipper) {
mViewFlipper.removeViewAt(removeIndex);
mViewFlipper.setDisplayedChild(removeIndex - 1);
mWebViews.remove(removeIndex);
} mCurrentWebView = mWebViews.get(mViewFlipper.getDisplayedChild()); updateUI();
updatePreviousNextTabViewsVisibility(); mUrlEditText.clearFocus();
}

我们首先

①找到相应的viewflipper控件,在viewflipper中,显示到该初始化webview。并且对其计数器加一,当前文本框失去焦点。

②移去view的时候,在webview移去,计数器减一,界面更新,文本框失去焦点。

有了这些主要的方法做支持,一个webview就这样显示出来,下节主要讲①一个网页显示在webview控件中,②如何正常隐藏显示标题栏。③如何用runnable来更加快速的显示网页,不使其页面实现卡顿。

揭秘uc浏览器一的更多相关文章

  1. 揭秘uc浏览器四

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

  2. 揭秘uc浏览器三

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

  3. 揭秘uc浏览器二

    这节,四个议题: ①一个网页显示在webview控件中 ②如何正常隐藏显示标题栏. ③如何用runnable来隐藏标题栏,这样子就更加的专业化. ④上节我们说道了QuickActionGrid,看他长 ...

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

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

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

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

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

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

  7. 用手机自带uc浏览器查看静态页面,css样式不显示

    问题描述: 这个问题是一个同事在写手机页面用UC浏览器测试以后遇到的,其他浏览器静态页面显示正常,唯独UC浏览器不显示页面样式. 我测试过代码是没有问题的,因为临时没有找到安卓手机,就猜想PC端的应该 ...

  8. 苹果浏览器和uc浏览器在移动端的坑(日常积累,随时更新)

    先mark 1 .  移动端uc浏览器不兼容css3 calc() 2 .  ie8下a标签没有内容给宽高也不能触发点击跳转 3 . safari输入框加上readOnly="ture&qu ...

  9. 如何使用 UC浏览器开发者版 进行移动端调试

    在 如何用 fiddler 代理调试本地手机页 一文中我们了解了如何用手机查看 PC 端写的网页(本地),但是我们只能看到页面效果,如果哪段 js 挂了,那部分样式失效了,我们该如何进行调试呢?今天为 ...

随机推荐

  1. BugkuCTF ---游戏过关 writeup

    下载程序后发现是输入1-8数字中的一位 至于怎么玩,我到现在都没弄懂 不多说,直接拖入Ollydbg 搜索 分析了一下字符串,发现有一个显示flag的字符串 双击过去看看,发现类似于一个函数. 接下来 ...

  2. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) E. Goods transportation 动态规划

    E. Goods transportation 题目连接: http://codeforces.com/contest/724/problem/E Description There are n ci ...

  3. CentOS安装CLI

    #使用root账号 vim /etc/yum.repos.d/epel.repo [epel] name=epel baseurl=http://mirrors.sohu.com/fedora-epe ...

  4. 收集的一些MikroTik RouterOS 5.x破解版

    链接:https://pan.baidu.com/s/1RyREMfrpLkpQ-AIcDQES_Q  密码:byhd

  5. div光标

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...

  6. Timer-triggered memory-to-memory DMA transfer demonstrator

    http://www.efton.sk/STM32/bt.c // Timer-triggered memory-to-memory DMA transfer demonstrator for STM ...

  7. C#复制数组的两种方式,以及效率比较

    如何高效地进行数组复制? 如果把一个变量值复制给另外一个数组变量,那么2个变量指向托管堆上同一个引用. 如果想在托管堆上创建另外的一份数组实例,通常使用Array.Copy方法. class Prog ...

  8. Visual Studio 2013 sqlce 配置(转)

    Visual Studio 2013 把內建 SQL CE 的管理工具拿掉了 下载SQL Server Compact Toolbox by ErikEJ并安装 打开VS2013,新建一工程,在“视图 ...

  9. require.js 简洁入门

    原文地址:http://blog.sae.sina.com.cn/archives/4382 前言 提到require.js大多数人会说提到模块化开发,AMD等等,其实require.js并没有这么多 ...

  10. NSURLRequest with UserAgent

    关于iOS上的http请求还在不断学习,从早先的时候发现原来iOS的http请求可以自动保存cookie到后来的,发现ASIHttpRequest会有User-Agent,到现在发现竟然NSURLRe ...