溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Android基礎(chǔ)View回顧

發(fā)布時(shí)間:2020-07-24 22:07:04 來源:網(wǎng)絡(luò) 閱讀:331 作者:屠夫章哥 欄目:移動(dòng)開發(fā)

為了提高工作效率,對(duì)一些常見View的特殊用法作一下總結(jié)。


一、進(jìn)度條對(duì)話框

????? ?坑:https://blog.csdn.net/nailsoul/article/details/38870827?(ProgressBar占據(jù)位置但是不顯示的問題)

????????最近我的同事孫大姐提個(gè)需求:將進(jìn)度顯示框的進(jìn)度條放到文字上方。

????? ?1.使用系統(tǒng)的ProgressDialog

??????????https://www.cnblogs.com/guop/p/5139937.html? (圓形進(jìn)度條與水平進(jìn)度條) (注意構(gòu)造方法要傳theme,否則有些手機(jī)可能看不到進(jìn)度條。)

??????????看不到進(jìn)度條的還有一種情況就是沒有指定ProgressBar的一個(gè)屬性:

?????

??????????

? ?

????????? 注意創(chuàng)建ProgressDialog時(shí)不要使用Builder來創(chuàng)建,即:

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

????????? 用這種方式創(chuàng)建的ProgressDialog會(huì)不顯示進(jìn)度條,只會(huì)顯示純文字。

? ? ? ? ? 原生的進(jìn)度顯示框設(shè)置樣式為SPINNER,默認(rèn)進(jìn)度條放在文字左方,所以無法滿足孫大姐的需求。

???????

????????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);

???????????注意錯(cuò)誤的用法:

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

????????? 上面的ProgressDialog.Builder實(shí)際上還是父類AlertDialog的類,create出來的是AlertDialog,并非ProgressDialog,無法將AlertDialog強(qiáng)制轉(zhuǎn)換成ProgressDialog。

????????? ?也就無法使用ProgressDialog的特有方法progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER),因此,如果想通過Builder類創(chuàng)建的dialog來實(shí)現(xiàn)圓形進(jìn)度條對(duì)話框,

????????? ?只有自定義view。

???????? 3.繼承的方式

? ? ? ? ? ? 方式1:直接繼承ProgressDialog

????????????研究ProgressDialog的源碼可以發(fā)現(xiàn)其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,如果將布局引用為自己應(yīng)用的app不就行了。于是繼承ProgressDialog準(zhǔn)備復(fù)寫onCreate方法:

????????????Android基礎(chǔ)View回顧

????????????可以發(fā)現(xiàn)會(huì)報(bào)各種引用不到的問題,因?yàn)檫@些變量都是父類定義的private變量。

????????????對(duì)于變量mContext有public訪問方法

????????????Android基礎(chǔ)View回顧

????????????對(duì)于其他沒有public訪問方法的private變量,該如何獲取呢?

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

????????????

? ? ? ? ? ? 還有一項(xiàng)就是系統(tǒng)資源文件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()?{
????????????????@Override
????????????????public?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"
????????????????
????????????????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>

??????????但是復(fù)寫的onCreate方法中有個(gè)問題

?????????view.findViewById(R.id.message)

??? ? ? ? ?結(jié)果返回null,但是這個(gè)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只是一個(gè)備用布局,跟本就沒有加載進(jìn)去。

????????? ?將上面的代碼稍作修改,將getResourceId方法的第一個(gè)值傳入一個(gè)非法參數(shù)0(-1試了不行),這樣R.layout.m_progress_dialog就加載了,果然一切正常。

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

? ? ? ? ? ?但是圓形進(jìn)度條不會(huì)顯示,上面已經(jīng)說到了,構(gòu)造方法要傳theme,但是傳了theme之后,上面代碼又會(huì)報(bào)下面的錯(cuò):

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

? ? ? ? ? ? 通過debug發(fā)現(xiàn),如果Dialog構(gòu)造方法加了主題,resId !=?R.layout.m_progress_dialog

????????????Android基礎(chǔ)View回顧

????????????如果Dialog構(gòu)造方法不加主題?,


一-2、SeekBar

  • ?自定義樣式

    https://blog.csdn.net/u010029983/article/details/45222257? ?(推薦)

    https://blog.csdn.net/qq_38407076/article/details/83012684

    改變游標(biāo)圖片大?。篽ttps://www.cnblogs.com/welhzh/p/3711694.html



????????????

二、快速創(chuàng)建一個(gè)輸入框

??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);

?????? 注意動(dòng)態(tài)設(shè)置edittext的inputType為密碼輸入框?yàn)椋?/p>

????InputType.TYPE_CLASS_TEXT?|?InputType.TYPE_TEXT_VARIATION_PASSWORD

?

三、Spinner

  • ?快速創(chuàng)建spinner


  • private?void?initAreaSpinner(Spinner?spinner_area)?{
    ????ArrayAdapter<CharSequence>?adapter;
    ????adapter?=?ArrayAdapter.createFromResource(this,?R.array.area,?android.R.layout.simple_spinner_item);
    ????spinner_area.setAdapter(adapter);
    ????spinner_area.setOnItemSelectedListener(new?AdapterView.OnItemSelectedListener()?{
    ????????@Override
    ????????public?void?onItemSelected(AdapterView<?>?parent,?View?view,?int?position,?long?id)?{
    ????????????switch?(position){
    ????????????????case?0:
    ????????????????????sdk.setBleAreaType(BleAreaType.HENAN);
    ????????????????????break;
    ????????????????case?1:
    ????????????????????sdk.setBleAreaType(BleAreaType.GUIZHOU);
    ????????????????????break;
    ????????????????case?2:
    ????????????????????sdk.setBleAreaType(BleAreaType.GUANGXI);
    ????????????????????break;
    ????????????}
    ????????}
    
    ????????@Override
    ????????public?void?onNothingSelected(AdapterView<?>?parent)?{
    
    ????????}
    ????});
    ????spinner_area.setSelection(0);
    }
  • ? ?? ?


四、PopWindow

????? ?https://github.com/pinguo-zhouwei/CustomPopwindow?(超級(jí)方便好用的popwindow)

????????



五、NavigationView

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

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

????????2.Android NavigationView 中 menu item 字體大小設(shè)置

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


六、TabLayout

???????? 1.修改字體大小

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

???????? 2.


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI