登录后台

页面导航

本文编写于 2399 天前,最后修改于 1667 天前,其中某些信息可能已经过时。

讲作业

话说这次的作业是设计一个布局:

这大概也是之前学过的了,直接贴一下代码吧:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:id="@+id/icon"
        android:layout_centerHorizontal="true"
        android:background="@drawable/ic_magnify"
        android:gravity="center"
        android:paddingTop="500dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/icon"
        android:orientation="horizontal">

        <EditText
            android:id="@+id/edittext"
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:layout_weight="1"
            android:hint="请输入关键词或网址" />

        <ImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:src="@drawable/ic_send" />
    </LinearLayout>

TIPS: EditText 可以通过「android:hint="提示词"」来设置提示词,在用户输入内容时提示词会自动消失;在清空输入框时,提示词又会重写出现

最外层的布局是一个相对布局,LOGO 的图片固定大小为 100dp*100dp ,距离顶端 500dp,对齐方式为居中。然后紧接着一个水平的线性布局宽填充父布局,高为适应大小。然后在线性布局里放置一个 EditText,一个 ImageView 。其中 EditText 高度和 ImageView 的高度相同都是 50dp ,因为那个小飞机是正方形,所以 ImageView 的宽也设置为 50dp 这也都不难。重点是,他需要背后的逻辑,我们需要让他输入关键词之后,该搜索的搜索,该跳转的跳转。

Intent 活动之间的桥梁

随着应用的开发,一个活动肯定解决的不了问题,那么就需要建立多个活动。不过打开程序时都是启动的主活动,如果要启动别的活动就需要使用 Intent 了。

显式 Intent

我们昨天已经讲过了怎么创建活动。我们依旧还是在 com.intent.test 包上右键~new~Activity~Empty Activity,弹出新建活动的窗口,我们呢这次就把新建的活动叫做 「webview_activity」,记得这次勾选 Generate Layout File 让 AS 为我们自动创建布局文件,然后在「Layout File」中给布局布局文件起一个名字,就叫「activity_webview」吧。点击 Finish 结束:

随后就可以看到创建好的布局和 Java 文件:

然后我们配置下 MainActivity.java ,为那个小飞机加一个点击事件来跳转到 webview_activity:

ImageView search = (ImageView)findViewById(R.id.search);
search.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(MainActivity.this, webview_activity.class);
        startActivity(intent);
    }
});     

Intent 翻译成中文就是意图的意思。Intent 的构造函数需要传入两个参数,第一个是当前活动的上下文,通常传入当前「类名.this」就行。第二个参数需要传入要启动的目标活动,通常传入「目标活动类名.class」即可。这样我们就构造出了我们要启动一个名字叫「webview_activity」的活动,意图很明显。这样的方式就叫做显示 Intent 。我们调用类提供「startactivity();」方法并传入 Intent 对象就可以启动另一个活动。现在我们重新运行程序,点击小飞机就会发现成功的跳转到了另一个活动:

现在来完善一下我们的新活动,在布局里放入一个 WebView 就行:

<!--文件:webview_activity.xml -->
<WebView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/webview"/>

然后修改 Java 文件:

public class webview_activity extends AppCompatActivity {

    String HOMEPAGE = "https://bing.com";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview);
        WebView webView = (WebView)findViewById(R.id.webview);
        initWebView(webView);
        webView.loadUrl(HOMEPAGE);
    }

    void initWebView(WebView webView){
        webView.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                //设置在当前窗口打开网页
                view.loadUrl(request.toString());
                return true;
            }

            @Override
                //拦截唤醒本地app
            public void onPageStarted(WebView view, String url, Bitmap favicon){
                if (url.startsWith("intent") || url.startsWith("INTENT")) view.loadUrl(url);
            }
        });
        //设置支持JavaScript
        webView.getSettings().setJavaScriptEnabled(true);
    }
}

最后别忘了加入联网权限

<uses-permission android:name="android.permission.INTERNET"/>

运行的效果如下:

传递数据到下一个活动

话说这也不行呀,我得把我输入的关键词传递给下一个活动。于是我们就需要用 Intent 把数据传递给下一个活动。修改MainActivity.java 中 ImageView 点击事件的代码:

Intent intent = new Intent(MainActivity.this, webview_activity.class);
EditText editText = (EditText)findViewById(R.id.edittext); 
intent.putExtra("InputWord",editText.getText().toString());
startActivity(intent);

这里我们利用 Intent.putExtra() 方法来把用户输入的文本暂存到 Intent 里。这里接收两个参数,第一个是「键」,第二个是要传递的数据。键说白了就是你给暂存的数据起一个名字,就好比在论坛中的 ID 一样。因为 Intent 能传递多个数据,要给每一个数据起一个名字。然后我们修改 webview_activity.java 中的逻辑,在 setContentView() 后加入以下的代码,来在第一时间获取 Intent 中的值:

Intent intent = getIntent();
String inputText = intent.getStringExtra("InputText");

首先可以通过 getIntent 来获取启动了这个活动的 Intent ,然后调用 getStringExtra(键值) 来获取 Intent 中的数据。因为我们刚才存放的是字符串,所以这里用 getStringExtra 。如果存放的是整数,那么可以用 getIntExtra,同样如果是布尔值,那么就是 getBooleanExtra。我们继续完善:

if (TextUtils.isEmpty(inputText)){  //验证获取到的用户输入是否为空
    //如果用户啥都没输入,就加载主页
    webView.loadUrl(HOMEPAGE);
} else{
    if (inputText.startsWith("http") || inputText.startsWith("HTTP")){ //验证是否是网址
        webView.loadUrl(inputText);  //是网址就直接加载
    } else {
        String result = "https://www.baidu.com/s?wd=" + inputText; //不是网址就拼接出百度搜索链接
        webView.loadUrl(result); //加载拼接出的链接
    }
}

在获取用户输入的内容后,先验证用户的输入是否为空,是空的话就加载主页。如果不为空就判断是否是网址,是网址就直接丢给 webview 去加载,要是不是网址就拼接出百度的搜索链接。逻辑也比较好理清。下面就贴一下完整的代码:

/** 文件:webview_activity.java **/
public class webview_activity extends AppCompatActivity { 

    String HOMEPAGE = "https://m.baidu.com";
    WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview);
        Intent intent = getIntent();
        String inputText = intent.getStringExtra("InputText");
        webView = (WebView)findViewById(R.id.webview);
        initWebView(webView);
        if (TextUtils.isEmpty(inputText)){
            //如果用户啥活都没输入,就加载主页
            webView.loadUrl(HOMEPAGE);
        } else{
            if (inputText.startsWith("http") || inputText.startsWith("HTTP")){
                webView.loadUrl(inputText);
            } else {
                String result = "https://www.baidu.com/s?wd=" + inputText;
                webView.loadUrl(result);
            }
        }
    }

    void initWebView(WebView webView){
        webView.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                //设置在当前窗口打开网页
                view.loadUrl(request.toString());
                return true;
            }

            @Override
            //拦截唤醒本地app等不是浏览器该做的事
            public void onPageStarted(WebView view, String url, Bitmap favicon){
                Log.d("webview", "onPageStarted: "+url);
                if (url.startsWith("intent") || url.startsWith("INTENT")) {
                    view.loadUrl(url);
                }
            }
        });
        //设置支持JavaScript
        webView.getSettings().setJavaScriptEnabled(true);
    }
/** 文件:MainActivity.java **/
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout);
        ImageView search = (ImageView)findViewById(R.id.search);
        search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, webview_activity.class);
                EditText editText = (EditText)findViewById(R.id.edittext);
                intent.putExtra("InputText",editText.getText().toString());
                startActivity(intent);
            }
        });
    }
}

效果图:

总结

今天我们学了显式 intent,明天我们搞隐式的。不过有一个问题值得考虑,这个浏览器没法后退,这个问题就当作业吧,下课。

2020/5/24 注:
这是我 2018 年高中毕业的假期写的,当时并没有自己搭建博客,近期我给这一系列的文章都放到我自己的博客上。
当时写这个系列文章的想法就是扎实下基础,然后能帮到更多的人就更好了,但是大学开学之后就开始了新生活,没有大块的时间去编撰,系列文章也没有再更新过。但是我其实并不想放弃这个系列,那就,有缘再见吧,拜拜ヾ(•ω•`)o