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.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实现
基本的浏览器功能已经实现。
代码:
PS:转载请注明出处谢谢!
Android网络:开发浏览器(一)——基本的浏览网页功能开发的更多相关文章
- [小程序开发] 微信小程序内嵌网页web-view开发教程
为了便于开发者灵活配置小程序,微信小程序开放了内嵌网页能力.这意味着小程序的内容不再局限于pages和large,我们可以借助内嵌网页丰富小程序的内容.下面附上详细的开发教程(含视频操作以及注意事项) ...
- Android进阶笔记01:Android 网络请求库的比较及实战(一)
在实际开发中,有的时候需要频繁的网络请求,而网络请求的方式很多,最常见的也就那么几个.本篇文章对常见的网络请求库进行一个总结. 一.使用HttpUrlConnection: 1. HttpUrlCon ...
- Android学习笔记(十八)——使用意图筛选器和实现浏览网页(附源代码)
使用意图筛选器 点击下载源代码 1.创建一个Intents项目,给该项目加入一个新类,命名为MyBrowserActivity.在res/layout目录下新增一个browser.xml: 2.在An ...
- go语言实战教程之 后台管理页面统计功能开发(1)
本节内容我们将学习开发实现后台管理平台页面统计功能开发的功能接口,本章节内容将涉及到多种请求路由的方式. 功能介绍 后台管理平台不仅是功能管理平台,同时还是数据管理平台.从数据管理平台角度来说,在管理 ...
- FastAPI(七十)实战开发《在线课程学习系统》接口开发--留言功能开发
在之前的文章:FastAPI(六十九)实战开发<在线课程学习系统>接口开发--修改密码,这次分享留言功能开发 我们能梳理下对应的逻辑 1.校验用户是否登录 2.校验留言的用户是否存在 3. ...
- 关于一次配合开发工作而产生的服务器内核参数问题(Android 网络问题)
关于一次配合开发工作而产生的服务器内核参数问题(Android 网络问题) 问题转载(本人与作者遇到了同样的问题) 问题描述 问题描述:在这几年的Android开发中,遇到了一个困扰我好久的问题,有时 ...
- 【Android 应用开发】Android 网络编程 API笔记 - java.net 包相关 接口 api
Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...
- 【Android 应用开发】Android 网络编程 API笔记 - java.net 包 权限 地址 套接字 相关类 简介
Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...
- Android 网络编程 记录
简单介绍 看了深入理解Android网络编程感觉不错.今天对Android网络编程进行了要点记录. 内容 Android基于网络技术和编程实践 要点 定义 描写叙述 IP协议 用于报文交换网络的一种面 ...
随机推荐
- c++ Cout 输出格式
控制符是在头文件iomanip.h中定义的对象.使用前必须把iomanip.h包含进来 1. I/O的书写格式 I/0流是输入或输出的一系列字节,当程序需要在屏幕上显示输出时,可以使用插入操作符“&l ...
- CentOS 6.5下搭建NFS文件服务器
环境介绍:服务器: 192.168.0.1客户机: 192.168.0.2安装软件包:服务器和客户机都要安装nfs 和 rpcbind 软件包:yum -y install nfs-utils rpc ...
- JSONModel的基本使用
JSONModel 是一个库,它能智能并且快速的创建出数据 model,你可以在你的 iOS 项目或者 OSX 项目上使用它. 使用前准备 添加 JSONModel 到你的工程中 1.需要的环境: A ...
- AFNetworking自带的解析图片的方法
首先要导入头文件 #import "UIKit+AFNetworking.h" 方法如下: [personImageView setImageWithURL:[NSURL URLW ...
- SGU 149. Computer Network
时间限制:0.25s 空间限制:4M: 题意: 给出一颗n(n<=10000)个节点的树,和n-1条边的长度.求出这棵树每个节点到最远节点的距离: Solution: 对于一个节点,我们可以用D ...
- java之两个字符串的比较
compareTo() 的返回值是int, 它是先比较对应字符的大小(ASCII码顺序)1.如果字符串相等返回值02.如果第一个字符和参数的第一个字符不等,结束比较,返回他们之间的差值(ascii码值 ...
- Sass学习
1.1下载地址: http://rubyinstaller.org/downloads 2.1 安装 SASS是Ruby语言写的,但是两者的语法没有关系.不懂Ruby,照样使用.只是必须先安装Ruby ...
- C++实现base64编码(1)
下面的代码是php里面的base64编码逻辑,确实比我之前的要美观很多,我只是简单的用C++的类进行了一下封装,删除了一些没用的逻辑,基本上还是原来PHP的代码: #include <iostr ...
- 在Site Settings下找不到Navigation标签
有时候我们可能找不到Navigation标签, 仅仅在Look and Feel下面看到"Quick launch" 如何才能找到我们想要的"Navigation&quo ...
- linux hadoop 集群安装步骤
http://blog.csdn.net/xjavasunjava/article/details/12013677 1,时间同步hadoop集群的每台机器的时间不能相差太大. 安装集群前最好进行一下 ...