写在我的第200篇博客中的“前言”
这篇是我的第200篇博客。落笔写正文前我感触彼深。自从一个小P孩那时写博客只是为了一时的好玩,到逐步发觉只有让越来越多的人理解了技术,把技术普及到门槛越来越低,才会反推技术人员的处镜越来越好。因为必竟那时是2003-2006年,这些BS技术还不这么普及的时候。博客在当时取得了一定的作用。同时随着写博客成为了我的习惯后我发觉不仅仅是光写博客这么一个事,更多的在于总结、梳理自己的即往知识的这个过程反推了自己进一步严谨、逻辑、抽象化思维,因此我开始发觉这件事是对己对彼都是一件双羸的事,同时也开始注意文体、格式、beautiful这些因素。同样的也因为长期写博客的锻炼我的架构彻底走向了成熟。我没有吃到互联网流量红利,虽然进过一些大厂但只吃到过一些很薄的利。什么叫薄?什么叫利?
真正的红利是指12,13年进大厂的这一批,都已经是真的得到利了。我得到的无非就是相对还可以的收入以及可以吊打90%传统企业内技术的能力,这在当年让我对于职业来说具有了:我来选的能力。我自己测过IQ,我承认不高,不是那种可以进清华北大的130+,同时我先天色弱、说话口吃+结巴。但就因为我要写博客、要表达清、要让看的人知道我到底要表达些什么?因此我把自己的能力放在了当时的行业内去做竞争,而不在于本企业。因此这10多年来我正是通过写博客克服了这些困难得到了“软”技能上的提升。如我之前写的博客内容里所述:任何一个“行业界”平民是吊打你所在的企业的所有人的。这个道理是在我的身上得到了验证。
随着时间的推移来到了今年。总体形势已经很明朗,我们反思我们过往的技术。什么Spring、什么Android开发、什么大数据!结果发觉它们其实没有之前那么的“硬”那么的“金”,连银都称不上。裁员潮和能力无关,而在于你能产生的带给企业的价值是否两倍于你的收入?这在我之前的博客中就给出过这个不等式,我记得是2015年左右的博客我写过一个“你的能力必须>你的收入,并且连等于都不可以有”,这一点和马斯可今年推特风波中说到的:两倍于你的能力不谋而合。这不是我的先见之明,而是那时我已经看透了事物的本质。这个本质就是:不管是Spring,还是大数据,还是Android,你学得再好、参于的核心开发再多,哪怕你创造了像Spring Cloud、NETTY、MYSQL、TIDB这样的东西,请问一下自己、并且是客观的问一下自己:你创造出来的东西为人类社会带来了财富了吗?
短期的红利型财富那不叫财富,那只是吃了资本投融资的利而己。我指的财富是真正的人类财富!社会的财富!这也是目前的趋势。
支柱产业之所以称为支柱,正是因为它们才可以真正带来人类社会的财富。反观Spring, MYSQL,大数据,Android这种,目前90%的开发都是些什么人呢当然这包括我自己?他们在为投融资带来的虚拟在开发。开发的东西只是满足了人类的“软”需求,而不是人类社会的“硬”需求。
我们举点实际的例子,不要说这么高大上的东西。我们都有过学生时代、或者是一些培训班出来的IT人员,我们在之前是不是发觉:用C写双向链表、红黑树特别的枯涩特别的让人怀疑人生?结果发觉有了一个SQL SERVER、ORACLE、MYSQL,原来只要会增删改查就可以完成了一个同学录?自己用MFC的类库、指针、链表、编译参数、环境调试还要学UI编程还要学内存控制苦哈哈了一年还做不出一个ASP、JSP可以用1个月不到就做出来的同学录这么“精美”,然后听着ASP、JSP满嘴飞的InterDev、SQL SERVER、IIS、TOMCAT、APACHE、Eclipse那叫一个羡慕那叫一个眼红。更不要说在2002年就已经开始传出了:互联网就业369之说。即:会个ASP月薪3,000,会个JSP月薪6,000,会个PHP月薪9,000。这叫369。
时代在变、环境在变,曾经的369只不过变成了Spring Boot、vue.js、Android。Oracle DBA只不过变成了大数据而己。而人心图“简单”、人心趋易这个魔咒始终悬在了我们的头上,它只是没有“发动”而己。
当时间来到这两年,当流量红利、投融资这种虚拟开始破灭时,那么我们手上的这些之前的金饭碗、银饭碗的情况自然不会好到什么地方去。我们说一个程序员、一个计算机科学。。。你写了10几年的Spring、你处理过万级的每秒并发、你可以把个Hadoop玩的头头是转。请问:现在我要写一个中翻英手机上安装用的字典,就你自己一个人,自己开发出来。你能做吗?90%包括大厂的P8听到这个需求后直接懵掉。
而我却在3年前看到小学生都已经开始自己能写出一个词典了,代码、算法之复杂远超我们这些架构师。
我拿了一道小学一年的C语言题去面试,直接淘汰过99%来面试高级的开发!
各位,我想起了2002年时我们的导师说过的一句话:任何没有用到高等数学的计算机都只能称之为简单应用。
这句话现在想起来如五雷轰顶一样在我们的头顶炸响!
人心趋易、快乐一时但不能快乐一辈子。当年的金、银饭碗其实它们的本质还是一种“投机取巧”的短时间快乐而己。
因此当我在2015年、16年就看出了这么一种趋势时。我就开始不谋求只有JAVA方面架构师这么“单纯”的一件事了。我已经开始在转Android和大数据了。而我转Android和大数据不是为了干Android和大数据。
而是,因为对标你要走一条“真正的计算机科学”这条路,我们来看计算机科学:支柱行业这些行业,比如说:量子通讯、比如说IOT、比如说:区块链、比如说:航天、比如说:金融里的挂标、基金、股标测算、FINTECH里的根据语音、视频判断投保人是否在说谎、虹膜、口气气味加密锁这些东西来说的话:什么Android、什么mysql、什么tidb、什么spring boot、什么微服务?对比这些真正的硬核技术来说都只是:1+1=2这么简单。
简单到你可以认为那个领域的人如果不全会这些就好比你没有“手”一样做什么事都不可能。
我有一个师兄,他是搞硬核科技那种,他之前看着我们满嘴跑火车一样的:hadoop、自建模、spring cloud,他听我们说时眼光中处处透露着惊奇又充满着对我们的羡慕。4年后再见他,他手下有2个硕士,他们3个人用spring boot、大数据实时开发了一套无人机飞控感知和远程操作系统用来采集大气内的微颗粒,界面是大屏Android PAD。3个人从0开始开发。对他们来说这些技能都只是“树枝”一样的工具、都只是为他们“掏蚂蚁窝”来做准备的而己。
业务逻辑输入员,或许用这个词来形容我们当年的这群人的所做会比较客观。
哦,你会改源码!你能读源码!So What!
那你也只能算是把树村削尖了一点让它可以除了掏蚂蚁窝外还能在河里打几条鱼而己。
而人家已经处于:黑火药时代了。
吊打一样的存在!
因此当时我转Android、大数据根本不是为了从事这些行当和转行当,而是在于真的要把自己的知识开始往硬核领域转。
我选的是量子学和IOT领域,在那个领域如我上面说过,这些业务逻辑输入技能都只是应该的、必须的、基本的。
因此这也是为什么我选择不断本着开源精神,把各种技术特别是网上很多找不到的实战级别的经验公开的道理。因为这些东西它们对我来说已经根本不构成“技术”了,它们被更多人学会也不会存在教会了徒弟、饿死了师傅。这个原因是:
- 超过90%以上的徒弟没有这个意识会去真的学,自己感觉“牛逼”的不得了直到拿到HR的“通知”;
- 剩下少部分的徒弟学会了,这玩意因为不属于硬核科学因此根本够不成技能、职业竞争。它们属于必须和应该的,不会都“吃不了饭”了,因此“拉你上岸”而己并不构成对自身的竞争威胁;
这就是我的认知。这个认知的核心总结就是:通过你我的共同努力把技术门槛降低因此可以让技术进一步普惠因此才能创造更多的普惠技术去服务的领域,那么反过来它会倒推让自己有更多机会,这是一个相悖的理念。但又是正确的理念。绝大多数人没有意识到这一点,所以我一点不担心普惠了别人、饿到了自己。
同时这边顺便说一下,有不少网上找不到的、连官网都没有、连GITHUP的讨论里几百个回贴老外都想不到的那些实战级的解决方案是我和我的大师兄讨论后得到的启发,然后我去自己的单位试了一下,发现这个效果不是一般的好然后回头一看,其实也就这么简单。
这些足以说明在硬核科学面前一切我们这些人的技能都是被吊打的。然后我大师兄这群人又特别谦虚、特别礼貌、特别的与世无争,我问过他,为什么见了之前在大厂然后进到他们单位做普通程序员的比他低5个级别的人他都会鞠躬献笑甚至为他们泡茶呢?他说:因为你和他们是产生不了任何利益上的冲突的;就算别人抢你的活、讨到了你的功劳,那都是一时之快,而到了深夜当你游荡在量子领域、游荡在EPR佯谬时无人可以和你竞争。当你想通这个道理时你还肖于和别人去争论吗?那么爱世人,就对别人礼貌点、谦虚点吧。
说个很搞笑的一件事,我和我们师兄讨论到实时计算的一些东西时,我告诉过他我面临过一家全国巨型零售时的一些实时数据以及人群、行为、动线分析有多么庞大、多么实时性要求高。他于是告诉遥感、监测、大气的数据以及他们用到的一些算法,我一看。。。好吧,我收起什么QPS10万、TPS上万这种东西来、收起什么大数据实时、什么icebug这种只能用来做个人show的东西,老老实实重温小波变大波、正弦、傅立叶,哪怕是从LOG对数补起来吧。我那次真心是看到了计算机科学的本质了。
好了。言规正传。
说到这儿大家就知道为什么我要立志公开我所有的在8年前学的Android的东西,首先是因为它太简单了。
其次,它没有技术含量,比了个vue.js还简单。
因此,对于程序员,因为我一直是面向程序员的博客来说它不属于另一种技能,而是属于一个1+1=2的东西。
退一万步来说,你要转行不方便或者觉得不可能。那么当人家只会用一根树枝,而你现在可以把树枝削削尖,那么你的生存也会比别人好过一点。如果加一个实时计算或者是初步的AI技能你至少可以生个篝火烤个鱼吃了不用“拉肚子”而不用“天天吃生的”。
就这么简单的道理。
知道了这个道理,我们更要好好学了。把基础打好才能谈发展。
下面进入今天的篇章。
介绍
Android中最常用的Dialog叫Alert Dialog,它默认支持三个按钮:OK、CANCEL、中立(相当于知道了)。
但是它也可以有多种表现方式,以及不同的按钮,甚至可以自定义。
Alert Dialog的使用步骤我们用逻辑的语言描述出来是下面这样的:
- 创建AlertDialog.Builder对象;
- 调用setIcon()设置图标,setTitle()或setCustomTitle()设置标题;
- 设置对话框的内容:setMessage()还有其他方法来指定显示的内容;
- 调用setPositive/Negative/NeutralButton()设置:确定,取消,中立按钮;
- 调用create()方法创建这个对象,再调用show()方法将对话框显示出来;
我们今天我们会先用以下几个简单例子来说透Alert Dialog的各种使用场景,最后的例子中我们会把整个Android自带的AlertDialog给完全自定义一下。
项目结构
其实上述这几个Dialog的例子真正用到的文件只有这3个:
- 一个是对话框里覆盖原生对话框图标的自定义图标;
- 一个是前端UI布局;
- 一个是后端交互;
下面就来看前端UI界面。
前端UI界面-activity_main.xml
简单了不能再简单了
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="5dp">
<Button
android:id="@+id/btnSimpleDialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="显示一个简单的对话框"/>
<Button
android:id="@+id/btnItemsDialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="显示一个列表对话框"/>
<Button
android:id="@+id/btnSingleChoiceDialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="显示一个带单选的对话框"/>
<Button
android:id="@+id/btnMultiChoiceDialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="显示一个可多选的对话框"/>
</LinearLayout>
后端交互代码-MainActivity.java
package org.mk.android.demoalertdialog;
import androidx.appcompat.app.AppCompatActivity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private Button btnSimpleDialog;
private Button btnItemDialog;
private Button btnSingleChoiceDialog;
private Button btnMultiChoiceDialog;
private View viewCustom;
private AlertDialog dlg = null;
private AlertDialog.Builder builder = null;
private Context ctx;
private String[] favoriateFood = new String[]{"辣子鸡", "水煮牛肉", "馋中级牛蛙"};
private String[] myFruit = new String[]{"西瓜", "葡萄", "香梨"};
private String[] chickenCombo = new String[]{"一对辣翅", "川香汉堡", "像皮泥鸡块", "苦味玉米"};
private boolean[] chickenComboChoice = new boolean[]{false, false, false, false};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ctx = MainActivity.this;
btnSimpleDialog = (Button) findViewById(R.id.btnSimpleDialog);
btnItemDialog = (Button) findViewById(R.id.btnItemsDialog);
btnSingleChoiceDialog = (Button) findViewById(R.id.btnSingleChoiceDialog);
btnMultiChoiceDialog = (Button) findViewById(R.id.btnMultiChoiceDialog);
btnSimpleDialog.setOnClickListener(new OnClickListener());
btnItemDialog.setOnClickListener(new OnClickListener());
btnSingleChoiceDialog.setOnClickListener(new OnClickListener());
btnMultiChoiceDialog.setOnClickListener(new OnClickListener());
}
private class OnClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnSimpleDialog:
builder = new AlertDialog.Builder(ctx);
dlg = builder.setIcon(R.mipmap.wechat_goutou).setTitle("系统提示:").setMessage("这是一个最普通的AlertDialog," + "\n带有两个按钮,分别是取消,和确定").setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(ctx, "你点击了取消按钮~", Toast.LENGTH_SHORT).show();
}
}).setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(ctx, "你点击了确定按钮~", Toast.LENGTH_SHORT).show();
}
}).create(); //创建AlertDialog对象
dlg.show();
break;
case R.id.btnItemsDialog:
builder = new AlertDialog.Builder(ctx);
dlg = builder.setIcon(R.mipmap.wechat_goutou).setTitle("选择你喜欢的菜").setItems(favoriateFood, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getApplicationContext(), "你选择了" + favoriateFood[which], Toast.LENGTH_SHORT).show();
}
}).create();
dlg.show();
break;
case R.id.btnSingleChoiceDialog:
builder = new AlertDialog.Builder(ctx);
dlg = builder.setIcon(R.mipmap.wechat_goutou).setTitle("选择你喜欢的水果,单选").setSingleChoiceItems(myFruit, 0, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getApplicationContext(), "myFruit" + myFruit[which], Toast.LENGTH_SHORT).show();
}
}).create();
dlg.show();
break;
case R.id.btnMultiChoiceDialog:
builder = new AlertDialog.Builder(ctx);
dlg = builder.setIcon(R.mipmap.wechat_goutou).setMultiChoiceItems(chickenCombo, chickenComboChoice, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
chickenComboChoice[which] = isChecked;
}
}).setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String result = "";
for (int i = 0; i < chickenComboChoice.length; i++) {
if (chickenComboChoice[i])
result += chickenCombo[i] + " ";
}
Toast.makeText(getApplicationContext(), "客官你点了:" + result, Toast.LENGTH_SHORT).show();
}
}).create();
dlg.show();
break;
}
}
}
}
代码导读
- 我们为每一个按钮绑定一个事件;
- 每个事件做的事就是:builder.setIcon(图标).setTitle("对话框Title").set对话框样式.为对话框绑定事件;
- 实现每个不同类型的对话框绑定事件的“点击/选择”事件,用Toast显示;
这已经简单了不能再简单了。
一系列简单对话框的实现效果
下面开始我们来实现一个自定义的对话框
自定义对话框
我们想把我们的对话框实现成上面这样的形式,我们可以看到首先我们不用Android Studio自带的对话框颜色、样式了。
连按钮都是我们自己的图片。
因此这边有这么两组按钮需要自定义
- 确认、关闭按钮的自定义,定义时我们每个按钮需要两个个图片样式,按下去和没有按下去时的按钮样式;
- 退出按钮的自定义,这个按钮也同样有两种样式,按下去和没有按下去时的按钮样式;
按钮没有被按下去的样式:
按钮被按下去的样式:
我们通过以下截图进一步来说明normal(没有被按下去)和pressed(按下去时)的样式:
按钮没有被按下去时的样式
按钮被按下去时的样式
下面我们就来看如何制作这样的一个对话框
项目结构和原理说明
- 整个自定义对话框有两组按钮,每一组按钮有normal态和pressed态;
- 两组对话框内含的内容;
- 整个自定义对话框的布局;
- 最后不要忘了一点,你需要修改你的:res\values\下的theme文件,否则android studio还是用自带的对话框样式而不会使用你自定义的这些背景和颜色;
自定义res\values\theme文件
看,我们把原来parent="Theme.MaterialComponents.DayNight.DarkActionBar"这句改成了:parent="Theme.MaterialComponents.DayNight.NoActionBar.Bridge",这样Android才允许我们使用我们的自定义对话框样式。这就是网上绝大部分教程没有说透的点,导致了竟然有一些初学者耗时几十小时不得“入法门”。
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<!--
<style name="Theme.DemoCustomizedDialog" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
-->
<style name="Theme.DemoCustomizedDialog" parent="Theme.MaterialComponents.DayNight.NoActionBar.Bridge">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>
自定义确定和关闭按钮
确定和关闭按钮是归为同一组按钮样式的,都为“selector/choice”,因此我们使用一个xml文件来定义它们,btn_selector_choose.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@mipmap/button_pressed"/>
<item android:drawable="@mipmap/button_normal"/>
</selector>
自定义对话框的关闭按钮同样也为一组,btn_selector_exit.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@mipmap/exit_pressed"/>
<item android:drawable="@mipmap/exit_normal"/>
</selector>
自定义对话框布局
view_dialog_custom.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/titlelayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:background="#CCE3ED"
android:padding="5dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="提示信息"
android:textColor="#2C2B2B"
android:textSize="14sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_cancle"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:background="@drawable/btn_selctor_exit" />
</RelativeLayout>
<LinearLayout
android:id="@+id/ly_detail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/titlelayout"
android:layout_centerInParent="true"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="20dp"
android:text="通过setView()方法定制AlertDialog"
android:textColor="#0A0B0B"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:text="作者:lifetragedy"
android:textColor="#090909"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/ly_detail"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<Button
android:id="@+id/btnBlog"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_margin="5dp"
android:layout_weight="1"
android:background="@drawable/btn_selctor_choose"
android:text="访问博客"
android:textColor="#ffffff"
android:textSize="14sp" />
<Button
android:id="@+id/btnClose"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_margin="5dp"
android:layout_weight="1"
android:background="@drawable/btn_selctor_choose"
android:text="关闭"
android:textColor="#ffffff"
android:textSize="14sp" />
</LinearLayout>
</RelativeLayout>
在这个xml文件中,我们把:btn_selector_choose.xml和btn_selector_exit.xml文件以及我们的4个图片串了起来。
同时,在这个view_dialog_custom.xml文件中我们还自定义了对话框的以下几个元素:
- title颜色
- 不同区域的文字颜色
- 按钮上的颜色
- 字体大小
activity_main.xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="5dp">
<Button
android:id="@+id/btnCustomizedDialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="自定义对话框"/>
</LinearLayout>
它就一个按钮,简单了不能再简单了。
MainActivity.java
package org.mk.android.democustomizeddialog;
import androidx.appcompat.app.AppCompatActivity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private Button btnCustomizedDialog;
private AlertDialog dlg = null;
private AlertDialog.Builder builder = null;
private View viewCustom;
private Context ctx;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ctx = MainActivity.this;
btnCustomizedDialog = (Button) findViewById(R.id.btnCustomizedDialog);
//初始化Builder
builder = new AlertDialog.Builder(ctx);
//加载自定义的那个View,同时设置下
final LayoutInflater inflater = MainActivity.this.getLayoutInflater();
viewCustom = inflater.inflate(R.layout.view_dialog_custom, null,false);
builder.setView(viewCustom);
builder.setCancelable(false);
dlg = builder.create();
viewCustom.findViewById(R.id.btn_cancle).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dlg.dismiss();
}
});
viewCustom.findViewById(R.id.btnBlog).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "访问博客", Toast.LENGTH_SHORT).show();
Uri uri = Uri.parse("http://blog.csdn.net/lifetragedy");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
dlg.dismiss();
}
});
viewCustom.findViewById(R.id.btnClose).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "对话框已关闭~", Toast.LENGTH_SHORT).show();
dlg.dismiss();
}
});
btnCustomizedDialog.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dlg.show();
}
});
}
}
代码导读:
- 使用setView,加载自定义的那个view_dialog_custom.xml布局;
- 为每一个对话框上的按钮绑定事件;
- 使用隐式授权:Intent intent = new Intent(Intent.ACTION_VIEW, uri)授权跳转到一个外部url,它会在我们的Android中直接采用AndroidStudio自带的google chrome打开一个网页;
来看实现效果
运行后,点击【自定义对话框】按钮,弹出以下自定义的对话框
点击【访问博客】按钮得到如下界面。在Android Studio里第一次使用chrome打开外部网页地址时会有一个google chrome的“使用导航“,你需要在这个导航里做一些简单的设置无非就是【下一步】->【下一步】之类的操作。然后它才会打开你在代码里指定的url。而下一次再做同样的操作,就不会在打开外部url时出现chrome的first steps的操作了。
自己动手去感受和体验一下吧。
结束第200篇博客,并在此勉励自己激励读者:
- 人生有限、学海无限!
- 勇于否定自己的过去、勇于面对从零开始刷新自己的知识!
- 世上无难事,只怕有心人!
- 这个世界永远没有太晚,能阻止你去做想要做的事的人永远只有你自己!