Android網絡:開發瀏覽器(一)——基本的瀏覽網頁功能開發

        我們定義這個版本爲1.0版本。

    首先,因爲要製作一個瀏覽器,那麼就不能通過調用內置瀏覽器來實現網頁的瀏覽功能,但是可以使用WebView組件來進行。

    在此之前,我們可以來看看兩種網頁顯示方式:

    1.  Intent調用內置瀏覽器

Uri uri = Uri.parse("http://www.baidu.com");

Intent launchBrowser = new Intent(Intent.ACTION_VIEW, uri);

startActivity(launchBrowser);

代碼片段10.1.1  Intent調用顯示網頁

   

    2.  WebView顯示網頁

<WebView

       android:id="@+id/web_holder"

       android:layout_width="match_parent"

       android:layout_height="wrap_content"

       />

代碼片段10.1.2  WebView設置在layout佈局文件中

   

WebView webHolder = (WebView) this.findViewById(R.id.web_holder);

webHolder.loadUrl("http://www.baidu.com");

代碼片段10.1.3  WebView調用顯示

   

    以上就是兩種調用方式,現在我們通過WebView來簡單的實現網頁顯示的功能。

   

    我們先添加一個WebView給Activity,不過需要注意的是,如果想要調用本應用程序的WebView來顯示網頁,則需要重寫webViewClienet,而且在之前先要進行編碼的設置,大致如下:

package com.example.androidstudy_web;

 

import android.app.Activity;

import android.os.Bundle;

import android.view.Menu;

import android.webkit.WebSettings;

import android.webkit.WebView;

import android.webkit.WebViewClient;

 

public class MainActivity extends Activity {

 

   private WebView webHolder;

   private WebSettings settings;

   private WebViewClient client;

  

   @Override

   protected void onCreate(Bundle savedInstanceState) {

      super.onCreate(savedInstanceState);

      setContentView(R.layout.activity_main);

     

      this.webHolder = (WebView) this.findViewById(R.id.web_holder);

      this.settings = this.webHolder.getSettings();

      this.client = new OwnerWebView();

     

      this.settings.setDefaultTextEncodingName("UTF-8");

     

      this.webHolder.setWebViewClient(this.client);

     

      this.webHolder.loadUrl("http://www.baidu.com");

     

   }

 

   @Override

   public boolean onCreateOptionsMenu(Menu menu) {

      getMenuInflater().inflate(R.menu.main, menu);

      return true;

   }

  

   private class OwnerWebView extends WebViewClient{

 

      @Override

      public boolean shouldOverrideUrlLoading(WebView view, String url) {

         view.loadUrl(url);

         return true;

      }

     

   }

 

}

代碼片段10.1.4  簡單的瀏覽器

   

    基本的功能做完了,這個瀏覽器現在能做的就是顯示一個百度頁面,而我們不能更改。那麼接下來的工作就是給它添加一個地址輸入欄了。

   

    我們可以設置一個LinerLayout,作爲導航,裏面包括地址欄和一個按鈕,我們可以添加按鈕監聽事件,當點擊的時候進行地址載入,當然,這個地址得進行檢測:

private class ButtonClickedListener implements OnClickListener{

 

      @Override

      public void onClick(View v) {

         if(v.getId()==R.id.web_url_goto){

            String url = webUrlStr.getText().toString();

            if(URLUtil.isNetworkUrl(url)&&URLUtil.isValidUrl(url)){

                webHolder.loadUrl(url);

            }else{

                new AlertDialog.Builder(MainActivity.this)

                   .setTitle("警告")

                  .setMessage("不是有效的網址")

                   .create()

                   .show();

            }

         }

      }

     

   }

代碼片段10.1.5  按鈕事件監聽

 

<EditText

           android:id="@+id/web_url_input"

           android:layout_width="0dp"

           android:layout_height="match_parent"

           android:layout_weight="0.8"

           android:hint="@string/webUrlHint"

           android:inputType="textUri"

          />

        <Button

           android:id="@+id/web_url_goto"

           android:layout_width="0dp"

           android:layout_height="match_parent"

            android:layout_weight="0.2"

           android:text="@string/webUrlGoto"

           />

代碼片段10.1.6  導航欄

   

需要注意的是地址欄的inputType設置,因爲我們需要輸入的是一個網址,所以這裏的輸入類型需要更改爲textUri

 

現在基本功能已經做好,在這個基本功能的基礎上,我們可以進行一些完善。

比如:

1.  在輸入地址的情況下,具有自動提示的功能

 

2.  在輸入的構成中判斷地址的有效性,有效按鈕爲“進入”,無效爲“取消”

 

要實現這個其實還是比較簡單的,就是監聽輸入的改變情況,來驗證地址的有效性,以此判斷按鈕是否爲“進入”狀態。

實現這個需要實現TextWatcher接口:

/**

    * TextWatcher自定義繼承類

    * 覆蓋方法如下:

    * 1. afterTextChanged

    * 2. beforeTextChanged

    * 3. onTextChanged

    *     實現更改地址的時候進行地址合法性檢測

    * */

   private class WebUrlStrChangedListener implements TextWatcher{

 

      @Override

      public void afterTextChanged(Editable editable) {

      }

      @Override

      public void beforeTextChanged(CharSequence charsequence, int i, int j,

            int k) {

     

}

 

      @Override

      public void onTextChanged(CharSequence charsequence, int i, int j, int k) {

         url = charsequence.toString();

         if(!(url.startsWith("http://")||url.startsWith("https://"))){

            url = "http://"+url;

         }

         Log.d(DEG_TAG,"onchangeText:"+url);

         if(URLUtil.isNetworkUrl(url)&&URLUtil.isValidUrl(url)){

            //改變按鈕的函數實現

            changeStatueOfWebGoto(true);

         }else{

            changeStatueOfWebGoto(false);

         }

      }

     

   }

代碼片段10.1.7  TextWacher實現類

 

3.  找不到網站的時候就以百度爲默認搜索,進行搜索

 

這個功能,因爲需要判斷是否能找到網站,所以我通過異常的處理來進行這個操作,當出現無法找到網頁的時候,它就會返回一個errorCode,這個errorCode的所有值都爲負數,而無法找到網頁的錯誤代號爲-2,所以判斷返回的errorCode是否等於-2,如果相等,則將輸入的內容作爲搜索關鍵字處理。

    關鍵代碼:

if(errorCode==WebViewClient.ERROR_HOST_LOOKUP){

            //找不到頁面,調用百度搜搜

            url = "http://www.baidu.com/baidu?word=" + url;

            Log.d(DEG_TAG, "errorRedirect:"+url);

            webHolder.loadUrl(url);

         }

代碼片段10.1.8  找不到頁面,調用百度搜索

這個監控的是通過繼承WebViewClient,然後覆蓋裏面的onReceivedError方法進行實現。

 

4.  按物理返回鍵返回前一個頁面,按兩次退出

 

在Activity中,自己默認有一個onBackPressed方法,這個方法是用來實現按物理返回鍵的方法的,其實可以通過覆蓋keydown的方法來實現,不過這個更改好些。

 

@Override

   public void onBackPressed() {

      //判斷是否可後退,是則後退,否則按兩次退出程序

      if(webHolder.canGoBack()){

         webHolder.goBack();

         //更改其他按鈕狀態(不妨礙物理返回效果的實現)

         //changeStatueOfWebToolsButton();

      }else{

         if(!isExit){

            isExit = true;

            Toast.makeText(getApplicationContext(), "再按一次退出程序",

                       Toast.LENGTH_SHORT).show();

            handler.sendEmptyMessageDelayed(0,2000);

         }else{

            finish();

            System.exit(0);

         }

      }

}

代碼片段10.1.9  實現返回效果

 

5.  完成加載後自動隱藏地址欄

   

    在WebViewClient繼承類中的onPageFinished方法可以實現

@Override

public void onPageFinished(WebView view, String url) {

   super.onPageFinished(view, url);       

   //隱藏地址欄

webUrlLayout.setVisibility(View.GONE);

//更改其他按鈕狀態(不妨礙影藏地址欄實現)

   //changeStatueOfWebToolsButton();   

}

代碼片段10.1.10 實現隱藏工具欄

 

6.  頁面加載後向上滑動到頂部顯示地址欄,向下滑動到底部,隱藏地址欄

   

    因爲這個設計到了手勢的運用,爲了方便的管理手勢,Android其實已經提供了一個類,能夠自動識別獲取到的手勢,這個類就是GestureDetector:

/**

 * GestureDetector.OnGestureListener自定義繼承類

* 解決各種手勢的相對應策略

* 1. 向上滑動webView到頂觸發事件,顯示地址欄

* 2. 向下滑動webView觸發時間,隱藏地址欄

 * */

private class GestureListener implementsGestureDetector.OnGestureListener{

 

@Override

public boolean onDown(MotionEvent e) {

   return false;

}

 

@Override

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {

   if(webHolder.getScrollY()==0){

      //滑倒頂部

      webUrlLayout.setVisibility(View.VISIBLE);

   }

   if(webHolder.getScrollY()>0){

      //滑倒底部

      webUrlLayout.setVisibility(View.GONE);

   }

   return true;

}

 

@Override

public void onLongPress(MotionEvent e) {

}

 

@Override

public boolean onScroll(MotionEvent e1, MotionEvent e2,

            float distanceX, float distanceY) {

   return false;

}

 

@Override

public void onShowPress(MotionEvent e) {

}

 

@Override

public boolean onSingleTapUp(MotionEvent e) {

   return false;

}

}

代碼片段10.1.11 GestureDirector.OnGestureListener實現

已經實現了手勢識別的方法,那麼現在只需要獲取手勢,並且將獲取到的交給手勢識別類(即上述的GestureDirector)識別即可。

手勢是對於webView這個組件來說的,所以只需要這個組件添加了OnTouchListener方法即可,這個方法會獲取到手勢產生的事件:

 

/**

 * OnTouchListener自定義繼承類

 * 解決將手勢交給GestureDetector類解決

 * */

private class WebViewTouchListener implements OnTouchListener{

   @Override

   public boolean onTouch(View v, MotionEvent event) {

      if(v.getId()==R.id.web_holder){

         return mGestureDetector.onTouchEvent(event);

      }

      return false;

   }

}

代碼片段10.1.12 獲取手勢事件

註釋:mGestureDetector即爲代碼偏單10.1.11中的類的實例

 

7.  添加刷新功能

   

    這個較爲簡單,只需要將當前的url地址重新加載就行:

else if(v.getId()==R.id.tools_normal_refresh){

            //刷新

            if(!(url.equals("")&&url.equals("http://"))){

                webHolder.loadUrl(url);

            }

         }

代碼片段10.1.12-1   refresh功能

           

   

8.  添加進度條

   

    爲了美觀,我並沒有採用系統的進度條,而是自己創建了一個進度條,並且在webChromeClient的onProgressChanged方法中同步進度。

/**

    * WebChromeClient自定義繼承類

    * 覆蓋如下方法

    * 1. onProgressChanged

    *     用來解決進度條顯示問題

    * */

   private class OwnerChromeClient extends WebChromeClient{

 

      @Override

      public void onProgressChanged(WebView view, int newProgress) {

         super.onProgressChanged(view, newProgress);

         //MainActivity.this.setProgress(newProgress* 100);

         if(newProgress==100){

            webProgressBar.setVisibility(View.GONE);

         }else{

            webProgressBar.setVisibility(View.VISIBLE);

            webProgressBar.setProgress(newProgress);

         }

      }

     

   }

代碼片段10.1.13 進度條同步

   

9.  設置點擊鏈接,設置地址欄地址

   

    這個功能在頁面加載的時候,可以通過一個覆蓋函數,在webViewClient中進行操作

@Override

public void onPageFinished(WebView view, String url) {

   super.onPageFinished(view, url);

   //設置地址欄地址

   webUrlStr.setText(url);

   webUrlLayout.setVisibility(View.GONE);

//在每次頁面加載完成後查看是否有可以回溯的歷史

   changeStatueOfWebToolsButton();

}

代碼片段10.1.14 頁面加載完成後設置地址欄

   

10. 設置向前向後按鈕,無則灰色

   

    因爲按鈕的不同狀態圖片也不相同,這個時候就需要使用selector標籤,如下:

   

<?xml version="1.0"encoding="utf-8"?>

<selector xmlns:android="http://schemas.android.com/apk/res/android">

<item android:state_pressed="true"android:drawable="@drawable/next_button_keydown"></item>

<item android:state_enabled="false"android:drawable="@drawable/next_button_unavailable"></item>

<item android:drawable="@drawable/next_button_normal"></item>

</selector>

代碼片段10.1.15 按鈕的三態

               

註釋:state_pressed表示按鈕按下的狀態時候爲真,則顯示drawable中的資源,其他兩個也是相同;enabled可使用爲假時,進行引用等

/**

 * 設置工具欄回溯歷史是否可用

 * */

private void changeStatueOfWebToolsButton(){

   if(webHolder.canGoBack()){

      //設置可使用狀態

      preButton.setEnabled(true);

   }else{

      //設置禁止狀態

      preButton.setEnabled(false);

   }

   if(webHolder.canGoForward()){

      //設置可使用狀態

      nextButton.setEnabled(true);

   }else{

      //設置禁止狀態

      nextButton.setEnabled(false);

   }

}

代碼片段10.1.16 設置工具欄中的回溯歷史的按鈕

   

11. 工具欄功能實現,包括總工具窗口顯示實現,主頁返回實現

   

    這個通過popupwindow和tabActivity結合來實現:

    基本的:

private void initTab(){

       this.toolsTabViewthis.toolsTabInflater.inflate(R.layout.tabactivity_tools,null);

       this.toolsTab = (TabHost) this.toolsTabView.findViewById(android.R.id.tabhost);       //獲取tabhost

       this.toolsTab.setup();           //使用findViewById()加載tabhost時在調用addTab前必須調用

 

       this.toolsTab.addTab(this.toolsTab.newTabSpec("normal").setIndicator("常用").setContent(R.id.tools_normal));

 

   this.toolsTab.addTab(this.toolsTab.newTabSpec("setttings").setIndicator("設置").setContent(R.id.tools_settings));

       this.toolsTab.addTab(this.toolsTab.newTabSpec("tool").setIndicator("工具").setContent(R.id.tools_tool));

       this.toolsTab.setCurrentTab(0);                                            //設置默認選種標籤

    }

代碼片段10.1.17 實現tab

   

/**

     * 構造函數

     * @param context Context

     * @param width int

     * @param height int

     * */

    public ToolsPopWindow(Contextcontext, int width, int height){

       super(context);

       this.context = context;

       this.toolsTabInflater = LayoutInflater.from(this.context);

      

       //創建標籤

       this.initTab();

      

       //設置默認選項

       setWidth(width);

       setHeight(height);

       setContentView(toolsTab);

       setOutsideTouchable(true);

       setFocusable(true);

    }

代碼片段10.1.8  popupWindow實現

   

   

    基本的瀏覽器功能已經實現。


代碼:

AndroidStudy_web1.0

PS:轉載請註明出處謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章