java 動(dòng)態(tài)改變style

在andriod開(kāi)發(fā)中,很大一部分都要與資源打交道,比如說(shuō):圖片,布局文件,字符串,樣式等等。這給我們想要開(kāi)發(fā)一些公共的組件帶來(lái)很大的困難,因?yàn)楣驳慕M件可能更愿意以jar包的形式出現(xiàn)。但是java的jar包中只允許出現(xiàn)java代碼而不能出現(xiàn)資源。

當(dāng)我們想要以jar包的形式提供我們自己開(kāi)發(fā)的公共組件時(shí),我們就需要把以代碼的形式創(chuàng)建資源。

下面提供一個(gè)使用全Java代碼的形式創(chuàng)建一個(gè)ProgressBar。

ProgressBar默認(rèn)的樣式是一個(gè)圈圈,我們要想其顯示為進(jìn)度條的樣式可以在布局文件中使用如下代碼:

<ProgressBar android:layout_width="fill_parent"

android:layout_height="wrap_content"

style="?android:attr/progressBarStyleHorizontal" />

上面的關(guān)鍵代碼是紅色的部分,這部分的代碼就是使得ProgressBar由轉(zhuǎn)圈圈的樣式變成進(jìn)度條的樣式。使用這種方式創(chuàng)建的ProgressBar不能包含在jar包中。

同樣我們也可以使用純代碼的形式創(chuàng)建ProgressBar對(duì)象,如下:

...

ProgressBar progressBar = new ProgressBar(context);

LineanerLayout layout = new LinearLayout(context);

layout.addView(progressBar, new LayoutParam(LayoutParam.FILL_PARENT, LayoutParam.FILL_PARENT));

....

這樣就使用純代碼的方式創(chuàng)建了一個(gè)ProgressBar對(duì)象,但是他還只是默認(rèn)的樣式一個(gè)不停的轉(zhuǎn)的圈圈。

這時(shí)我們可能都會(huì)想到好像沒(méi)有設(shè)置樣式。我們可以把之前的那個(gè)樣式設(shè)進(jìn)去,但是我們找遍API發(fā)現(xiàn)View并沒(méi)有提供任何給我們?cè)O(shè)置樣式的方法。

其實(shí)樣式就是通過(guò)一種方式給一個(gè)View或一組View設(shè)置一些共同的屬性值,所以不可能能使用代碼來(lái)設(shè)置。

我們可以看下progressBarStyleHorizontal樣式中給View設(shè)置了哪些屬性,我們找到framework下的res目錄下的values/Theme.xml文件,搜索progressBarStyleHorizontal會(huì)發(fā)現(xiàn)如下行:

<item name="progressBarStyleHorizontal">@android:style/Widget.ProgressBar.Horizontal</item>

該主題對(duì)應(yīng)的Widget樣式是Widget.ProgressBar.Horizontal,我們?cè)谕瑯拥牡哪夸浵麓蜷_(kāi)style.xml文件,搜索該樣式,可以找到如下代碼:

<style name="Widget.ProgressBar.Horizontal">

    <item name="android:indeterminateOnly">false</item> 

    <item name="android:progressDrawable">@android:drawable/progress_horizontal</item> 

    <item name="android:indeterminateDrawable">@android:drawable/progress_indeterminate_horizontal</item> 

    <item name="android:minHeight">20dip</item> 

    <item name="android:maxHeight">20dip</item> 

</style> 

也就是progressBarStyleHorizontal樣式實(shí)際上就是設(shè)置了如上的屬性,我們直接在布局文件中把如上的值設(shè)進(jìn)去,代碼看起來(lái)如下:

<ProgressBar android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:indeterminateOnly="false"

android:progressDrawable="@android:drawable/progress_horizontal"

android:indeterminateDrawable="@android:drawable/progress_indeterminate_horizontal"

android:minHeight="20dip"

android:maxHeight="20dip" />

這時(shí)運(yùn)行我們的程序,發(fā)現(xiàn)ProgressBar已從圈圈變成進(jìn)度條的樣式。這時(shí)我們可以在代碼中把這些屬性設(shè)成布局文件中的值,純Java代碼看起來(lái)應(yīng)該如下面的那樣:

ProgressBar progressBar = new ProgressBar(this);

    progressBar.setIndeterminate(false); 

    progressBar.setProgressDrawable(getResources().getDrawable(android.R.drawable.progress_horizontal)); 

    progressBar.setIndeterminateDrawable(getResources().getDrawable(android.R.drawable.progress_indeterminate_horizontal)); 

    progressBar.setMinimumHeight(20); 



    LinearLayout layout = new LinearLayout(this); 

    layout.addView(progressBar, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); 

    setContentView(layout); 

這時(shí)我們發(fā)現(xiàn)ProgressBar確實(shí)變成了橫條,但并沒(méi)有顯示成進(jìn)度條的樣子,我們仔細(xì)對(duì)比一下純Java代碼和xml布局文件之間差異,我們發(fā)現(xiàn) android:indeterminateOnly="false"和 progressBar.setIndeterminate(false);并不完全一樣布局文件的屬性有一個(gè)Only結(jié)尾但代碼中并沒(méi)有,我們查找Api發(fā)現(xiàn)并沒(méi)有setIndeterminateOnly這樣的一個(gè)方法。

我們打開(kāi)ProgressBar的源代碼,找到.setIndeterminate(false) 方法,方法的代碼如下:

public synchronized void setIndeterminate(boolean indeterminate) {

    if ((!mOnlyIndeterminate || !mIndeterminate) && indeterminate != mIndeterminate) { 

        mIndeterminate = indeterminate; 



        if (indeterminate) { 

            // swap between indeterminate and regular backgrounds 

            mCurrentDrawable = mIndeterminateDrawable; 

            startAnimation(); 

        } else { 

            mCurrentDrawable = mProgressDrawable; 

            stopAnimation(); 

        } 

    } 

} 

我們這時(shí)候可以發(fā)現(xiàn)Indeterminate和IndeterminateOnly并不是同一個(gè)東西,這時(shí)我們應(yīng)該想的到,只要我們把 IndeterminateOnly的值變成false就可以使ProgressBar變成進(jìn)度條的樣式,我們查找所有的代碼,發(fā)現(xiàn)并沒(méi)有提供相應(yīng)的公開(kāi)方法來(lái)修改該屬性的值。

也就是說(shuō),我們討論了那么久發(fā)現(xiàn)根本就無(wú)法通過(guò)純代碼的形式來(lái)創(chuàng)建一個(gè)進(jìn)度條樣式的ProgressBar.

但是。。。

不就是改變一個(gè)類(lèi)的私有變量的值嘛,Java的封裝性其實(shí)并沒(méi)有我想的那么好,我們完全可以通過(guò)反射機(jī)制來(lái)修改一個(gè)對(duì)象的私有變量的值,由于該文章并不是討論反射的的文章,所以這里只給出通過(guò)反射來(lái)修改私有變量值的代碼,但并不作詳細(xì)的說(shuō)明:

我們創(chuàng)建一個(gè)新的類(lèi),叫BeanUtils.java

類(lèi)得內(nèi)容看其來(lái)如下:

public class BeanUtils {

private BeanUtils() { 

} 





/** 

 * 直接設(shè)置對(duì)象屬性值,無(wú)視private/protected修飾符,不經(jīng)過(guò)setter函數(shù). 

 */ 

public static void setFieldValue(final Object object, final String fieldName, final Object value) { 

    Field field = getDeclaredField(object, fieldName); 



    if (field == null) 

        throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]"); 



    makeAccessible(field); 



    try { 

        field.set(object, value); 

    } catch (IllegalAccessException e) { 

    Log.e("zbkc", "", e); 

    } 

} 



/** 

 * 循環(huán)向上轉(zhuǎn)型,獲取對(duì)象的DeclaredField. 

 */ 

protected static Field getDeclaredField(final Object object, final String fieldName) { 

    return getDeclaredField(object.getClass(), fieldName); 

} 



/** 

 * 循環(huán)向上轉(zhuǎn)型,獲取類(lèi)的DeclaredField. 

 */ 

@SuppressWarnings("unchecked") 

protected static Field getDeclaredField(final Class clazz, final String fieldName) { 

    for (Class superClass = clazz; superClass != Object.class; superClass = superClass.getSuperclass()) { 

        try { 

            return superClass.getDeclaredField(fieldName); 

        } catch (NoSuchFieldException e) { 

            // Field不在當(dāng)前類(lèi)定義,繼續(xù)向上轉(zhuǎn)型 

        } 

    } 

    return null; 

} 



/** 

 * 強(qiáng)制轉(zhuǎn)換fileld可訪問(wèn). 

 */ 

protected static void makeAccessible(Field field) { 

    if (!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())) { 

        field.setAccessible(true); 

    } 

} 

}

該工具提供一個(gè)共有的方法:public static void setFieldValue(final Object object, final String fieldName, final Object value)來(lái)修改一個(gè)對(duì)象的私有變量的值:

這時(shí)我們的ProgressBar代碼看起來(lái)應(yīng)該如下:

ProgressBar progressBar = new ProgressBar(this);

    BeanUtils.setFieldValue(progressBar, "mIndeterminateOnly", new Boolean(false)); 

    progressBar.setIndeterminate(false); 

    progressBar.setProgressDrawable(getResources().getDrawable(android.R.drawable.progress_horizontal)); 

    progressBar.setIndeterminateDrawable(getResources().getDrawable(android.R.drawable.progress_indeterminate_horizontal)); 

    progressBar.setMinimumHeight(20); 





    LinearLayout layout = new LinearLayout(this); 

    layout.addView(progressBar, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); 

    setContentView(layout); 

到此為止我們終于使用純java代碼的方式創(chuàng)建了一個(gè)ProgressBar的進(jìn)度條樣式。

ProcessBar的使用:

public class ProcessActivity extends Activity { private ProgressBar psb_sec; private Button btn_process; private static final int PSB_MAX = 100; private static int process; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); psb_sec = (ProgressBar) findViewById(R.id.psb_sec); psb_sec.setMax(100); btn_process = (Button) findViewById(R.id.btn_process); btn_process.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if(process < PSB_MAX){ psb_sec.setProgress(process); process += PSB_MAX/10; psb_sec.setSecondaryProgress(process); return; } psb_sec.setVisibility(View.INVISIBLE); } }); }}

分享到:

Handler對(duì)象的Message應(yīng)用 | android中的守護(hù)線程

2011-05-28 10:02
瀏覽 5553
評(píng)論(0)
分類(lèi):移動(dòng)開(kāi)發(fā)
相關(guān)推薦

參考知識(shí)庫(kù)


Android知識(shí)庫(kù) 34785 關(guān)注 | 3135 收錄

評(píng)論

發(fā)表評(píng)論

您還沒(méi)有登錄,請(qǐng)您登錄后再發(fā)表評(píng)論


尋夢(mèng)者

瀏覽: 426101 次
性別: [圖片上傳中。。。(6)]
來(lái)自: 杭州


最近訪客 更多訪客>>


en24414115


formoney


心_晴


furmint

文章分類(lèi)
全部博客 (290)
javaBase (29)
design pattern (3)
javaWeb (4)
android (214)
IDE (4)
linux (10)
jsp (0)
ext (2)
生活 (1)

社區(qū)版塊
我的資訊 (0)
我的論壇 (0)
我的問(wèn)答 (0)

存檔分類(lèi)
2013-02 (1)
2012-11 (7)
2012-10 (5)
更多存檔...

最新評(píng)論
luo_ganlin: 別的不多說(shuō),點(diǎn)個(gè)贊!關(guān)于Android隱式啟動(dòng)Activity
IWSo: 謝樓主!研究了好久,原來(lái)是這樣!android中如何讓LinearLayout實(shí)現(xiàn)點(diǎn)擊時(shí)背景圖片切換
fantao005x: 粘帖的不錯(cuò)android中如何讓listview的內(nèi)容全部顯示出來(lái)
learner576539763: Android_gqs 寫(xiě)道請(qǐng)問(wèn)博主,Viewstub 可實(shí)現(xiàn) ...android中ViewStub使用
goontosoon: 抄的什么啊,狗屁不通對(duì)ContentProvider中g(shù)etType(Uri uri)

聲明:ITeye文章版權(quán)屬于作者,受法律保護(hù)。沒(méi)有作者書(shū)面許可不得轉(zhuǎn)載。若作者同意轉(zhuǎn)載,必須以超鏈接形式標(biāo)明文章原始出處和作者。? 2003-2017 ITeye.com. All rights reserved. [ 京ICP證110151號(hào) 京公網(wǎng)安備110105010620 ]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容