首先,看一下項目完成後的,最終效果是這樣的:javascript
一.主界面java
二,書籤界面android
3、主界面web
四.操做對話框界面數據庫
這幾個界面你是否看到了uc瀏覽器的影子了,其實我說你也能夠了,在接下來篇幅中,我將手把手叫你們完成這個瀏覽器。瀏覽器
首先,咱們從主界面開始吧,這是一個主線,項目的一些開始由他開始了。緩存
從圖一中,咱們能夠看出其佈局文件主要的佈局文件以線性佈局爲主,而同時了他嵌套了相對佈局,有圖有真相,下圖就是我對主頁佈局文件一種說明:多線程
從上圖的佈局文件,咱們能夠清晰的看出來了,中間viewflipper這個翻頁控件有大做用的,裏面的一些網頁內容將展示如此。app
android佈局文件當然重要,但只有了代碼控制,才能使一個app變得"有血有肉",咱們來看看這個主頁面的控制文件。ide
照例了,咱們先介紹了一些常量的聲明:這些在下面的代碼中將會大量的使用,源代碼以下:
//滑動像素的入口常量 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來更加快速的顯示網頁,不使其頁面實現卡頓。