<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Android可更換布局的換膚方案

      換膚,顧名思義,就是對應用中的視覺元素進行更新,呈現(xiàn)新的顯示效果。一般來說,換膚的時候只是更新UI上使用的資源,如顏色,圖片,字體等等。本文介紹一種筆者自己使用的基于布局的Android換膚方案,不僅可以更換所有的UI資源,而且可以更換主題樣式(style)和布局樣式。代碼已托管到github:SkinFramework

      換膚當然得有相應的皮膚包,不管是內(nèi)置在應用內(nèi),還是做成可安裝的皮膚應用包。但是這兩種都有弊端:

      1.內(nèi)置在應用內(nèi)會增加應用包的體積。

      2.皮膚安裝包需要安裝過程,會占用更多的設備內(nèi)置存儲,用戶會介意安裝過多應用。而且為了是應用能夠訪問安裝包內(nèi)的資源,必須與應用使用相同的shareUserId。

      鑒于此,本文推薦使用無需安裝的外置皮膚包,優(yōu)點在于:

      1.無需安裝,也無關乎shareUserId,不會引起用戶反感。

      2.按需下載使用,用戶需要使用時自行下載,下載即可使用。

      3.可放置于任何可訪問的位置,SD卡或內(nèi)置存儲,可隨時刪除和添加,不會增加應用體積。

      先來看一下效果圖:

      可以看到,圖中有三種皮膚,默認皮膚,plain皮膚和vivid皮膚,都是更換了布局和資源的,其中還使用了AdapterView和Fragment作測試。可以看到,不同的皮膚有不同的布局樣式,布局樣式的不同也帶來了很多可能,如隱藏或移動了功能入口。

      所以說這是一個有很多可能的換膚框架,下面介紹一下核心 實現(xiàn)。

      一、皮膚包

      皮膚包就是一個不包含代碼文件的Apk包,無需安裝,可以新建工程,刪除掉代碼文件,復制應用里面需要修改的資源到新工程中修改,打成新包即可作為皮膚包使用,皮膚包后綴名可以改為任意。示例中使用了.skin作為后綴名。

       

      二、皮膚包加載

      皮膚包中包含的資源文件,需要加載到AssetManager中并創(chuàng)建Resources才能提供使用,關于Android的資源管理機制書上或網(wǎng)上已經(jīng)有很多介紹,可以參考:Android中資源管理機制詳細分析。所以我們的第一件事也是來加載皮膚包:

       AssetManager assetManager = AssetManager.class.newInstance();
              Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
              //Return 0 on failure.
              Object ret = addAssetPath.invoke(assetManager, skinPath);
              if (Integer.parseInt(ret.toString()) == 0) {
                  throw new IllegalStateException("Add asset fail");
              }
              Resources localRes = context.getResources();
              return new SkinResource(context, assetManager, localRes.getDisplayMetrics(), localRes.getConfiguration(), packageName);

       

      三、資源管理器

      加載了皮膚包,我們就有了兩套可共使用的皮膚資源,應用默認資源和皮膚包資源,何時使用默認,何時使用皮膚,需要有一個管理器來決定,所以我們實現(xiàn)一個名為ComposedResources的類來扮演ResourcesManager:

      /**
       * Created by ARES on 2016/5/20
       * This is a resources class consists of App default skin and external skin resources if exists. We will find resource in external skin resources first,then the default.
       * Assume all resources ids are original  so that we should find corresponding resources ids in skin .
       */
      
      public class ComposedResources extends BaseResources {
          static int LAYOUT_TAG_ID = -1;
          private Context mContext;
          private BaseSkinResources mSkinResources;
      
          public ComposedResources(Context context) {
              this(context, null);
          }
      
          public ComposedResources(Context context, BaseSkinResources skinResources) {
              super(context.getResources());
              mContext = context;
              mSkinResources = skinResources;
          }
      
      
          public ComposedResources setSkinResources(BaseSkinResources resources) {
              mSkinResources = resources;
              return this;
          }
      
          public BaseSkinResources getSkinResources() {
              return mSkinResources;
          }
      
          @NonNull
          @Override
          public CharSequence getText(@StringRes int id) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  try {
                      return mSkinResources.getText(realId);
                  } catch (Exception e) {
                  }
              }
              return super.getText(id);
          }
      
          @NonNull
          @Override
          public CharSequence getQuantityText(@PluralsRes int id, int quantity) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getQuantityText(realId, quantity);
              }
              return super.getQuantityText(id, quantity);
          }
      
          @NonNull
          @Override
          public String getQuantityString(@PluralsRes int id, int quantity, Object... formatArgs) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getQuantityString(realId, quantity, formatArgs);
              }
              return super.getQuantityString(id, quantity, formatArgs);
          }
      
          @NonNull
          @Override
          public String getQuantityString(@PluralsRes int id, int quantity) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getQuantityString(realId, quantity);
              }
              return super.getQuantityString(id, quantity);
          }
      
          @Override
          public CharSequence getText(@StringRes int id, CharSequence def) {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getText(realId, def);
              }
              return super.getText(id, def);
          }
      
          @NonNull
          @Override
          public CharSequence[] getTextArray(@ArrayRes int id) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getTextArray(id);
              }
              return super.getTextArray(id);
          }
      
          @NonNull
          @Override
          public String[] getStringArray(@ArrayRes int id) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getStringArray(realId);
              }
              return super.getStringArray(id);
          }
      
          @NonNull
          @Override
          public int[] getIntArray(@ArrayRes int id) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getIntArray(realId);
              }
              return super.getIntArray(id);
          }
      
          @NonNull
          @Override
          public TypedArray obtainTypedArray(@ArrayRes int id) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.obtainTypedArray(realId);
              }
              return super.obtainTypedArray(id);
          }
      
          @Override
          public float getDimension(@DimenRes int id) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getDimension(realId);
              }
              return super.getDimension(id);
          }
      
          @Override
          public int getDimensionPixelOffset(@DimenRes int id) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getDimensionPixelOffset(realId);
              }
              return super.getDimensionPixelOffset(id);
          }
      
          @Override
          public int getDimensionPixelSize(@DimenRes int id) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getDimensionPixelSize(realId);
              }
              return super.getDimensionPixelSize(id);
          }
      
          @Override
          public float getFraction(@FractionRes int id, int base, int pbase) {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getFraction(id, base, pbase);
              }
              return super.getFraction(id, base, pbase);
          }
      
          @Override
          public Drawable getDrawable(@DrawableRes int id) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getDrawable(realId);
              }
              return super.getDrawable(id);
          }
      
          @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
          @Override
          public Drawable getDrawable(@DrawableRes int id, @Nullable Theme theme) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getDrawable(realId, theme);
              }
              return super.getDrawable(id, theme);
          }
      
          @Override
          public Drawable getDrawableForDensity(@DrawableRes int id, int density) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getDrawableForDensity(realId, density);
              }
              return super.getDrawableForDensity(id, density);
          }
      
          @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
          @Override
          public Drawable getDrawableForDensity(@DrawableRes int id, int density, @Nullable Theme theme) {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getDrawableForDensity(realId, density, theme);
              }
              return super.getDrawableForDensity(id, density, theme);
          }
      
          @Override
          public Movie getMovie(@RawRes int id) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getMovie(realId);
              }
              return super.getMovie(id);
          }
      
          @Override
          public int getColor(@ColorRes int id) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getColor(realId);
              }
              return super.getColor(id);
          }
      
          @RequiresApi(api = Build.VERSION_CODES.M)
          @Override
          public int getColor(@ColorRes int id, @Nullable Theme theme) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getColor(realId, theme);
              }
              return super.getColor(id, theme);
          }
      
          @Nullable
          @Override
          public ColorStateList getColorStateList(@ColorRes int id) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getColorStateList(realId);
              }
              return super.getColorStateList(id);
          }
      
          @RequiresApi(api = Build.VERSION_CODES.M)
          @Nullable
          @Override
          public ColorStateList getColorStateList(@ColorRes int id, @Nullable Theme theme) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getColorStateList(realId, theme);
              }
              return super.getColorStateList(id, theme);
          }
      
          @Override
          public boolean getBoolean(@BoolRes int id) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getBoolean(realId);
              }
              return super.getBoolean(id);
          }
      
          @Override
          public int getInteger(@IntegerRes int id) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.getInteger(realId);
              }
              return super.getInteger(id);
          }
      
          @Override
          public XmlResourceParser getLayout(@LayoutRes int id) throws NotFoundException {
              int realId = getCorrespondResIdStrictly(id);
              if (realId > 0) {
                  return mSkinResources.getLayout(realId);
              }
              return super.getLayout(id);
          }
      
          @Override
          public XmlResourceParser getAnimation(@AnimRes int id) throws NotFoundException {
              int realId = getCorrespondResIdStrictly(id);
              if (realId > 0) {
                  return mSkinResources.getAnimation(realId);
              }
              return super.getAnimation(id);
          }
      
          @Override
          public XmlResourceParser getXml(@XmlRes int id) throws NotFoundException {
              int realId = getCorrespondResIdStrictly(id);
              if (realId > 0) {
                  return mSkinResources.getXml(realId);
              }
              return super.getXml(id);
          }
      
          @Override
          public InputStream openRawResource(@RawRes int id) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.openRawResource(realId);
              }
              return super.openRawResource(id);
          }
      
          @Override
          public InputStream openRawResource(@RawRes int id, TypedValue value) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.openRawResource(realId, value);
              }
              return super.openRawResource(id, value);
          }
      
          @Override
          public AssetFileDescriptor openRawResourceFd(@RawRes int id) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  return mSkinResources.openRawResourceFd(realId);
              }
              return super.openRawResourceFd(id);
          }
      
          @Override
          public void getValue(@AnyRes int id, TypedValue outValue, boolean resolveRefs) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  mSkinResources.getValue(realId, outValue, resolveRefs);
                  return;
              }
              super.getValue(id, outValue, resolveRefs);
          }
      
          @Override
          public void getValueForDensity(@AnyRes int id, int density, TypedValue outValue, boolean resolveRefs) throws NotFoundException {
              int realId = getCorrespondResId(id);
              if (realId > 0) {
                  mSkinResources.getValueForDensity(realId, density, outValue, resolveRefs);
                  return;
              }
              super.getValueForDensity(id, density, outValue, resolveRefs);
          }
      
          @Override
          public void getValue(String name, TypedValue outValue, boolean resolveRefs) throws NotFoundException {
              if (mSkinResources != null) {
                  try {
                      mSkinResources.getValue(name, outValue, resolveRefs);
                      return;
                  } catch (Exception e) {
                  }
              }
              super.getValue(name, outValue, resolveRefs);
          }
      
          @Override
          public void updateConfiguration(Configuration config, DisplayMetrics metrics) {
              if (mSkinResources != null) {
                  mSkinResources.updateConfiguration(config, metrics);
              }
              super.updateConfiguration(config, metrics);
          }
      
          /**
           * Get correspond resources id with  app package. See also {@link #getCorrespondResId(int)}
           *
           * @param resId
           * @return 0 if not exist
           */
          public int getCorrespondResIdStrictly(int resId) {
              if (mSkinResources == null) {
                  return 0;
              }
              String resName = getResourceName(resId);
              return mSkinResources.getIdentifier(resName, null, null);
          }
      
          /**
           * Get correspond resources id with skin package. See also {@link #getCorrespondResId(int)}
           *
           * @param resId
           * @return
           */
          public int getCorrespondResId(int resId) {
              if (mSkinResources == null) {
                  return 0;
              }
              return mSkinResources.getCorrespondResId(resId);
          }
      
      
          @Override
          public View getView(Context context, @LayoutRes int resId) {
              //Take a resource id as the tag key.
              if (LAYOUT_TAG_ID < 1) {
                  LAYOUT_TAG_ID = resId;
              }
              View view;
              if (mSkinResources != null) {
                  int realId = getCorrespondResId(resId);
                  if (realId > 0) {
                      view = mSkinResources.getView(context, realId);
                      if (view != null) {
                          view.setTag(LAYOUT_TAG_ID, mSkinResources.getPackageName());
                          SkinUtils.showIds(view);
                          return view;
                      }
                  }
              }
              view = LayoutInflater.from(context).inflate(resId, null);
              view.setTag(LAYOUT_TAG_ID, getPackageName());
              SkinUtils.showIds(view);
              return view;
          }
      
          @Override
          public String getPackageName() {
              return mContext.getPackageName();
          }
      }

       

      可以看到這個ResourceManager本身也是一個Resources,它繼承自BaseResources,BaseResources繼承自android.content.res.Resources。所以它可以直接作為應用的Resources來使用。其中有幾點需要注意:

      1.查找資源時,資源管理器應優(yōu)先查找皮膚包中的資源,若皮膚包中沒有相應資源,才使用應用默認資源。

      2.每個應用包中的資源id是不同的,查找資源時,我們傳入Resources的id都是應用中的id,而非皮膚包中的id,所以我們需要轉(zhuǎn)換為皮膚包中相應的資源id,再獲取具體的資源(此代碼實現(xiàn)在SkinResources中,ComposedResources調(diào)用了此方法):

         /**
           * Get correspond resource id in skin archive.
           * @param resId Resource id in app.
           * @return 0 if not exist
           */
          public int getCorrespondResId(int resId) {
              Resources appResources = getAppResources();
              String resName = appResources.getResourceName(resId);
              if (!TextUtils.isEmpty(resName)) {
                  String skinName = resName.replace(mAppPackageName, getPackageName());
                  int id = getIdentifier(skinName, null, null);
                  return id;
              }
              return 0;
          }

       

      3.在獲取XmlResourceParser時,需要使用應用對于資源的描述,而非皮膚包中的資源描述,所以有了getCorrespondResIdStrictly:

        /**
           * Get correspond resources id with  app package. See also {@link #getCorrespondResId(int)}
           *
           * @param resId
           * @return 0 if not exist
           */
          public int getCorrespondResIdStrictly(int resId) {
              if (mSkinResources == null) {
                  return 0;
              }
              String resName = getResourceName(resId);
              return mSkinResources.getIdentifier(resName, null, null);
          }

       

      4.我們使用了LAYOUT_TAG_ID來記錄了Layout所屬的皮膚包,以便可以動態(tài)的判斷是否需要更換布局(此方法可以用在動態(tài)換膚的時候,詳情參考Demo):

       @Override
          public View getView(Context context, @LayoutRes int resId) {
              //Take a resource id as the tag key.
              if (LAYOUT_TAG_ID < 1) {
                  LAYOUT_TAG_ID = resId;
              }
              View view;
              if (mSkinResources != null) {
                  int realId = getCorrespondResId(resId);
                  if (realId > 0) {
                      view = mSkinResources.getView(context, realId);
                      if (view != null) {
                          view.setTag(LAYOUT_TAG_ID, mSkinResources.getPackageName());
                          return view;
                      }
                  }
              }
              view = LayoutInflater.from(context).inflate(resId, null);
              view.setTag(LAYOUT_TAG_ID, getPackageName());
              return view;
          }

       

      四、布局更換處理

      通過上述的代碼,我們就已經(jīng)能夠完成常見資源的換膚了。但是對于布局資源,我們還需要做額外的處理。

      1.Context與LayoutInflater

      渲染View時,我們需要使用皮膚對應的Context和LayoutInflater,這樣才能在View中使用正確的資源,所以我們?yōu)橥庵闷つw包創(chuàng)建相應的Context:

        /**
           * Context implementation for skin package.
           */
          private class SkinThemeContext extends ContextThemeWrapper {
              private WeakReference<Context> mContextRef;
      
              public SkinThemeContext(Context base) {
                  super();
                  if (base instanceof ContextThemeWrapper) {
                      attachBaseContext(((ContextThemeWrapper) base).getBaseContext());
                      mContextRef = new WeakReference<Context>(base);
                  } else {
                      attachBaseContext(base);
                  }
                  int themeRes = getThemeRes();
                  if (themeRes <= 0) {
                      themeRes = android.R.style.Theme_Light;
                  }
                  setTheme(themeRes);
              }
      
              /**
               * This implementation will support <code>onClick</code> attribute of view in xml.
               * @param v
               */
              public void onClick(View v) {
                  Context context = mContextRef == null ? null : mContextRef.get();
                  if (context == null) {
                      return;
                  }
                  if (context instanceof View.OnClickListener) {
                      ((View.OnClickListener) context).onClick(v);
                  } else {
                      Class cls = context.getClass();
                      try {
                          Method m = cls.getDeclaredMethod("onClick", View.class);
                          if (m != null) {
                              m.invoke(context, v);
                          }
                      } catch (NoSuchMethodException e) {
                          e.printStackTrace();
                      } catch (InvocationTargetException e) {
                          e.printStackTrace();
                      } catch (IllegalAccessException e) {
                          e.printStackTrace();
                      }
                  }
              }
      
              @Override
              public AssetManager getAssets() {
                  return getAssets();
              }
      
              @Override
              public Resources getResources() {
                  return SkinResource.this;
              }
      
              private int getThemeRes() {
                  try {
                      Method m = Context.class.getMethod("getThemeResId");
                      return (int) m.invoke(getBaseContext());
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
                  return -1;
              }
      
          }

       

      其中我們對xml布局文件中的onClick屬性作了支持,同時通過提供了皮膚包對應的資源,然后我們使用這個Context的實例創(chuàng)建LayoutInflater并渲染View:

        @Override
          public View getView(Context context, @LayoutRes int resId) {
              try {
                  Context skinContext = new SkinThemeContext(context);
                  View v = LayoutInflater.from(skinContext).inflate(resId, null);
                  handleView(skinContext, v);
                  return v;
              } catch (Exception e) {
      
              }
              return null;
          }

       

      其中注意到handleView方法,正如前文所說,每個應用包生成的資源id是不一樣的,這里View中生成的id是皮膚包中的id,需要轉(zhuǎn)換為應用中的id方可使用:

          /**
           * Handle view to support used by app.
           *
           * @param v View resource from skin package.
           */
          public void handleView(Context context, View v) {
              resetID();
              //Id map: Key as skin id and Value as local id.
              SparseIntArray array = new SparseIntArray();
              buildIdRules(context, v, array);
              int size = array.size();
              // Map ids to which app can recognize locally.
              for (int i = 0; i < size; i++) {
                  //Map id defined in skin package into real id in app.
                  v.findViewById(array.keyAt(i)).setId(array.valueAt(i));
              }
          }
      
          /**
           * Extract id from view , build id rules and inflate rules if needed.
           *
           * @param v
           * @param array
           */
          protected void buildIdRules(Context context, View v, SparseIntArray array) {
              if (v.getId() != View.NO_ID) {
                  //Get mapped id by id name.
                  String idName = getResourceEntryName(v.getId());
                  int mappedId = getAppResources().getIdentifier(idName, "id", context.getPackageName());
                  //Add custom id to avoid id conflict when mapped id not exist.
                  //Key as skin id and value as mapped id.
                  array.put(v.getId(), mappedId > 0 ? mappedId : generateId());
              }
              if (v instanceof ViewGroup) {
                  ViewGroup vp = (ViewGroup) v;
                  int childCount = vp.getChildCount();
                  for (int i = 0; i < childCount; i++) {
                      buildIdRules(context, vp.getChildAt(i), array);
                  }
              }
              buildInflateRules(v, array);
          }
      
          /**
           * Build inflate rules.
           *
           * @param v
           * @param array ID map of which Key as skin id and value as mapped id.
           */
          protected void buildInflateRules(View v, SparseIntArray array) {
              ViewGroup.LayoutParams lp = v.getLayoutParams();
              if (lp == null) {
                  return;
              }
              if (lp instanceof RelativeLayout.LayoutParams) {
                  int[] rules = ((RelativeLayout.LayoutParams) lp).getRules();
                  if (rules == null) {
                      return;
                  }
                  int size = rules.length;
                  int mapRule = -1;
                  for (int i = 0; i < size; i++) {
                      //Key as skin id and value as mapped id.
                      if (rules[i] > 0 && (mapRule = array.get(rules[i])) > 0) {
      //                    Log.i(TAG, "Rules[" + i + "]: Mapped from: " + rules[i] + "  to  " +mapRule);
                          rules[i] = mapRule;
                      }
                  }
              }
          }

       

      五、使用

      下載源碼,集成skin module到工程中,然后使用SkinManager提供的接口:

      public SkinManager initialize(Context context);//初始化皮膚管理器
      
      
      
      /**
       * Register an observer to be informed of skin changed for ui interface such as activity,fragment, dialog etc.
       * @param observer
       */
      public void register(ISkinObserver observer);//注冊換膚監(jiān)聽器,用于需要動態(tài)換膚的場景。
      
      /**
       * Get resources.
       * @return
       */
      public BaseResources getResources();//獲取資源
      
      /**
       * Change skin.
       * @param skinPath Path of skin archive.
       * @param pkgName Package name of skin archive.
       * @param cb Callback to be informed of skin-changing event.
       */
      public void changeSkin(String skinPath, String pkgName, ISkinCallback cb);//更換皮膚
      
      /**
       * Restore skin to app default skin.
       *
       * @param cb
       */
      public void restoreSkin(ISkinCallback cb) ;//恢復應用默認皮膚
      
      /**
       * Resume skin.Call it on application started.
       *
       * @param cb
       */
      public void resumeSkin(ISkinCallback cb) ;//恢復當前使用的皮膚,應在應用啟動界面調(diào)用。

       

       

      框架支持兩種換膚方式:

      1.靜態(tài)換膚(推薦)

      換膚完成后,關閉掉所有的Activity,然后重新啟動主界面。簡單方便。

      2.動態(tài)換膚

      需要換膚的Activity、Fragment、Dialog實現(xiàn)ISkinObserver, 并通過register(ISkinObserver observer)注冊到SkinManager,動態(tài)更換布局,詳情見Sample代碼。

      這種方式需要重新渲染View,綁定數(shù)據(jù),在使用Fragment時,還需要在換膚期間detach/attach fragment,使用起來比較麻煩。優(yōu)點是換膚后可以停留在原來界面。

       

      兩種方式都需要使用SkinManager提供的Resource來獲取布局或其他資源。推薦寫自己的BaseActivity,重寫getResources()返回SkinManager提供的Resources方便使用。小伙伴們根據(jù)自己的實際情況來選擇具體使用何種方式。

       

      好了,到這里換膚框架就介紹完了,歡迎關注SkinFramework的最新動態(tài),若有任何建議和意見,歡迎指出!

       

      posted @ 2017-07-12 14:20  Oxgen  Views(3276)  Comments(2)    收藏  舉報
      主站蜘蛛池模板: 女同性恋一区二区三区视频| 国产高在线精品亚洲三区| 国产中文字幕一区二区| 国产精品人妻在线观看| 狠狠综合久久综合88亚洲| 日韩深夜福利视频在线观看 | 亚洲一卡2卡3卡4卡精品| 中文字幕亚洲精品人妻| 337p粉嫩大胆噜噜噜| 国产精品日本一区二区不卡视频| 国产色悠悠在线免费观看| 国内精品久久人妻互换| 一区二区三区日本久久九| 人人澡人摸人人添| 日韩精品有码中文字幕| 亚洲AV高清一区二区三区尤物| 久久无码专区国产精品| 富顺县| 精品国产av一区二区果冻传媒| 亚洲欧美日韩成人综合一区| 成武县| 免费无码中文字幕A级毛片| 337P日本欧洲亚洲大胆精品555588| 麻豆精品一区二区综合av| 国产自在自线午夜精品| 免费又黄又爽又猛的毛片| 亚州中文字幕一区二区| 黄色三级亚洲男人的天堂| 婷婷丁香五月激情综合| 福利一区二区不卡国产| 精品久久精品久久精品九九| 久久男人av资源站| 国产伦一区二区三区久久| 东京热高清无码精品| 中文字幕日韩国产精品| 四虎影视一区二区精品| a级黑人大硬长爽猛出猛进| 东京热加勒比无码少妇| 国产成人精品无码一区二区老年人 | 狠狠综合久久综合88亚洲| 免费一本色道久久一区|