揭秘uc浏览器一
首先,看一下项目完成后的,最终效果是这样的:
一.主界面
二,书签界面
三、主界面
四.操作对话框界面
这几个界面你是否看到了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浏览器一的更多相关文章
- 揭秘uc浏览器四
请问大家用过uc浏览器,他收藏一个网页是怎么操作的? 是不是这样,按菜单键——弹出添加网页,收藏网页等等的菜单操作,这个菜单操作很人性化了,并且在前面的篇幅已经说过了,这里不做太多的赘述了. 我这里只 ...
- 揭秘uc浏览器三
这节我们主要讨论收藏与历史记录页面的边边角角. 首先,看看他的最终的效果图了: 照例了,我们先看看他的布局文件: <!-- tab布局文件 --> <TabHost xmlns:an ...
- 揭秘uc浏览器二
这节,四个议题: ①一个网页显示在webview控件中 ②如何正常隐藏显示标题栏. ③如何用runnable来隐藏标题栏,这样子就更加的专业化. ④上节我们说道了QuickActionGrid,看他长 ...
- 让你在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 ...
- 用手机自带uc浏览器查看静态页面,css样式不显示
问题描述: 这个问题是一个同事在写手机页面用UC浏览器测试以后遇到的,其他浏览器静态页面显示正常,唯独UC浏览器不显示页面样式. 我测试过代码是没有问题的,因为临时没有找到安卓手机,就猜想PC端的应该 ...
- 苹果浏览器和uc浏览器在移动端的坑(日常积累,随时更新)
先mark 1 . 移动端uc浏览器不兼容css3 calc() 2 . ie8下a标签没有内容给宽高也不能触发点击跳转 3 . safari输入框加上readOnly="ture&qu ...
- 如何使用 UC浏览器开发者版 进行移动端调试
在 如何用 fiddler 代理调试本地手机页 一文中我们了解了如何用手机查看 PC 端写的网页(本地),但是我们只能看到页面效果,如果哪段 js 挂了,那部分样式失效了,我们该如何进行调试呢?今天为 ...
随机推荐
- Android activity之间数据传递和共享的方式之Application
1.基于消息的通信机制 Intent ---bundle ,extra 数据类型有限,比如遇到不可序列化的数据Bitmap,InputStream,或者LinkedList链表等等数据类型就不太好用 ...
- 【BZOJ-4016】最短路径树问题 Dijkstra + 点分治
4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec Memory Limit: 512 MBSubmit: 1092 Solved: 383[Submit][Sta ...
- html5 js实现浏览器全屏
全屏 var docElm = document.documentElement; //W3C if (docElm.requestFullscreen) { docElm.requestFullsc ...
- LPC-LINK 2 LPC4337 TQFP144 IO
- 78-WS2812-Library (STM32F4)
78-WS2812-Library (STM32F4) //-------------------------------------------------------------- // File ...
- svn : Can not Parse lock / entries hashfile错误解决办法
svn服务器死机重启之后,锁定文件的时候出下面的提示: Malformed file svn: Can't parse lock/entries hashfile '/data/svn/svnroot ...
- Unity3D实践系列05,为GameObject添加额外属性
在Unity中,通常通过脚本为GameObject添加额外的属性.具体有2种方式:一种是通过硬编码为脚本字段赋值,另一种是通过反射在运行时给脚本字段赋值. 脚本通过字段硬编码为GameObject添加 ...
- GDI+用PNG图片做半透明异型窗口
{*******************************************************} { ...
- CentOS RabbitMQ 高可用(Mirrored)
原文:https://www.sunjianhua.cn/archives/centos-rabbitmq.html 一.RabbitMQ 单节点 1.1.Windows 版安装配置 1.1.1 安装 ...
- Android开发中,比较有特色的特性(与iOS相比)
1.界面代码和界面控件元素时时联动.同步 2.当我们创建一个Activity时,系统自动帮我们维护strings.xml 文件和AndroidManifest.xml文件. 3.有来无回,删除.修改时 ...