我有我自己的風格定義爲主題的按鈕,但我也用我自己的類來處理按鈕(因爲自己的字體)。是否可以叫我的按鈕,一個漂亮的名字,如使用自定義視圖,而無需使用完全合格的類名
<MyButton>
代替
<com.wehavelongdomainname.android.ui.MyButton>
我有我自己的風格定義爲主題的按鈕,但我也用我自己的類來處理按鈕(因爲自己的字體)。是否可以叫我的按鈕,一個漂亮的名字,如使用自定義視圖,而無需使用完全合格的類名
<MyButton>
代替
<com.wehavelongdomainname.android.ui.MyButton>
所以答案,令人驚訝的,是 「是」。筆者近日瞭解到這一點,它實際上是東西,你可以做,使您的自定義視圖通脹更有效。的IntelliJ仍警告你,它的無效(儘管它會編譯併成功運行) - 我不知道是否Eclipse的警告你與否。
無論如何,所以你需要做的就是定義自己的LayoutInflater.Factory
子類:
public class CustomViewFactory implements LayoutInflater.Factory {
private static CustomViewFactory mInstance;
public static CustomViewFactory getInstance() {
if (mInstance == null) {
mInstance = new CustomViewFactory();
}
return mInstance;
}
private CustomViewFactory() {}
@Override
public View onCreateView (String name, Context context, AttributeSet attrs) {
//Check if it's one of our custom classes, if so, return one using
//the Context/AttributeSet constructor
if (MyCustomView.class.getSimpleName().equals(name)) {
return new MyCustomView(context, attrs);
}
//Not one of ours; let the system handle it
return null;
}
}
然後,在任何活動或情境中,你會膨脹包含這些自定義視圖的佈局,你需要你的工廠分配給LayoutInflater
爲背景:
public class CustomViewActivity extends Activity {
public void onCreate (Bundle savedInstanceState) {
//Get the LayoutInflater for this Activity context
//and set the Factory to be our custom view factory
LayoutInflater.from(this).setFactory(CustomViewFactory.getInstance());
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_with_custom_view);
}
}
然後你可以在你的XML使用簡單的類名稱:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<MyCustomView
android:id="@+id/my_view"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_gravity="center_vertical" />
</FrameLayout>
你也可以這樣做:
<view
class="com.wehavelongdomainname.android.ui.MyButton"
... />
比照http://developer.android.com/guide/topics/ui/custom-components.html#modifying
定義自己的LayoutInflater.Factory的子類,似乎很多工作我的。 只需使用一些通用的代碼重寫活動的onCreateView():
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
View view;
// No need wasting microseconds getting the inflater every time.
// This method gets called a great many times.
// Better still define these instance variables in onCreate()
if (mInflator == null){
mInflator = LayoutInflater.from(context);
mPrefix = ((Activity) context).getComponentName().getClassName();
// Take off the package name including the last period
// and look for custom views in the same directory.
mPrefix = mPrefix.substring(0, mPrefix.lastIndexOf(".")+1);
}
// Don't bother if 'a path' is already specified.
if (name.indexOf('.') > -1) return null;
try{
view = mInflator.createView(name, mPrefix, attrs);
} catch (ClassNotFoundException e) {
view = null;
} catch (InflateException e) {
view = null;
}
// Returning null is no big deal. The super class will continue the inflation.
return view;
}
注意自定義視圖必須駐留在同一個包(即在同一目錄)作爲本次活動,但當時它只是一個普通的一段代碼你可以在任何活動中打耳光(甚至更好,從自定義的父活動類繼承)。 你不擔心在由kcoppock提供的解決方案中指定尋找出某一類:
if (MyCustomView.class.getSimpleName().equals(name)) {....
你肯定不是創建一個全新的類。
真正神奇的是在覈心庫類,LayoutInflator.java。看到通話,mPrivateFactory.onCreateView(),下面?:
if (view == null && mPrivateFactory != null) {
view = mPrivateFactory.onCreateView(parent, name, mContext, attrs);
}
if (view == null) {
if (-1 == name.indexOf('.')) {
view = onCreateView(parent, name, attrs);
} else {
view = createView(name, null, attrs);
}
}
你看,如果所謂的,mPrivateFactory,返回null(mPrivateFactory恰好是由這樣你的活動類),該LayoutInflator剛剛進行與它的其他替代方法,並繼續通貨膨脹:
if (view == null) {
if (-1 == name.indexOf('.')) {
view = onCreateView(parent, name, attrs);
} else {
view = createView(name, null, attrs);
}
}
這是圖書館類與IDE調試器「穿行」,真正看到Android的作品是一個好主意。:)
請注意,代碼if (-1 == name.indexOf('.')) {
適用於仍然堅持使用自定義視圖的完整路徑<com.wehavelongdomainname.android.ui.MyButton>
如果名稱中有一個「點」,則creatview()將與前綴(第二個參數)爲空:view = createView(name, null, attrs);
爲什麼我使用這種方法是因爲我發現在初始開發過程中,有些時候程序包名稱被移動(即更改)。但是,與java代碼本身內執行的程序包名稱更改不同,編譯器不會捕獲任何XML文件中現在存在的此類更改和差異。使用這種方法,現在不需要。
乾杯。
Eclipse告訴我沒有LayoutInflater.Factory – Ragnar
@Ragnar自從API 1(http://developer.android.com/reference/android/view/LayoutInflater.Factory.html)以來就一直存在。你爲它添加了適當的導入嗎? – kcoppock
發現了它,我只是不得不進口android.view.LayoutInflater – Ragnar