我们定义这个版本为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.toolsTabView =  this.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:转载请注明出处谢谢!

Android网络:开发浏览器(一)——基本的浏览网页功能开发的更多相关文章

  1. [小程序开发] 微信小程序内嵌网页web-view开发教程

    为了便于开发者灵活配置小程序,微信小程序开放了内嵌网页能力.这意味着小程序的内容不再局限于pages和large,我们可以借助内嵌网页丰富小程序的内容.下面附上详细的开发教程(含视频操作以及注意事项) ...

  2. Android进阶笔记01:Android 网络请求库的比较及实战(一)

    在实际开发中,有的时候需要频繁的网络请求,而网络请求的方式很多,最常见的也就那么几个.本篇文章对常见的网络请求库进行一个总结. 一.使用HttpUrlConnection: 1. HttpUrlCon ...

  3. Android学习笔记(十八)——使用意图筛选器和实现浏览网页(附源代码)

    使用意图筛选器 点击下载源代码 1.创建一个Intents项目,给该项目加入一个新类,命名为MyBrowserActivity.在res/layout目录下新增一个browser.xml: 2.在An ...

  4. go语言实战教程之 后台管理页面统计功能开发(1)

    本节内容我们将学习开发实现后台管理平台页面统计功能开发的功能接口,本章节内容将涉及到多种请求路由的方式. 功能介绍 后台管理平台不仅是功能管理平台,同时还是数据管理平台.从数据管理平台角度来说,在管理 ...

  5. FastAPI(七十)实战开发《在线课程学习系统》接口开发--留言功能开发

    在之前的文章:FastAPI(六十九)实战开发<在线课程学习系统>接口开发--修改密码,这次分享留言功能开发 我们能梳理下对应的逻辑 1.校验用户是否登录 2.校验留言的用户是否存在 3. ...

  6. 关于一次配合开发工作而产生的服务器内核参数问题(Android 网络问题)

    关于一次配合开发工作而产生的服务器内核参数问题(Android 网络问题) 问题转载(本人与作者遇到了同样的问题) 问题描述 问题描述:在这几年的Android开发中,遇到了一个困扰我好久的问题,有时 ...

  7. 【Android 应用开发】Android 网络编程 API笔记 - java.net 包相关 接口 api

    Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...

  8. 【Android 应用开发】Android 网络编程 API笔记 - java.net 包 权限 地址 套接字 相关类 简介

    Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...

  9. Android 网络编程 记录

    简单介绍 看了深入理解Android网络编程感觉不错.今天对Android网络编程进行了要点记录. 内容 Android基于网络技术和编程实践 要点 定义 描写叙述 IP协议 用于报文交换网络的一种面 ...

随机推荐

  1. Scrum教练不应兼任product owner

    ScrumMasters Should Not Also Be Product Owners(中文翻译) December 2, 2014 by Mike Cohn 翻译:2015.2.18 by o ...

  2. oracle-同义词,又学到东西了

    select  col1  from tab1@db_link1; create or replace synonym test123 as se,ect col1 from tab1@db_link ...

  3. 对 const char* const &a 的理解

    定义中用到&是独立引用. 比如: char i; char &a=i; 表示a是i的一个单独引用. 当有i='a'时,也有a='a'; 当有a='c'时,也有i='c'; 两个变量的标 ...

  4. SGU 196.Matrix Multiplication

    时间限制:0.25s 空间限制:4M Solution n=10000,m=100000,显然不能用矩阵乘法乘出来. S= ATA 对于矩阵S的一行,所有在A矩阵中1位置的元素都相等,并且都等于这一行 ...

  5. ios开发之ios9UIWebView不显示网页问题

    错误描述: App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecu ...

  6. Java学习----创建对象的数组

    1.初始化数组的长度 2.初始化每个元素对象 3.调用每个对象的方法 public class Student { private String name; public Student() {} p ...

  7. Centos JAVA Eclipse

    wget http://download.oracle.com/otn-pub/java/jdk/8u5-b13/jdk-8u5-linux-i586.tar.gz vi /etc/profile 在 ...

  8. PHP之验证码识别

    首先推荐几篇有关验证码识别的文章,觉得不错 php实现验证码的识别(初级篇) 关于bp神经网格识别验证码 一.思路 碰见一个验证码,如果我们想要识别它,我们需要的是做什么呢? 我们先观察几个验证码.. ...

  9. PHP 获取目录

    取得当前文件名,当前目录,上层目录 文件名 test.php 路径 + 文件名 (要取得 /var/www/test/test.php)      echo __FILE__; 文件名 (要取得 te ...

  10. 快速访问WCF服务--ServiceModel 元数据实用工具 (Svcutil.exe)

    基本定义 ServiceModel 元数据实用工具用于依据元数据文档生成服务模型代码,以及依据服务模型代码生成元数据文档. SvcUtil.exe ServiceModel 元数据实用工具可在 Win ...