为了提高工作效率,对一些常见View的特殊用法作一下总结。

一、进度条对话框

坑:https://blog.csdn.net/nailsoul/article/details/38870827 (ProgressBar占据位置但是不显示的问题)

最近我的同事孙大姐提个需求:将进度显示框的进度条放到文字上方。

1.使用系统的ProgressDialog

https://www.cnblogs.com/guop/p/5139937.html  (圆形进度条与水平进度条) (注意构造方法要传theme,否则有些手机可能看不到进度条。)

看不到进度条的还有一种情况就是没有指定ProgressBar的一个属性:

     style="@android:style/Widget.ProgressBar.Inverse"

注意创建ProgressDialog时不要使用Builder来创建,即:

     new ProgressDialog.Builder(mContext).create();

用这种方式创建的ProgressDialog会不显示进度条,只会显示纯文字。

原生的进度显示框设置样式为SPINNER,默认进度条放在文字左方,所以无法满足孙大姐的需求。

2.使用AlertDialog自定义View

正确的用法:

     progressDialog = new AlertDialog.Builder(mContext).create();View rootView = LayoutInflater.from(mContext).inflate(R.layout.mprogress_dialog, null);pbBar = rootView.findViewById(R.id.pb_bar);tvMsg = (TextView) rootView.findViewById(R.id.tvMsg);progressDialog.setView(rootView);

注意错误的用法:

     new ProgressDialog.Builder(mContext,ProgressDialog.THEME_DEVICE_DEFAULT_DARK).create();

上面的ProgressDialog.Builder实际上还是父类AlertDialog的类,create出来的是AlertDialog,并非ProgressDialog,无法将AlertDialog强制转换成ProgressDialog。

也就无法使用ProgressDialog的特有方法progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER),因此,如果想通过Builder类创建的dialog来实现圆形进度条对话框,

只有自定义view。

3.继承的方式

方式1:直接继承ProgressDialog

研究ProgressDialog的源码可以发现其onCreate方法里:

      else{View view = inflater.inflate(a.getResourceId(com.android.internal.R.styleable.AlertDialog_progressLayout,R.layout.progress_dialog), null);mProgress = (ProgressBar) view.findViewById(R.id.progress);mMessageView = (TextView) view.findViewById(R.id.message);setView(view);}

注意上面的R是com.android.internal.R,如果将布局引用为自己应用的app不就行了。于是继承ProgressDialog准备复写onCreate方法:

可以发现会报各种引用不到的问题,因为这些变量都是父类定义的private变量。

对于变量mContext有public访问方法

对于其他没有public访问方法的private变量,该如何获取呢?

答案:反射   (代码附于文章最后)

还有一项就是系统资源文件com.android.internal.R如何获取呢?

答案:反射   (代码附于文章最后)

com.android.internal.R是无法在java文件里import的

将私有变量和方法用反射代替之后,代码如下:

@Override
protected void onCreate(Bundle savedInstanceState) {LayoutInflater inflater = LayoutInflater.from(getContext());TypedArray a = getContext().obtainStyledAttributes(null,SystemResourceManager.getResourceStyleableIds("AlertDialog"),SystemResourceManager.getResourceAttrId("alertDialogStyle"), 0);if ((int)ReflectManger.getField(ProgressDialog.class,this,"mProgressStyle")  == STYLE_HORIZONTAL) {/* Use a separate handler to update the text views as they* must be updated on the same thread that created them.*/ReflectManger.setField(ProgressDialog.class,this,"mViewUpdateHandler",new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);/* Update the number and percent */int progress = ((ProgressBar)(ReflectManger.getField(ProgressDialog.class,this,"mProgress"))).getProgress();int max = ((ProgressBar)(ReflectManger.getField(ProgressDialog.class,this,"mProgress"))).getMax();if (ReflectManger.getField(ProgressDialog.class,this,"mProgressNumberFormat") != null) {String format = (String) ReflectManger.getField(ProgressDialog.class,this,"mProgressNumberFormat");((TextView)ReflectManger.getField(ProgressDialog.class,this,"mProgressNumber")).setText(String.format(format, progress, max));} else {((TextView)ReflectManger.getField(ProgressDialog.class,this,"mProgressNumber")).setText("");}if (ReflectManger.getField(ProgressDialog.class,this,"mProgressPercentFormat") != null) {double percent = (double) progress / (double) max;SpannableString tmp = new SpannableString(((NumberFormat)ReflectManger.getField(ProgressDialog.class,this,"mProgressPercentFormat")).format(percent));tmp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),0, tmp.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);((TextView)ReflectManger.getField(ProgressDialog.class,this,"mProgressPercent")).setText(tmp);} else {((TextView)ReflectManger.getField(ProgressDialog.class,this,"mProgressPercent")).setText("");}}});View view = inflater.inflate(a.getResourceId(SystemResourceManager.getResourceStyleableId("AlertDialog_horizontalProgressLayout"),SystemResourceManager.getResourceLayoutId("alert_dialog_progress")), null);ReflectManger.setField(ProgressDialog.class,this,"mProgress",view.findViewById(SystemResourceManager.getResourceId("progress")));ReflectManger.setField(ProgressDialog.class,this,"mProgressNumber",view.findViewById(SystemResourceManager.getResourceId("progress_number")));ReflectManger.setField(ProgressDialog.class,this,"mProgressPercent",view.findViewById(SystemResourceManager.getResourceId("progress_percent")));setView(view);} else {View view = inflater.inflate(a.getResourceId(SystemResourceManager.getResourceStyleableId("AlertDialog_progressLayout"),R.layout.m_progress_dialog), null);//注意布局中id的引用:android:id="@android:id/progress"ReflectManger.setField(ProgressDialog.class,this,"mProgress",view.findViewById(android.R.id.progress));ReflectManger.setField(ProgressDialog.class,this,"mMessageView",view.findViewById(R.id.message));setView(view);}a.recycle();if ((int)ReflectManger.getField(ProgressDialog.class,this,"mMax") > 0) {setMax((int)ReflectManger.getField(ProgressDialog.class,this,"mMax") );}if ((int)ReflectManger.getField(ProgressDialog.class,this,"mProgressVal") > 0) {setProgress((int)ReflectManger.getField(ProgressDialog.class,this,"mProgressVal") );}if ((int)ReflectManger.getField(ProgressDialog.class,this,"mSecondaryProgressVal") > 0) {setSecondaryProgress((int)ReflectManger.getField(ProgressDialog.class,this,"mSecondaryProgressVal") );}if ((int)ReflectManger.getField(ProgressDialog.class,this,"mIncrementBy") > 0) {incrementProgressBy((int)ReflectManger.getField(ProgressDialog.class,this,"mIncrementBy") );}if ((int)ReflectManger.getField(ProgressDialog.class,this,"mIncrementSecondaryBy") > 0) {incrementSecondaryProgressBy((int)ReflectManger.getField(ProgressDialog.class,this,"mIncrementSecondaryBy") );}if ( ReflectManger.getField(ProgressDialog.class,this,"mProgressDrawable") != null) {setProgressDrawable((Drawable) ReflectManger.getField(ProgressDialog.class,this,"mProgressDrawable"));}if ( ReflectManger.getField(ProgressDialog.class,this,"mIndeterminateDrawable") != null) {setIndeterminateDrawable((Drawable) ReflectManger.getField(ProgressDialog.class,this,"mIndeterminateDrawable"));}if ( ReflectManger.getField(ProgressDialog.class,this,"mMessage") != null) {setMessage((CharSequence) ReflectManger.getField(ProgressDialog.class,this,"mMessage"));}setIndeterminate((Boolean) ReflectManger.getField(ProgressDialog.class,this,"mIndeterminate"));try {ReflectManger.invokeMethod(ProgressDialog.class,this,"onProgressChanged",null,null);} catch (NoSuchMethodException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}super.onCreate(savedInstanceState);
}

自定义布局m_progress_dialog.xml  如下:

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"><LinearLayout android:id="@+id/body"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="match_parent"android:baselineAligned="false"android:paddingStart="8dip"android:paddingTop="10dip"android:paddingEnd="8dip"android:paddingBottom="10dip"><ProgressBar android:id="@android:id/progress"style="?android:attr/progressBarStyle"android:layout_width="wrap_content"android:layout_height="wrap_content"android:max="10000"android:layout_marginEnd="12dip" /><TextView android:id="@+id/message"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center_vertical" /></LinearLayout></FrameLayout>

但是复写的onCreate方法中有个问题

         view.findViewById(R.id.message)

结果返回null,但是这个id明明是存在的。但是view.findViewById(android.R.id.progress)怎么不是null呢?

思考半天,看下面的代码:

  View view = inflater.inflate(a.getResourceId(SystemResourceManager.getResourceStyleableId("AlertDialog_progressLayout"),R.layout.m_progress_dialog), null);

R.layout.m_progress_dialog只是一个备用布局,跟本就没有加载进去。

将上面的代码稍作修改,将getResourceId方法的第一个值传入一个非法参数0(-1试了不行),这样R.layout.m_progress_dialog就加载了,果然一切正常。

View view = inflater.inflate(a.getResourceId(
//                        SystemResourceManager.getResourceStyleableId("AlertDialog_progressLayout"),0,R.layout.m_progress_dialog), null);

但是圆形进度条不会显示,上面已经说到了,构造方法要传theme,但是传了theme之后,上面代码又会报下面的错:

android.content.res.Resources$NotFoundException: File res/drawable-xhdpi-v4/dialog_full_holo_light.9.png from xml type layout resource ID #0x1080295

通过debug发现,如果Dialog构造方法加了主题,resId != R.layout.m_progress_dialog

如果Dialog构造方法不加主题 ,

二、快速创建一个输入框

  Builder builder = new Builder();builder.setTitle(title).setMessage(message);final EditText et = new EditText(builder.getContext());et.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);builder.setView(et);

注意动态设置edittext的inputType为密码输入框为:

    InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD

三、NavigationView

1.修改NavigationView中的Item的Icon大小

https://blog.csdn.net/zuolovefu/article/details/50175245

2.Android NavigationView 中 menu item 字体大小设置

https://blog.csdn.net/TLD_DLT/article/details/79865525

四、TabLayout

1.修改字体大小

https://blog.csdn.net/qq_33919497/article/details/78548198

2.

转载于:https://blog.51cto.com/4259297/2371400

Android基础View回顾相关推荐

  1. 【学习笔记】Android基础知识回顾

    参考文章 Android序列化总结 Android 四大组件 分别是Activity.Service.BroadCastReceiver.ContentProvider Activity 生命周期 M ...

  2. Android 基础 View 系列之 仿IPhone 开关控件

    极力推荐Android 开发大总结文章:欢迎收藏程序员Android 力荐 ,Android 开发者需要的必备技能 自定义View 是Android中常用的方法之一,本章实现类似于IPhone 开关控 ...

  3. Android基础——View和ViewGroup

    View和ViewGroup 什么是View? 什么是ViewGroup? 继承层次图 基本属性 常用ViewGroup介绍 线性布局 相对布局 帧布局 常用View介绍 TextView Butto ...

  4. android基础!靠着这份面试题跟答案,赶紧收藏!

    上周喜提oppo面试offer,本人在深圳,有4年多的Android项目经验,普通本科学历. 面试是相互相在,OPPO给我的印象确实如其核心价值观所说:本分. 一面.部长面和HR面都蛮顺利(一千个人可 ...

  5. Android自定义view之基础知识

    Android自定义view之基础知识 虽然Android已经自带了很多实用的view和layout,加以调教能实现很美观的界面,但是有一些情况下,需要实现特殊的界面效果,比如我们比较熟悉的各种播放器 ...

  6. 【5年Android从零复盘系列之六】Android自定义View(1):基础详解(图文)

    1.基础一:坐标计算 1.1 Android窗口坐标系计算以屏幕左上角为原点, 向右为X轴正向,向下为Y轴正向 1.2 View坐标系 [注意获取的坐标是像素值,不是dp值] [注意获取的坐标是像素值 ...

  7. Android基础——四大组件之Activity

    这几天继续回顾了一些Android基础方面的知识,今天跟大家一起回顾下Android四大组件中的Activity.虽然很基础,但工欲善其事,必先利其器.我们只有打好夯实的基础,才能在技术开发这条道路上 ...

  8. Android 面试系列(一)Android 基础

    文章目录 序言 四大组件 Activity Activity 生命周期 onStart() 与 onResume() 区别? Activity 启动模式 launchMode 使用 Intent 标记 ...

  9. Android 自定义View(四)实现股票自选列表滑动效果

    一.前言 Android 开发过程中自定义 View 真的是无处不在,随随便便一个 UI 效果,都会用到自定义 View.前面三篇文章已经讲过自定义 View 的一些案例效果,相关类和 API,还有事 ...

最新文章

  1. 转 Android开发学习笔记:浅谈WebView
  2. jstatd,VisualVM使用和报错解决:Could not create remote object--java.security.AccessControlException
  3. 均值定理最大值最小值公式_如何理解中值定理?三大微分中值定理的几何意义及其证明介绍。...
  4. 在JBoss的服务器端正确解码URL参数
  5. openlayers5之热力图heatmap
  6. 应用程序如何链接静态QT Plugin库
  7. python bytes是什么类型,python中的字节串类型(bytes)
  8. windows系统vbs脚本 恶搞将系统搞崩 死机 以及解决
  9. ExtJs6 FontAwesome 图标引用
  10. html闹钟设置,闹钟设置页.html
  11. 一文梳理等保2.0与工业控制系统安全扩展要求
  12. html如何设置hr 标签的线条粗细,设置hr标签的粗细
  13. java五子棋技术路线,一位老码农的编程简史
  14. 分布式基础-分布式事务
  15. 台式计算机除尘方法,一种计算机主机箱除尘装置及其工作方法与流程
  16. linux如何安装python
  17. 企业数字化转型“核心方法论”
  18. python歌词分析_用Python分析周杰伦6.5W字的歌词,原来他是这样的人
  19. Bosun RabbitMQ数据收集
  20. repeat语句 及 赋值语句说明---verilog HDL

热门文章

  1. sftp工具都有哪些_公众号怎么排版?公众号排版都会用到哪些工具?
  2. android-ndk-aide,NDK安装教程20180605
  3. oracle安装前准备,Oracle 安装前准备
  4. python可以处理哪些文件_4招小技巧,带你迅速提升Python文件处理的逼格
  5. kali2020进入单模式_出租车使用“滴滴”平台 司机希望恢复抢单模式 滴滴出行有回应...
  6. service获取selinux权限_属性问题展开的selinux权限介绍
  7. java反编译工具_推荐Java反编译工具luyten、jd-gui
  8. vue取div当前宽度_vue 过滤器
  9. vue 子级拿值_Vue 父组件主动获取子组件的值,子组件主动获取父组件的值
  10. php访问mysql数据库实验报告,php访问mysql数据库