Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 主題資源風格定制 (1)

Android 主題資源風格定制 (1)

編輯:關於Android編程

無論是定制系統還是自行開發APP的UI,其無論是使用標准UI還是自定義UI,最終都是需要自己熟悉主題風格的各種屬性設置,不過屬性非常的多,如果需要知道某個UI可以臨時查看一下SDK的 

D:\liuzhibao\Android\sdk\platforms\android-N\data\res路徑下的,但是這個是純粹的資源文件,沒有java文件,所以還是推薦repo下來framework/base代碼.

下面先看看自定義View如何添加屬性之類的:

新建一個PumpKinCustomeView的android studio工程:

主類程序:

package org.durian.pumpkincustomeview;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class PumpKinMainActivity extends AppCompatActivity {

    private Button mButton;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pump_kin_main);

        mButton=(Button)findViewById(R.id.button);
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(PumpKinMainActivity.this,ThemeActivity.class);
                PumpKinMainActivity.this.startActivity(intent);
                finish();
            }
        });

    }

}

既然要自定義View,那麼就需要新建一個atts.xml文件到res/values下,下面隨便舉幾個:





    
    
    
    
    
    
    
    
    
    
    
    



上面基本上一看還是非常清楚的,上面只缺少flag位運算format,fraction為百分比,reference為引用,enum可以如下:



    1
    2
    3


定義好上面的屬性後,新建一個UIView的繼承View的類:

package org.durian.pumpkincustomeview.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;

import org.durian.pumpkincustomeview.R;

/**
 * Project name : PumpKinCustomeView
 * Created by zhibao.liu on 2016/4/28.
 * Time : 10:32
 * Email warden_sprite@foxmail.com
 * Action : durian
 */
public class UIView extends View {

    private Paint mPaint;
    private Paint mTextPaint;

    private int rectWidth;
    private int rectHeight;

    public UIView(Context context) {
        super(context);
    }

    public UIView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context);
        TypedArray typedArray=context.obtainStyledAttributes(attrs, R.styleable.UIView);

        int textSize=typedArray.getInteger(R.styleable.UIView_pumpkin_textsize,128);
        int textColor=typedArray.getColor(R.styleable.UIView_pumpkin_textcolor, Color.GRAY);

        mTextPaint.setColor(textColor);
        mTextPaint.setStrokeWidth(2);
        mTextPaint.setTextSize(textSize);

        int backgroundColor=typedArray.getColor(R.styleable.UIView_pumpkin_background,Color.GRAY);
        rectWidth=(int)typedArray.getDimension(R.styleable.UIView_pumpkin_view_width,512);
        rectHeight=(int)typedArray.getDimension(R.styleable.UIView_pumpkin_view_height,513);
        rectWidth=Utils.px2dip(context,rectWidth);
        rectHeight=Utils.px2dip(context,rectHeight);
        //rectHeight=Utils.dip2px(context,rectHeight);
        mPaint.setColor(backgroundColor);
        android.util.Log.i("UIVIEW","rectWidth : "+rectWidth+" rectHeight : "+rectHeight);

    }

    public void initView(Context context){
        mPaint=new Paint();
        mTextPaint=new Paint();
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);

        canvas.drawRect(new Rect(10,10,rectWidth,rectHeight),mPaint);

        canvas.drawText("hello view",50,800,mTextPaint);

    }


}

然後在工程主Activity的布局中添加這個自定義View.在添加之前,先為這個View寫一個自定義style:


然後添加到主Activity的布局中:




    


注意:

這裡故意分開一部分直接寫在布局中,有一部分屬性賦值封裝到PumKin_style,但是直接寫到布局中需要注意比如(pumpkin:pumpkin_textsize):

在布局頭部需要標記路徑:現在android studio可以直接res-auto,以前需要換成res/報名

xmlns:pumpkin=http://schemas.android.com/apk/res-auto

在自定義UIView中注意:

rectWidth=Utils.px2dip(context,rectWidth);
        rectHeight=Utils.px2dip(context,rectHeight);

注意: 我們在風格中明明寫著是500,但是如果沒有上面兩句程序,RectWidth的值將是1500,也就是這個地方設置的500dp(預想這樣),但是打印log出來將是1500px,結果整個屏幕的方形將非常的大,也不是我們所需要的,所以獲取尺寸以後需要轉一下從px轉到pd單位,所以這個地方需要特別注意.字體也存在這個轉換,但是上面程序沒有在給出了,轉換一般如下:

package org.durian.pumpkincustomeview.view;

import android.content.Context;

/**
 * Project name : PumpKinCustomeView
 * Created by zhibao.liu on 2016/4/28.
 * Time : 14:42
 * Email warden_sprite@foxmail.com
 * Action : durian
 */
public class Utils {

    public static int dip2px(Context context, float dipValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }

    public static int px2dip(Context context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

}


運行結果:

\
 

下面來看看如果是系統UI的屬性如何修改:下面android5.0來簡說,

加入我的Activity有CheckBox和EditText,我希望這個Activity中所有的CheckBox都是一致的,所有的EditText風格也是一致的,如何處理呢?

系統資源設計有幾個基本原則和規律:

<1> : 具有繼承性:如

<1>

使用parent關鍵字,繼承parent的所有屬性值.

<2> : 子類屬性覆蓋父類屬性值:即在雖然在父類對某個屬性賦值了,但是子類希望在這個屬性值上面不同於父類,那麼就在子類重新對改屬性值賦值,如下:

<2>

 


 

屬性colorPrimary在父類AppTheme中已經賦了值,但還是我希望自己的Activity的titlebar的顏色是紅色,那麼在這裡就重新賦值,達到覆蓋父類那個屬性值的目的.

<3> : 回答最上面那個問題,如果需要調整一個頁面內所以某個UI的風格,那麼就需要重新將UI的風格重新寫,但是一般推薦繼承父類,只調整需要調整的部分,其他的仍然采用父類的屬性,這樣就不要從零開始寫了:

<3>

將頁面的EditText和CheckBox的幾個屬性重新調整.

在新建一個Activity測試一下:

package org.durian.pumpkincustomeview;

import android.content.Intent;
import android.content.res.Resources;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class ThemeActivity extends AppCompatActivity {

    private Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_theme);

        button=(Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(ThemeActivity.this,CompareThemeActivity.class);
                ThemeActivity.this.startActivity(intent);
            }
        });

    }

}

manifest.xml添加自定義主題給它:


對應的布局:




    

    

    


運行結果:

\

 

發現顏色有54%透明度的黑色變為指定的顏色了.

有讀者可能又會問題,如何知道EditText等的屬性風格,比如

這個地方記住順序:

打開android源代碼,查看EditText.java源代碼:

public EditText(Context context, AttributeSet attrs) {
        this(context, attrs, com.android.internal.R.attr.editTextStyle);
    }

看到了吧,這就是為什麼前面要自己先寫一個自定義的UIView,回顧一下這些主題風格是如何被UI使用的,看到上面的editTextStyle,然後搜索:

 

        @style/Widget.Material.EditText
我的是android5.0的代碼,所以帶有material.
\
同時搜索的時候一定要注意,這個搜索的關鍵字一定要出現在Public.xml中,因為android系統後面的資源需要聲明,如果聲明在Public.xml中才能夠被APP developer使用,即公共的,如果是在symbol.xml,那就算是系統內部自己使用,即私有的.很顯然我們這裡是需要在APP中使用,所以一定是需要公有的才行.在自己APP程序重新再寫這些屬性值即可覆蓋framework中預設的.

 

假如自己的UI的一些屬性在系統中聲明為私有的,怎麼辦,最粗暴的做法就是直接將系統中的風格和資源文件全部挑選出來放到自己的APP資源下,單個UI的話並不是很難.

假設,這裡只是個假設SeekBar 這個ui風格是私有的,那麼步驟如下:

<1> : 查看SeekBar.java這個類:

<1>
public SeekBar(Context context, AttributeSet attrs) {
        this(context, attrs, com.android.internal.R.attr.seekBarStyle);
    }

繼續看seekBarStyle風格:

@style/Widget.Material.SeekBar

找到"定義處":

其實一般改的並不多,一般是修改SeekBar的進度線的風格(粗細,顏色等)以及游標圖案或者顏色,將上面的copy到自己的工程

假如修改背景顏色,那麼就還需要提取這個資源:

@drawable/control_background_32dp_material

這個想都不用想,絕對是個xml文件:





一看,control_highlight_material還是一個xml:





    
    

也需要提取出來.繼續查找顏色:

        ?attr/colorAccent

一看colorAccent這個顏色值,這個顏色值很瘋狂的,是一個全局的,比如你在自己的APP主題中設置:

 

#fff4e80b

 

你會發現你的所有UI都變色了,而不是一個.

繼續查看另外一個顏色colorCotrolHighlight:

@color/ripple_material_dark

這個顏色值也是一個xml:





    

再來看看foreground_material_dark,最終是

@color/white

即白色前景.

了解上面的流程,如果參考系統的UI就可以拷貝出來自行調整各自的值.

 

當然上面都是調整APP部分的屬性,如果是定制系統,那麼就可以在vendor/overlay/framework中自行開發,這樣整個系統都有了,但是一般這樣的都要拷貝系統原生的,如果希望自己定制的系統中運行的第三方app也跟著調整,也可以直接改原生的主題風格,將原生的代碼改掉,當然一般不推薦.


後面一篇可以看看系統基本UI都是誰演化而來:

 

Button extends TextView 
TextView extends View 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved