Merge branch 'skin_custom_view' into dev
This commit is contained in:
5
.idea/gradle.xml
generated
5
.idea/gradle.xml
generated
@@ -61,6 +61,11 @@
|
||||
<option value="$PROJECT_DIR$/skin/mogo-skin-support" />
|
||||
<option value="$PROJECT_DIR$/skin/mogo-skin-support-impl" />
|
||||
<option value="$PROJECT_DIR$/skin/mogo-skin-support-noop" />
|
||||
<option value="$PROJECT_DIR$/skin/skin-support" />
|
||||
<option value="$PROJECT_DIR$/skin/skin-support-appcompat" />
|
||||
<option value="$PROJECT_DIR$/skin/skin-support-cardview" />
|
||||
<option value="$PROJECT_DIR$/skin/skin-support-constraint-layout" />
|
||||
<option value="$PROJECT_DIR$/skin/skin-support-design" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
|
||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -4,7 +4,7 @@
|
||||
<asm skipDebug="false" skipFrames="false" skipCode="false" expandFrames="false" />
|
||||
<groovy codeStyle="LEGACY" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="JDK" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.mogo.module.common.glide;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.SimpleTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020/9/2
|
||||
*
|
||||
* 描述
|
||||
*/
|
||||
class SkinAbleBitmapTarget extends SimpleTarget< Bitmap > {
|
||||
|
||||
private ImageView mTarget;
|
||||
private RequestOptions mOptions;
|
||||
|
||||
public SkinAbleBitmapTarget( ImageView mTarget, RequestOptions mOptions ) {
|
||||
super();
|
||||
this.mTarget = mTarget;
|
||||
this.mOptions = mOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResourceReady( @NonNull Bitmap resource, @Nullable Transition< ? super Bitmap > transition ) {
|
||||
try {
|
||||
mTarget.setImageResource( 0 );
|
||||
mTarget.setImageBitmap( resource );
|
||||
} catch( Exception e ){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadCleared( @Nullable Drawable placeholder ) {
|
||||
super.onLoadCleared( placeholder );
|
||||
try {
|
||||
mTarget.setImageResource( mOptions.getPlaceholderId() );
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadStarted( @Nullable Drawable placeholder ) {
|
||||
super.onLoadStarted( placeholder );
|
||||
try {
|
||||
mTarget.setImageResource( mOptions.getPlaceholderId() );
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFailed( @Nullable Drawable errorDrawable ) {
|
||||
super.onLoadFailed( errorDrawable );
|
||||
try {
|
||||
mTarget.setImageResource( mOptions.getErrorId() );
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,13 +19,13 @@ import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.mogo.commons.debug.DebugConfig;
|
||||
import com.mogo.module.common.entity.MarkerExploreWay;
|
||||
import com.mogo.module.common.glide.SkinAbleBitmapTarget;
|
||||
import com.mogo.module.tanlu.R;
|
||||
import com.mogo.module.tanlu.callback.IThumbsUpCallback;
|
||||
import com.mogo.module.tanlu.constant.TanluConstants;
|
||||
import com.mogo.module.tanlu.model.TanluModelData;
|
||||
import com.mogo.module.tanlu.model.event.CloseWindowInfo;
|
||||
import com.mogo.module.tanlu.model.event.ControlClickUpInfo;
|
||||
import com.mogo.module.tanlu.model.event.DataErrorInfo;
|
||||
import com.mogo.module.tanlu.model.event.StartPlayInfo;
|
||||
import com.mogo.module.tanlu.model.event.VoiceControlUpInfo;
|
||||
import com.mogo.module.tanlu.util.ChartUtil;
|
||||
@@ -372,9 +372,10 @@ public class TanluSlideAdapterNew extends RecyclerView.Adapter<TanluSlideViewHol
|
||||
.error(R.drawable.tanlu_normal_image)
|
||||
.fallback(R.drawable.tanlu_normal_image);
|
||||
Glide.with(mContext)
|
||||
.asBitmap()
|
||||
.load(imageUrl)
|
||||
.apply(requestOptions)
|
||||
.into(autoZoomInImageView);
|
||||
.into(new SkinAbleBitmapTarget(autoZoomInImageView, requestOptions));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/tanlu_module_card_height"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:background="@drawable/tanlu_gradual_change_bg">
|
||||
|
||||
<!--视频播放器和图片播放器-->
|
||||
@@ -37,7 +38,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/tanlu_normal_image"
|
||||
tools:src="@drawable/tanlu_normal_image"
|
||||
android:scaleType="fitXY" />
|
||||
</com.mogo.module.tanlu.view.RoundLayout>
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
include ':skin:skin-support'
|
||||
include ':skin:skin-support-appcompat'
|
||||
include ':skin:skin-support-cardview'
|
||||
include ':skin:skin-support-constraint-layout'
|
||||
include ':skin:skin-support-design'
|
||||
include ':skin:mogo-skin-light'
|
||||
include ':skin:mogo-skin-support-impl'
|
||||
include ':skin:mogo-skin-support-noop'
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 444 B |
@@ -40,11 +40,17 @@ dependencies {
|
||||
annotationProcessor rootProject.ext.dependencies.aroutercompiler
|
||||
|
||||
// 换肤功能
|
||||
implementation 'skin.support:skin-support:4.0.5' // skin-support
|
||||
implementation 'skin.support:skin-support-appcompat:4.0.5' // skin-support 基础控件支持
|
||||
implementation 'skin.support:skin-support-design:4.0.5' // skin-support-design material design 控件支持[可选]
|
||||
implementation 'skin.support:skin-support-cardview:4.0.5' // skin-support-cardview CardView 控件支持[可选]
|
||||
implementation 'skin.support:skin-support-constraint-layout:4.0.5' // skin-support-constraint-layout ConstraintLayout 控件支持[可选]
|
||||
// implementation 'skin.support:skin-support:4.0.5' // skin-support
|
||||
// implementation 'skin.support:skin-support-appcompat:4.0.5' // skin-support 基础控件支持
|
||||
// implementation 'skin.support:skin-support-design:4.0.5' // skin-support-design material design 控件支持[可选]
|
||||
// implementation 'skin.support:skin-support-cardview:4.0.5' // skin-support-cardview CardView 控件支持[可选]
|
||||
// implementation 'skin.support:skin-support-constraint-layout:4.0.5' // skin-support-constraint-layout ConstraintLayout 控件支持[可选]
|
||||
|
||||
implementation project(":skin:skin-support")
|
||||
implementation project(":skin:skin-support-appcompat")
|
||||
implementation project(":skin:skin-support-cardview")
|
||||
implementation project(":skin:skin-support-constraint-layout")
|
||||
implementation project(":skin:skin-support-design")
|
||||
|
||||
if( Boolean.valueOf(RELEASE) ){
|
||||
implementation rootProject.ext.dependencies.skinsupport
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.mogo.skin.support;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020/9/2
|
||||
*
|
||||
* 自定义view
|
||||
*/
|
||||
interface IMogoSkinCompatSupportable {
|
||||
|
||||
void applySkin();
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.mogo.skin.support.helper;
|
||||
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import com.mogo.skin.support.IMogoSkinCompatSupportable;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020/9/3
|
||||
*
|
||||
* 代理 skin.support.widget.SkinCompatBackgroundHelper 类
|
||||
*/
|
||||
class MogoSkinCompatBackgroundHelperDelegate extends MogoSkinCompatHelperDelegate {
|
||||
|
||||
private static Method sMethodOnSetBackgroundResource;
|
||||
|
||||
@Override
|
||||
protected String getDelegateClazzName() {
|
||||
return "skin.support.widget.SkinCompatBackgroundHelper";
|
||||
}
|
||||
|
||||
public MogoSkinCompatBackgroundHelperDelegate( View view ) {
|
||||
super( view );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class< ? extends View >[] getConstructParameterClazz() {
|
||||
return new Class[]{View.class};
|
||||
}
|
||||
|
||||
public void onSetBackgroundResource( int resId ) {
|
||||
if ( sMethodOnSetBackgroundResource == null ) {
|
||||
try {
|
||||
sMethodOnSetBackgroundResource = mTargetClazz.getDeclaredMethod( "onSetBackgroundResource", int.class );
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if ( sMethodOnSetBackgroundResource != null ) {
|
||||
sMethodOnSetBackgroundResource.setAccessible( true );
|
||||
try {
|
||||
sMethodOnSetBackgroundResource.invoke( mDelegate, resId );
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.mogo.skin.support.helper;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.CompoundButton;
|
||||
|
||||
import com.mogo.skin.support.IMogoSkinCompatSupportable;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020/9/3
|
||||
*
|
||||
* 描述
|
||||
*/
|
||||
class MogoSkinCompatCompoundButtonHelperDelegate extends MogoSkinCompatHelperDelegate implements IMogoSkinCompatSupportable {
|
||||
|
||||
protected static Method sSetButtonDrawableMethod;
|
||||
|
||||
public MogoSkinCompatCompoundButtonHelperDelegate( CompoundButton view ) {
|
||||
super( view );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class< ? extends View >[] getConstructParameterClazz() {
|
||||
return new Class[]{CompoundButton.class};
|
||||
}
|
||||
|
||||
public void setButtonDrawable( int resId ) {
|
||||
if ( sSetButtonDrawableMethod == null ) {
|
||||
try {
|
||||
sSetButtonDrawableMethod = mTargetClazz.getDeclaredMethod( "setButtonDrawable", int.class );
|
||||
sSetButtonDrawableMethod.setAccessible( true );
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if ( sSetButtonDrawableMethod != null ) {
|
||||
try {
|
||||
sSetButtonDrawableMethod.invoke( mDelegate, resId );
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDelegateClazzName() {
|
||||
return "skin.support.widget.SkinCompatCompoundButtonHelper";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.mogo.skin.support.helper;
|
||||
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import com.mogo.skin.support.IMogoSkinCompatSupportable;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020/9/3
|
||||
*
|
||||
* 描述
|
||||
*/
|
||||
abstract class MogoSkinCompatHelperDelegate implements IMogoSkinCompatSupportable {
|
||||
|
||||
protected volatile static Class< ? > mTargetClazz;
|
||||
protected Object mDelegate;
|
||||
protected volatile static Method sMethodApplySkin;
|
||||
protected volatile static Method sMethodLoadFromAttributes;
|
||||
private static Constructor sConstructor;
|
||||
|
||||
public MogoSkinCompatHelperDelegate( View view ) {
|
||||
loadClazz();
|
||||
initDelegateInstance( view );
|
||||
}
|
||||
|
||||
protected void loadClazz() {
|
||||
if ( mTargetClazz == null ) {
|
||||
try {
|
||||
mTargetClazz = Class.forName( getDelegateClazzName() );
|
||||
getLoadFromAttributesMethod();
|
||||
getApplySkinMethod();
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void initDelegateInstance( View view ) {
|
||||
try {
|
||||
if ( sConstructor == null ) {
|
||||
if ( mTargetClazz != null ) {
|
||||
sConstructor = mTargetClazz.getConstructor( getConstructParameterClazz() );
|
||||
sConstructor.setAccessible( true );
|
||||
}
|
||||
}
|
||||
if ( sConstructor != null ) {
|
||||
mDelegate = sConstructor.newInstance( view );
|
||||
}
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Class< ? extends View >[] getConstructParameterClazz();
|
||||
|
||||
protected abstract String getDelegateClazzName();
|
||||
|
||||
protected static Method getLoadFromAttributesMethod() throws Exception {
|
||||
if ( mTargetClazz != null ) {
|
||||
Method method = mTargetClazz.getDeclaredMethod( "loadFromAttributes", AttributeSet.class, int.class );
|
||||
method.setAccessible( true );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Method getApplySkinMethod() throws Exception {
|
||||
if ( mTargetClazz != null ) {
|
||||
Method method = mTargetClazz.getDeclaredMethod( "applySkin" );
|
||||
method.setAccessible( true );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void loadFromAttributes( AttributeSet attrs, int defStyleAttr ) {
|
||||
if ( sMethodLoadFromAttributes != null ) {
|
||||
try {
|
||||
sMethodLoadFromAttributes.invoke( mDelegate, attrs, defStyleAttr );
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if ( sMethodApplySkin != null ) {
|
||||
try {
|
||||
sMethodApplySkin.invoke( mDelegate );
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.mogo.skin.support.helper;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020/9/3
|
||||
*
|
||||
* 描述
|
||||
*/
|
||||
class MogoSkinCompatImageHelperDelegate extends MogoSkinCompatHelperDelegate {
|
||||
|
||||
private static Method sSetImageResourceMethod;
|
||||
|
||||
public MogoSkinCompatImageHelperDelegate( ImageView view ) {
|
||||
super( view );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class< ? extends View >[] getConstructParameterClazz() {
|
||||
return new Class[]{ImageView.class};
|
||||
}
|
||||
|
||||
public void setImageResource( int resId ) {
|
||||
if ( sSetImageResourceMethod == null ) {
|
||||
try {
|
||||
sSetImageResourceMethod = mTargetClazz.getDeclaredMethod( "setImageResource", int.class );
|
||||
sSetImageResourceMethod.setAccessible( true );
|
||||
} catch ( NoSuchMethodException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if ( sSetImageResourceMethod != null ) {
|
||||
try {
|
||||
sSetImageResourceMethod.invoke( mDelegate, resId );
|
||||
} catch ( IllegalAccessException e ) {
|
||||
e.printStackTrace();
|
||||
} catch ( InvocationTargetException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDelegateClazzName() {
|
||||
return "skin.support.widget.SkinCompatImageHelper";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.mogo.skin.support.helper;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020/9/3
|
||||
*
|
||||
* 描述
|
||||
*/
|
||||
class MogoSkinCompatProgressBarHelperDelegate extends MogoSkinCompatHelperDelegate {
|
||||
|
||||
public MogoSkinCompatProgressBarHelperDelegate( ProgressBar view ) {
|
||||
super( view );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class< ? extends View >[] getConstructParameterClazz() {
|
||||
return new Class[]{ProgressBar.class};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDelegateClazzName() {
|
||||
return "skin.support.widget.SkinCompatProgressBarHelper";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.mogo.skin.support.helper;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.SeekBar;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020/9/3
|
||||
*
|
||||
* 描述
|
||||
*/
|
||||
class MogoSkinCompatSeekBarHelperDelegate extends MogoSkinCompatHelperDelegate {
|
||||
|
||||
public MogoSkinCompatSeekBarHelperDelegate( SeekBar view ) {
|
||||
super( view );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class< ? extends View >[] getConstructParameterClazz() {
|
||||
return new Class[]{SeekBar.class};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDelegateClazzName() {
|
||||
return "skin.support.widget.SkinCompatSeekBarHelper";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package com.mogo.skin.support.helper;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020/9/3
|
||||
*
|
||||
* 描述
|
||||
*/
|
||||
class MogoSkinCompatTextHelperDelegate extends MogoSkinCompatHelperDelegate {
|
||||
|
||||
private static Method sOnSetTextAppearanceMethod;
|
||||
private static Method sOnSetCompoundDrawablesRelativeWithIntrinsicBoundsMethod;
|
||||
private static Method sOnSetCompoundDrawablesWithIntrinsicBoundsMethod;
|
||||
private static Method sGetTextColorResIdMethod;
|
||||
|
||||
public MogoSkinCompatTextHelperDelegate( TextView view ) {
|
||||
super( view );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class< ? extends View >[] getConstructParameterClazz() {
|
||||
return new Class[]{TextView.class};
|
||||
}
|
||||
|
||||
public void onSetTextAppearance( Context context, int resId ) {
|
||||
if ( sOnSetTextAppearanceMethod == null ) {
|
||||
try {
|
||||
sOnSetTextAppearanceMethod = mTargetClazz.getDeclaredMethod( "onSetTextAppearance", Context.class, int.class );
|
||||
sOnSetTextAppearanceMethod.setAccessible( true );
|
||||
} catch ( NoSuchMethodException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if ( sOnSetTextAppearanceMethod != null ) {
|
||||
try {
|
||||
sOnSetTextAppearanceMethod.invoke( mDelegate, context, resId );
|
||||
} catch ( IllegalAccessException e ) {
|
||||
e.printStackTrace();
|
||||
} catch ( InvocationTargetException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void onSetCompoundDrawablesRelativeWithIntrinsicBounds(
|
||||
@DrawableRes int start, @DrawableRes int top, @DrawableRes int end, @DrawableRes int bottom ) {
|
||||
if ( sOnSetCompoundDrawablesRelativeWithIntrinsicBoundsMethod == null ) {
|
||||
try {
|
||||
sOnSetCompoundDrawablesRelativeWithIntrinsicBoundsMethod = mTargetClazz.getDeclaredMethod( "onSetCompoundDrawablesRelativeWithIntrinsicBounds", int.class, int.class, int.class, int.class );
|
||||
sOnSetCompoundDrawablesRelativeWithIntrinsicBoundsMethod.setAccessible( true );
|
||||
} catch ( NoSuchMethodException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if ( sOnSetCompoundDrawablesRelativeWithIntrinsicBoundsMethod != null ) {
|
||||
try {
|
||||
sOnSetCompoundDrawablesRelativeWithIntrinsicBoundsMethod.invoke( mDelegate, start, top, end, bottom );
|
||||
} catch ( IllegalAccessException e ) {
|
||||
e.printStackTrace();
|
||||
} catch ( InvocationTargetException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onSetCompoundDrawablesWithIntrinsicBounds(
|
||||
@DrawableRes int left, @DrawableRes int top, @DrawableRes int right, @DrawableRes int bottom ) {
|
||||
if ( sOnSetCompoundDrawablesWithIntrinsicBoundsMethod == null ) {
|
||||
try {
|
||||
sOnSetCompoundDrawablesWithIntrinsicBoundsMethod = mTargetClazz.getDeclaredMethod( "onSetCompoundDrawablesWithIntrinsicBounds", int.class, int.class, int.class, int.class );
|
||||
sOnSetCompoundDrawablesWithIntrinsicBoundsMethod.setAccessible( true );
|
||||
} catch ( NoSuchMethodException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if ( sOnSetCompoundDrawablesWithIntrinsicBoundsMethod != null ) {
|
||||
try {
|
||||
sOnSetCompoundDrawablesWithIntrinsicBoundsMethod.invoke( mDelegate, left, top, right, bottom );
|
||||
} catch ( IllegalAccessException e ) {
|
||||
e.printStackTrace();
|
||||
} catch ( InvocationTargetException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getTextColorResId() {
|
||||
if ( sGetTextColorResIdMethod == null ) {
|
||||
try {
|
||||
sGetTextColorResIdMethod = mTargetClazz.getDeclaredMethod( "getTextColorResId" );
|
||||
sGetTextColorResIdMethod.setAccessible( true );
|
||||
} catch ( NoSuchMethodException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if ( sGetTextColorResIdMethod != null ) {
|
||||
try {
|
||||
Object result = sGetTextColorResIdMethod.invoke( mDelegate );
|
||||
return ( ( Integer ) result ).intValue();
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDelegateClazzName() {
|
||||
return "skin.support.widget.SkinCompatTextHelper";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package com.mogo.skin.support.helper;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020/9/3
|
||||
*
|
||||
* 描述
|
||||
*/
|
||||
@RequiresApi( 17 )
|
||||
@TargetApi( 17 )
|
||||
class MogoSkinCompatTextHelperV17Delegate extends MogoSkinCompatHelperDelegate {
|
||||
|
||||
private static Method sOnSetTextAppearanceMethod;
|
||||
private static Method sOnSetCompoundDrawablesRelativeWithIntrinsicBoundsMethod;
|
||||
private static Method sOnSetCompoundDrawablesWithIntrinsicBoundsMethod;
|
||||
private static Method sGetTextColorResIdMethod;
|
||||
|
||||
public MogoSkinCompatTextHelperV17Delegate( TextView view ) {
|
||||
super( view );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class< ? extends View >[] getConstructParameterClazz() {
|
||||
return new Class[]{TextView.class};
|
||||
}
|
||||
|
||||
public void onSetTextAppearance( Context context, int resId ) {
|
||||
if ( sOnSetTextAppearanceMethod == null ) {
|
||||
try {
|
||||
sOnSetTextAppearanceMethod = mTargetClazz.getDeclaredMethod( "onSetTextAppearance", Context.class, int.class );
|
||||
sOnSetTextAppearanceMethod.setAccessible( true );
|
||||
} catch ( NoSuchMethodException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if ( sOnSetTextAppearanceMethod != null ) {
|
||||
try {
|
||||
sOnSetTextAppearanceMethod.invoke( mDelegate, context, resId );
|
||||
} catch ( IllegalAccessException e ) {
|
||||
e.printStackTrace();
|
||||
} catch ( InvocationTargetException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void onSetCompoundDrawablesRelativeWithIntrinsicBounds(
|
||||
@DrawableRes int start, @DrawableRes int top, @DrawableRes int end, @DrawableRes int bottom ) {
|
||||
if ( sOnSetCompoundDrawablesRelativeWithIntrinsicBoundsMethod == null ) {
|
||||
try {
|
||||
sOnSetCompoundDrawablesRelativeWithIntrinsicBoundsMethod = mTargetClazz.getDeclaredMethod( "onSetCompoundDrawablesRelativeWithIntrinsicBounds", int.class, int.class, int.class, int.class );
|
||||
sOnSetCompoundDrawablesRelativeWithIntrinsicBoundsMethod.setAccessible( true );
|
||||
} catch ( NoSuchMethodException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if ( sOnSetCompoundDrawablesRelativeWithIntrinsicBoundsMethod != null ) {
|
||||
try {
|
||||
sOnSetCompoundDrawablesRelativeWithIntrinsicBoundsMethod.invoke( mDelegate, start, top, end, bottom );
|
||||
} catch ( IllegalAccessException e ) {
|
||||
e.printStackTrace();
|
||||
} catch ( InvocationTargetException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onSetCompoundDrawablesWithIntrinsicBounds(
|
||||
@DrawableRes int left, @DrawableRes int top, @DrawableRes int right, @DrawableRes int bottom ) {
|
||||
if ( sOnSetCompoundDrawablesWithIntrinsicBoundsMethod == null ) {
|
||||
try {
|
||||
sOnSetCompoundDrawablesWithIntrinsicBoundsMethod = mTargetClazz.getDeclaredMethod( "onSetCompoundDrawablesWithIntrinsicBounds", int.class, int.class, int.class, int.class );
|
||||
sOnSetCompoundDrawablesWithIntrinsicBoundsMethod.setAccessible( true );
|
||||
} catch ( NoSuchMethodException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if ( sOnSetCompoundDrawablesWithIntrinsicBoundsMethod != null ) {
|
||||
try {
|
||||
sOnSetCompoundDrawablesWithIntrinsicBoundsMethod.invoke( mDelegate, left, top, right, bottom );
|
||||
} catch ( IllegalAccessException e ) {
|
||||
e.printStackTrace();
|
||||
} catch ( InvocationTargetException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getTextColorResId() {
|
||||
if ( sGetTextColorResIdMethod == null ) {
|
||||
try {
|
||||
sGetTextColorResIdMethod = mTargetClazz.getDeclaredMethod( "getTextColorResId" );
|
||||
sGetTextColorResIdMethod.setAccessible( true );
|
||||
} catch ( NoSuchMethodException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if ( sGetTextColorResIdMethod != null ) {
|
||||
try {
|
||||
Object result = sGetTextColorResIdMethod.invoke( mDelegate );
|
||||
return ( ( Integer ) result ).intValue();
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDelegateClazzName() {
|
||||
return "skin.support.widget.SkinCompatTextHelperV17";
|
||||
}
|
||||
}
|
||||
40
skin/mogo-skin-support/src/main/res/values/attrs.xml
Executable file
40
skin/mogo-skin-support/src/main/res/values/attrs.xml
Executable file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="MogoSkinBackgroundHelper">
|
||||
<attr name="android:background" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="MogoSkinCompatImageView">
|
||||
<attr name="android:src" />
|
||||
<attr name="srcCompat" />
|
||||
<attr name="android:tint" format="color" />
|
||||
<attr name="tint" format="color" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="MogoSkinCompatTextHelper">
|
||||
<attr name="android:drawableLeft" />
|
||||
<attr name="android:drawableTop" />
|
||||
<attr name="android:drawableRight" />
|
||||
<attr name="android:drawableBottom" />
|
||||
<attr name="android:drawableStart" />
|
||||
<attr name="android:drawableEnd" />
|
||||
<attr name="android:textAppearance" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="MogoSkinTextAppearance">
|
||||
<attr name="android:textSize" />
|
||||
<attr name="android:textColor" />
|
||||
<attr name="android:textColorHint" />
|
||||
<attr name="android:textStyle" />
|
||||
<attr name="android:typeface" />
|
||||
<attr name="textAllCaps" />
|
||||
<attr name="android:shadowColor" />
|
||||
<attr name="android:shadowDy" />
|
||||
<attr name="android:shadowDx" />
|
||||
<attr name="android:shadowRadius" />
|
||||
</declare-styleable>
|
||||
<declare-styleable name="SkinCompatProgressBar">
|
||||
<attr name="android:indeterminateDrawable" />
|
||||
<attr name="android:progressDrawable" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
1
skin/skin-support-appcompat/.gitignore
vendored
Executable file
1
skin/skin-support-appcompat/.gitignore
vendored
Executable file
@@ -0,0 +1 @@
|
||||
/build
|
||||
40
skin/skin-support-appcompat/build.gradle
Executable file
40
skin/skin-support-appcompat/build.gradle
Executable file
@@ -0,0 +1,40 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
||||
// buildToolsVersion rootProject.ext.android.buildToolsVersion
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.android.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.android.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
res.srcDirs = ['src/main/res', 'src/main/res-alertdialog']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation project(':skin:skin-support')
|
||||
implementation rootProject.ext.dependencies.androidxappcompat
|
||||
}
|
||||
|
||||
tasks.withType(Javadoc) {
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
options.addStringOption('encoding', 'UTF-8')
|
||||
options.addStringOption('charSet', 'UTF-8')
|
||||
}
|
||||
|
||||
ext {
|
||||
moduleName = 'skin-support-appcompat'
|
||||
descContent = 'skin-support 基础控件换肤支持包'
|
||||
}
|
||||
21
skin/skin-support-appcompat/proguard-rules.pro
vendored
Executable file
21
skin/skin-support-appcompat/proguard-rules.pro
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
2
skin/skin-support-appcompat/src/main/AndroidManifest.xml
Executable file
2
skin/skin-support-appcompat/src/main/AndroidManifest.xml
Executable file
@@ -0,0 +1,2 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="skin.support.appcompat" />
|
||||
@@ -0,0 +1,31 @@
|
||||
package androidx.appcompat.app;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.view.Window;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public class SkinAppCompatDelegateImpl extends AppCompatDelegateImpl {
|
||||
private static Map<Activity, WeakReference<AppCompatDelegate>> sDelegateMap = new WeakHashMap<>();
|
||||
|
||||
public static AppCompatDelegate get(Activity activity, AppCompatCallback callback) {
|
||||
WeakReference<AppCompatDelegate> delegateRef = sDelegateMap.get(activity);
|
||||
AppCompatDelegate delegate = (delegateRef == null ? null : delegateRef.get());
|
||||
if (delegate == null) {
|
||||
delegate = new SkinAppCompatDelegateImpl(activity, activity.getWindow(), callback);
|
||||
sDelegateMap.put(activity, new WeakReference<>(delegate));
|
||||
}
|
||||
return delegate;
|
||||
}
|
||||
|
||||
private SkinAppCompatDelegateImpl(Context context, Window window, AppCompatCallback callback) {
|
||||
super(context, window, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installViewFactory() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
package skin.support.app;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.appcompat.view.ContextThemeWrapper;
|
||||
import androidx.appcompat.widget.TintContextWrapper;
|
||||
import androidx.appcompat.widget.VectorEnabledTintResources;
|
||||
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewParent;
|
||||
|
||||
import skin.support.appcompat.R;
|
||||
import skin.support.content.res.SkinCompatVectorResources;
|
||||
import skin.support.utils.Slog;
|
||||
import skin.support.widget.SkinCompatAutoCompleteTextView;
|
||||
import skin.support.widget.SkinCompatButton;
|
||||
import skin.support.widget.SkinCompatCheckBox;
|
||||
import skin.support.widget.SkinCompatCheckedTextView;
|
||||
import skin.support.widget.SkinCompatEditText;
|
||||
import skin.support.widget.SkinCompatFrameLayout;
|
||||
import skin.support.widget.SkinCompatImageButton;
|
||||
import skin.support.widget.SkinCompatImageView;
|
||||
import skin.support.widget.SkinCompatLinearLayout;
|
||||
import skin.support.widget.SkinCompatMultiAutoCompleteTextView;
|
||||
import skin.support.widget.SkinCompatProgressBar;
|
||||
import skin.support.widget.SkinCompatRadioButton;
|
||||
import skin.support.widget.SkinCompatRadioGroup;
|
||||
import skin.support.widget.SkinCompatRatingBar;
|
||||
import skin.support.widget.SkinCompatRelativeLayout;
|
||||
import skin.support.widget.SkinCompatScrollView;
|
||||
import skin.support.widget.SkinCompatSeekBar;
|
||||
import skin.support.widget.SkinCompatSpinner;
|
||||
import skin.support.widget.SkinCompatTextView;
|
||||
import skin.support.widget.SkinCompatToolbar;
|
||||
import skin.support.widget.SkinCompatView;
|
||||
|
||||
public class SkinAppCompatViewInflater implements SkinLayoutInflater, SkinWrapper {
|
||||
private static final String LOG_TAG = "SkinAppCompatViewInflater";
|
||||
|
||||
public SkinAppCompatViewInflater() {
|
||||
SkinCompatVectorResources.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createView(Context context, String name, AttributeSet attrs) {
|
||||
View view = createViewFromFV(context, name, attrs);
|
||||
|
||||
if (view == null) {
|
||||
view = createViewFromV7(context, name, attrs);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
private View createViewFromFV(Context context, String name, AttributeSet attrs) {
|
||||
View view = null;
|
||||
if (name.contains(".")) {
|
||||
return null;
|
||||
}
|
||||
switch (name) {
|
||||
case "View":
|
||||
view = new SkinCompatView(context, attrs);
|
||||
break;
|
||||
case "LinearLayout":
|
||||
view = new SkinCompatLinearLayout(context, attrs);
|
||||
break;
|
||||
case "RelativeLayout":
|
||||
view = new SkinCompatRelativeLayout(context, attrs);
|
||||
break;
|
||||
case "FrameLayout":
|
||||
view = new SkinCompatFrameLayout(context, attrs);
|
||||
break;
|
||||
case "TextView":
|
||||
view = new SkinCompatTextView(context, attrs);
|
||||
break;
|
||||
case "ImageView":
|
||||
view = new SkinCompatImageView(context, attrs);
|
||||
break;
|
||||
case "Button":
|
||||
view = new SkinCompatButton(context, attrs);
|
||||
break;
|
||||
case "EditText":
|
||||
view = new SkinCompatEditText(context, attrs);
|
||||
break;
|
||||
case "Spinner":
|
||||
view = new SkinCompatSpinner(context, attrs);
|
||||
break;
|
||||
case "ImageButton":
|
||||
view = new SkinCompatImageButton(context, attrs);
|
||||
break;
|
||||
case "CheckBox":
|
||||
view = new SkinCompatCheckBox(context, attrs);
|
||||
break;
|
||||
case "RadioButton":
|
||||
view = new SkinCompatRadioButton(context, attrs);
|
||||
break;
|
||||
case "RadioGroup":
|
||||
view = new SkinCompatRadioGroup(context, attrs);
|
||||
break;
|
||||
case "CheckedTextView":
|
||||
view = new SkinCompatCheckedTextView(context, attrs);
|
||||
break;
|
||||
case "AutoCompleteTextView":
|
||||
view = new SkinCompatAutoCompleteTextView(context, attrs);
|
||||
break;
|
||||
case "MultiAutoCompleteTextView":
|
||||
view = new SkinCompatMultiAutoCompleteTextView(context, attrs);
|
||||
break;
|
||||
case "RatingBar":
|
||||
view = new SkinCompatRatingBar(context, attrs);
|
||||
break;
|
||||
case "SeekBar":
|
||||
view = new SkinCompatSeekBar(context, attrs);
|
||||
break;
|
||||
case "ProgressBar":
|
||||
view = new SkinCompatProgressBar(context, attrs);
|
||||
break;
|
||||
case "ScrollView":
|
||||
view = new SkinCompatScrollView(context, attrs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
private View createViewFromV7(Context context, String name, AttributeSet attrs) {
|
||||
View view = null;
|
||||
switch (name) {
|
||||
case "androidx.appcompat.widget.Toolbar":
|
||||
view = new SkinCompatToolbar(context, attrs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context wrapContext(Context context, View parent, AttributeSet attrs) {
|
||||
final boolean isPre21 = Build.VERSION.SDK_INT < 21;
|
||||
|
||||
// We only want the View to inherit its context if we're running pre-v21
|
||||
final boolean inheritContext = isPre21 && shouldInheritContext(context, (ViewParent) parent);
|
||||
|
||||
// We can emulate Lollipop's android:theme attribute propagating down the view hierarchy
|
||||
// by using the parent's context
|
||||
if (inheritContext && parent != null) {
|
||||
context = parent.getContext();
|
||||
}
|
||||
boolean readAndroidTheme = isPre21; /* Only read android:theme pre-L (L+ handles this anyway) */
|
||||
boolean readAppTheme = true; /* Read read app:theme as a fallback at all times for legacy reasons */
|
||||
boolean wrapContext = VectorEnabledTintResources.shouldBeUsed(); /* Only tint wrap the context if enabled */
|
||||
|
||||
// We can emulate Lollipop's android:theme attribute propagating down the view hierarchy
|
||||
// by using the parent's context
|
||||
if (inheritContext && parent != null) {
|
||||
context = parent.getContext();
|
||||
}
|
||||
if (readAndroidTheme || readAppTheme) {
|
||||
// We then apply the theme on the context, if specified
|
||||
context = themifyContext(context, attrs, readAndroidTheme, readAppTheme);
|
||||
}
|
||||
if (wrapContext) {
|
||||
context = TintContextWrapper.wrap(context);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
private boolean shouldInheritContext(Context context, ViewParent parent) {
|
||||
if (parent == null) {
|
||||
// The initial parent is null so just return false
|
||||
return false;
|
||||
}
|
||||
if (context instanceof Activity) {
|
||||
final View windowDecor = ((Activity) context).getWindow().getDecorView();
|
||||
while (true) {
|
||||
if (parent == null) {
|
||||
// Bingo. We've hit a view which has a null parent before being terminated from
|
||||
// the loop. This is (most probably) because it's the root view in an inflation
|
||||
// call, therefore we should inherit. This works as the inflated layout is only
|
||||
// added to the hierarchy at the end of the inflate() call.
|
||||
return true;
|
||||
} else if (parent == windowDecor || !(parent instanceof View)
|
||||
|| ViewCompat.isAttachedToWindow((View) parent)) {
|
||||
// We have either hit the window's decor view, a parent which isn't a View
|
||||
// (i.e. ViewRootImpl), or an attached view, so we know that the original parent
|
||||
// is currently added to the view hierarchy. This means that it has not be
|
||||
// inflated in the current inflate() call and we should not inherit the context.
|
||||
return false;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows us to emulate the {@code android:theme} attribute for devices before L.
|
||||
*/
|
||||
private static Context themifyContext(Context context, AttributeSet attrs,
|
||||
boolean useAndroidTheme, boolean useAppTheme) {
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.View, 0, 0);
|
||||
int themeId = 0;
|
||||
if (useAndroidTheme) {
|
||||
// First try reading android:theme if enabled
|
||||
themeId = a.getResourceId(R.styleable.View_android_theme, 0);
|
||||
}
|
||||
if (useAppTheme && themeId == 0) {
|
||||
// ...if that didn't work, try reading app:theme (for legacy reasons) if enabled
|
||||
themeId = a.getResourceId(R.styleable.View_theme, 0);
|
||||
|
||||
if (themeId != 0) {
|
||||
Slog.i(LOG_TAG, "app:theme is now deprecated. "
|
||||
+ "Please move to using android:theme instead.");
|
||||
}
|
||||
}
|
||||
a.recycle();
|
||||
|
||||
if (themeId != 0 && (!(context instanceof ContextThemeWrapper)
|
||||
|| ((ContextThemeWrapper) context).getThemeResId() != themeId)) {
|
||||
// If the context isn't a ContextThemeWrapper, or it is but does not have
|
||||
// the same theme as we need, wrap it in a new wrapper
|
||||
context = new ContextThemeWrapper(context, themeId);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package skin.support.app;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.view.LayoutInflaterCompat;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import skin.support.SkinCompatManager;
|
||||
import skin.support.content.res.SkinCompatThemeUtils;
|
||||
import skin.support.content.res.SkinCompatVectorResources;
|
||||
import skin.support.observe.SkinObservable;
|
||||
import skin.support.observe.SkinObserver;
|
||||
|
||||
import static skin.support.widget.SkinCompatHelper.INVALID_ID;
|
||||
import static skin.support.widget.SkinCompatHelper.checkResourceId;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 17-1-8.
|
||||
*/
|
||||
@Deprecated
|
||||
public class SkinCompatActivity extends AppCompatActivity implements SkinObserver {
|
||||
|
||||
private SkinCompatDelegate mSkinDelegate;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
LayoutInflaterCompat.setFactory2(getLayoutInflater(), getSkinDelegate());
|
||||
super.onCreate(savedInstanceState);
|
||||
updateStatusBarColor();
|
||||
updateWindowBackground();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public SkinCompatDelegate getSkinDelegate() {
|
||||
if (mSkinDelegate == null) {
|
||||
mSkinDelegate = SkinCompatDelegate.create(this);
|
||||
}
|
||||
return mSkinDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
SkinCompatManager.getInstance().addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
SkinCompatManager.getInstance().deleteObserver(this);
|
||||
}
|
||||
|
||||
protected void updateStatusBarColor() {
|
||||
}
|
||||
|
||||
protected void updateWindowBackground() {
|
||||
int windowBackgroundResId = SkinCompatThemeUtils.getWindowBackgroundResId(this);
|
||||
if (checkResourceId(windowBackgroundResId) != INVALID_ID) {
|
||||
Drawable drawable = SkinCompatVectorResources.getDrawableCompat(this, windowBackgroundResId);
|
||||
if (drawable != null) {
|
||||
getWindow().setBackgroundDrawable(drawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSkin(SkinObservable observable, Object o) {
|
||||
updateStatusBarColor();
|
||||
updateWindowBackground();
|
||||
getSkinDelegate().applySkin();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,754 @@
|
||||
package skin.support.content.res;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Drawable.ConstantState;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.os.Build;
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat;
|
||||
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
import androidx.collection.ArrayMap;
|
||||
import androidx.collection.LongSparseArray;
|
||||
import androidx.collection.LruCache;
|
||||
import androidx.appcompat.R;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.util.TypedValue;
|
||||
import android.util.Xml;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import static androidx.core.graphics.ColorUtils.compositeColors;
|
||||
import static skin.support.content.res.SkinCompatThemeUtils.getDisabledThemeAttrColor;
|
||||
import static skin.support.content.res.SkinCompatThemeUtils.getThemeAttrColor;
|
||||
import static skin.support.content.res.SkinCompatThemeUtils.getThemeAttrColorStateList;
|
||||
|
||||
final class SkinCompatDrawableManager {
|
||||
private interface InflateDelegate {
|
||||
Drawable createFromXmlInner(@NonNull Context context, @NonNull XmlPullParser parser,
|
||||
@NonNull AttributeSet attrs, @Nullable Resources.Theme theme);
|
||||
}
|
||||
|
||||
private static final String TAG = SkinCompatDrawableManager.class.getSimpleName();
|
||||
private static final boolean DEBUG = false;
|
||||
private static final PorterDuff.Mode DEFAULT_MODE = PorterDuff.Mode.SRC_IN;
|
||||
private static final String SKIP_DRAWABLE_TAG = "appcompat_skip_skip";
|
||||
|
||||
private static final String PLATFORM_VD_CLAZZ = "android.graphics.drawable.VectorDrawable";
|
||||
|
||||
private static SkinCompatDrawableManager INSTANCE;
|
||||
|
||||
public static SkinCompatDrawableManager get() {
|
||||
if (INSTANCE == null) {
|
||||
INSTANCE = new SkinCompatDrawableManager();
|
||||
installDefaultInflateDelegates(INSTANCE);
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private static void installDefaultInflateDelegates(@NonNull SkinCompatDrawableManager manager) {
|
||||
// This sdk version check will affect src:appCompat code path.
|
||||
// Although VectorDrawable exists in Android framework from Lollipop, AppCompat will use the
|
||||
// VectorDrawableCompat before Nougat to utilize the bug fixes in VectorDrawableCompat.
|
||||
if (Build.VERSION.SDK_INT < 24) {
|
||||
manager.addDelegate("vector", new VdcInflateDelegate());
|
||||
// AnimatedVectorDrawableCompat only works on API v11+
|
||||
manager.addDelegate("animated-vector", new AvdcInflateDelegate());
|
||||
}
|
||||
}
|
||||
|
||||
private static final ColorFilterLruCache COLOR_FILTER_CACHE = new ColorFilterLruCache(6);
|
||||
|
||||
/**
|
||||
* Drawables which should be tinted with the value of {@code R.attr.colorControlNormal},
|
||||
* using the default mode using a raw color filter.
|
||||
*/
|
||||
private static final int[] COLORFILTER_TINT_COLOR_CONTROL_NORMAL = {
|
||||
R.drawable.abc_textfield_search_default_mtrl_alpha,
|
||||
R.drawable.abc_textfield_default_mtrl_alpha,
|
||||
R.drawable.abc_ab_share_pack_mtrl_alpha
|
||||
};
|
||||
|
||||
/**
|
||||
* Drawables which should be tinted with the value of {@code R.attr.colorControlNormal}, using
|
||||
* {@link DrawableCompat}'s tinting functionality.
|
||||
*/
|
||||
private static final int[] TINT_COLOR_CONTROL_NORMAL = {
|
||||
R.drawable.abc_ic_commit_search_api_mtrl_alpha,
|
||||
R.drawable.abc_seekbar_tick_mark_material,
|
||||
R.drawable.abc_ic_menu_share_mtrl_alpha,
|
||||
R.drawable.abc_ic_menu_copy_mtrl_am_alpha,
|
||||
R.drawable.abc_ic_menu_cut_mtrl_alpha,
|
||||
R.drawable.abc_ic_menu_selectall_mtrl_alpha,
|
||||
R.drawable.abc_ic_menu_paste_mtrl_am_alpha
|
||||
};
|
||||
|
||||
/**
|
||||
* Drawables which should be tinted with the value of {@code R.attr.colorControlActivated},
|
||||
* using a color filter.
|
||||
*/
|
||||
private static final int[] COLORFILTER_COLOR_CONTROL_ACTIVATED = {
|
||||
R.drawable.abc_textfield_activated_mtrl_alpha,
|
||||
R.drawable.abc_textfield_search_activated_mtrl_alpha,
|
||||
R.drawable.abc_cab_background_top_mtrl_alpha,
|
||||
R.drawable.abc_text_cursor_material,
|
||||
R.drawable.abc_text_select_handle_left_mtrl_dark,
|
||||
R.drawable.abc_text_select_handle_middle_mtrl_dark,
|
||||
R.drawable.abc_text_select_handle_right_mtrl_dark,
|
||||
R.drawable.abc_text_select_handle_left_mtrl_light,
|
||||
R.drawable.abc_text_select_handle_middle_mtrl_light,
|
||||
R.drawable.abc_text_select_handle_right_mtrl_light
|
||||
};
|
||||
|
||||
/**
|
||||
* Drawables which should be tinted with the value of {@code android.R.attr.colorBackground},
|
||||
* using the {@link PorterDuff.Mode#MULTIPLY} mode and a color filter.
|
||||
*/
|
||||
private static final int[] COLORFILTER_COLOR_BACKGROUND_MULTIPLY = {
|
||||
R.drawable.abc_popup_background_mtrl_mult,
|
||||
R.drawable.abc_cab_background_internal_bg,
|
||||
R.drawable.abc_menu_hardkey_panel_mtrl_mult
|
||||
};
|
||||
|
||||
/**
|
||||
* Drawables which should be tinted using a state list containing values of
|
||||
* {@code R.attr.colorControlNormal} and {@code R.attr.colorControlActivated}
|
||||
*/
|
||||
private static final int[] TINT_COLOR_CONTROL_STATE_LIST = {
|
||||
R.drawable.abc_tab_indicator_material,
|
||||
R.drawable.abc_textfield_search_material
|
||||
};
|
||||
|
||||
/**
|
||||
* Drawables which should be tinted using a state list containing values of
|
||||
* {@code R.attr.colorControlNormal} and {@code R.attr.colorControlActivated} for the checked
|
||||
* state.
|
||||
*/
|
||||
private static final int[] TINT_CHECKABLE_BUTTON_LIST = {
|
||||
R.drawable.abc_btn_check_material,
|
||||
R.drawable.abc_btn_radio_material
|
||||
};
|
||||
|
||||
private WeakHashMap<Context, SparseArray<ColorStateList>> mTintLists;
|
||||
private ArrayMap<String, InflateDelegate> mDelegates;
|
||||
private SparseArray<String> mKnownDrawableIdTags;
|
||||
|
||||
private final Object mDrawableCacheLock = new Object();
|
||||
private final WeakHashMap<Context, LongSparseArray<WeakReference<ConstantState>>>
|
||||
mDrawableCaches = new WeakHashMap<>(0);
|
||||
|
||||
private TypedValue mTypedValue;
|
||||
|
||||
private boolean mHasCheckedVectorDrawableSetup;
|
||||
|
||||
void clearCaches() {
|
||||
mDrawableCaches.clear();
|
||||
if (mKnownDrawableIdTags != null) {
|
||||
mKnownDrawableIdTags.clear();
|
||||
}
|
||||
if (mTintLists != null) {
|
||||
mTintLists.clear();
|
||||
}
|
||||
COLOR_FILTER_CACHE.evictAll();
|
||||
}
|
||||
|
||||
public Drawable getDrawable(@NonNull Context context, @DrawableRes int resId) {
|
||||
return getDrawable(context, resId, false);
|
||||
}
|
||||
|
||||
Drawable getDrawable(@NonNull Context context, @DrawableRes int resId,
|
||||
boolean failIfNotKnown) {
|
||||
checkVectorDrawableSetup(context);
|
||||
|
||||
Drawable drawable = loadDrawableFromDelegates(context, resId);
|
||||
if (drawable == null) {
|
||||
drawable = createDrawableIfNeeded(context, resId);
|
||||
}
|
||||
if (drawable == null) {
|
||||
drawable = SkinCompatResources.getDrawable(context, resId);
|
||||
}
|
||||
|
||||
if (drawable != null) {
|
||||
// Tint it if needed
|
||||
drawable = tintDrawable(context, resId, failIfNotKnown, drawable);
|
||||
}
|
||||
if (drawable != null) {
|
||||
// See if we need to 'fix' the drawable
|
||||
SkinCompatDrawableUtils.fixDrawable(drawable);
|
||||
}
|
||||
return drawable;
|
||||
}
|
||||
|
||||
public void onConfigurationChanged(@NonNull Context context) {
|
||||
synchronized (mDrawableCacheLock) {
|
||||
LongSparseArray<WeakReference<ConstantState>> cache = mDrawableCaches.get(context);
|
||||
if (cache != null) {
|
||||
// Crude, but we'll just clear the cache when the configuration changes
|
||||
cache.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static long createCacheKey(TypedValue tv) {
|
||||
return (((long) tv.assetCookie) << 32) | tv.data;
|
||||
}
|
||||
|
||||
private Drawable createDrawableIfNeeded(@NonNull Context context,
|
||||
@DrawableRes final int resId) {
|
||||
if (mTypedValue == null) {
|
||||
mTypedValue = new TypedValue();
|
||||
}
|
||||
final TypedValue tv = mTypedValue;
|
||||
SkinCompatResources.getValue(context, resId, tv, true);
|
||||
final long key = createCacheKey(tv);
|
||||
|
||||
Drawable dr = getCachedDrawable(context, key);
|
||||
if (dr != null) {
|
||||
// If we got a cached drawable, return it
|
||||
return dr;
|
||||
}
|
||||
|
||||
// Else we need to try and create one...
|
||||
if (resId == R.drawable.abc_cab_background_top_material) {
|
||||
dr = new LayerDrawable(new Drawable[]{
|
||||
getDrawable(context, R.drawable.abc_cab_background_internal_bg),
|
||||
getDrawable(context, R.drawable.abc_cab_background_top_mtrl_alpha)
|
||||
});
|
||||
}
|
||||
|
||||
if (dr != null) {
|
||||
dr.setChangingConfigurations(tv.changingConfigurations);
|
||||
// If we reached here then we created a new drawable, add it to the cache
|
||||
addDrawableToCache(context, key, dr);
|
||||
}
|
||||
|
||||
return dr;
|
||||
}
|
||||
|
||||
private Drawable tintDrawable(@NonNull Context context, @DrawableRes int resId,
|
||||
boolean failIfNotKnown, @NonNull Drawable drawable) {
|
||||
final ColorStateList tintList = getTintList(context, resId);
|
||||
if (tintList != null) {
|
||||
// First mutate the Drawable, then wrap it and set the tint list
|
||||
if (SkinCompatDrawableUtils.canSafelyMutateDrawable(drawable)) {
|
||||
drawable = drawable.mutate();
|
||||
}
|
||||
drawable = DrawableCompat.wrap(drawable);
|
||||
DrawableCompat.setTintList(drawable, tintList);
|
||||
|
||||
// If there is a blending mode specified for the drawable, use it
|
||||
final PorterDuff.Mode tintMode = getTintMode(resId);
|
||||
if (tintMode != null) {
|
||||
DrawableCompat.setTintMode(drawable, tintMode);
|
||||
}
|
||||
} else if (resId == R.drawable.abc_seekbar_track_material) {
|
||||
LayerDrawable ld = (LayerDrawable) drawable;
|
||||
setPorterDuffColorFilter(ld.findDrawableByLayerId(android.R.id.background),
|
||||
getThemeAttrColor(context, R.attr.colorControlNormal), DEFAULT_MODE);
|
||||
setPorterDuffColorFilter(ld.findDrawableByLayerId(android.R.id.secondaryProgress),
|
||||
getThemeAttrColor(context, R.attr.colorControlNormal), DEFAULT_MODE);
|
||||
setPorterDuffColorFilter(ld.findDrawableByLayerId(android.R.id.progress),
|
||||
getThemeAttrColor(context, R.attr.colorControlActivated), DEFAULT_MODE);
|
||||
} else if (resId == R.drawable.abc_ratingbar_material
|
||||
|| resId == R.drawable.abc_ratingbar_indicator_material
|
||||
|| resId == R.drawable.abc_ratingbar_small_material) {
|
||||
LayerDrawable ld = (LayerDrawable) drawable;
|
||||
setPorterDuffColorFilter(ld.findDrawableByLayerId(android.R.id.background),
|
||||
getDisabledThemeAttrColor(context, R.attr.colorControlNormal),
|
||||
DEFAULT_MODE);
|
||||
setPorterDuffColorFilter(ld.findDrawableByLayerId(android.R.id.secondaryProgress),
|
||||
getThemeAttrColor(context, R.attr.colorControlActivated), DEFAULT_MODE);
|
||||
setPorterDuffColorFilter(ld.findDrawableByLayerId(android.R.id.progress),
|
||||
getThemeAttrColor(context, R.attr.colorControlActivated), DEFAULT_MODE);
|
||||
} else {
|
||||
final boolean tinted = tintDrawableUsingColorFilter(context, resId, drawable);
|
||||
if (!tinted && failIfNotKnown) {
|
||||
// If we didn't tint using a ColorFilter, and we're set to fail if we don't
|
||||
// know the id, return null
|
||||
drawable = null;
|
||||
}
|
||||
}
|
||||
return drawable;
|
||||
}
|
||||
|
||||
private Drawable loadDrawableFromDelegates(@NonNull Context context, @DrawableRes int resId) {
|
||||
if (mDelegates != null && !mDelegates.isEmpty()) {
|
||||
if (mKnownDrawableIdTags != null) {
|
||||
final String cachedTagName = mKnownDrawableIdTags.get(resId);
|
||||
if (SKIP_DRAWABLE_TAG.equals(cachedTagName)
|
||||
|| (cachedTagName != null && mDelegates.get(cachedTagName) == null)) {
|
||||
// If we don't have a delegate for the drawable tag, or we've been set to
|
||||
// skip it, fail fast and return null
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "[loadDrawableFromDelegates] Skipping drawable: "
|
||||
+ context.getResources().getResourceName(resId));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
// Create an id cache as we'll need one later
|
||||
mKnownDrawableIdTags = new SparseArray<>();
|
||||
}
|
||||
|
||||
if (mTypedValue == null) {
|
||||
mTypedValue = new TypedValue();
|
||||
}
|
||||
final TypedValue tv = mTypedValue;
|
||||
SkinCompatResources.getValue(context, resId, tv, true);
|
||||
|
||||
final long key = createCacheKey(tv);
|
||||
|
||||
Drawable dr = getCachedDrawable(context, key);
|
||||
if (dr != null) {
|
||||
if (DEBUG) {
|
||||
Log.i(TAG, "[loadDrawableFromDelegates] Returning cached drawable: " +
|
||||
context.getResources().getResourceName(resId));
|
||||
}
|
||||
// We have a cached drawable, return it!
|
||||
return dr;
|
||||
}
|
||||
|
||||
if (tv.string != null && tv.string.toString().endsWith(".xml")) {
|
||||
// If the resource is an XML file, let's try and parse it
|
||||
try {
|
||||
final XmlPullParser parser = SkinCompatResources.getXml(context, resId);
|
||||
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||
int type;
|
||||
while ((type = parser.next()) != XmlPullParser.START_TAG &&
|
||||
type != XmlPullParser.END_DOCUMENT) {
|
||||
// Empty loop
|
||||
}
|
||||
if (type != XmlPullParser.START_TAG) {
|
||||
throw new XmlPullParserException("No start tag found");
|
||||
}
|
||||
|
||||
final String tagName = parser.getName();
|
||||
// Add the tag name to the cache
|
||||
mKnownDrawableIdTags.append(resId, tagName);
|
||||
|
||||
// Now try and find a delegate for the tag name and inflate if found
|
||||
final InflateDelegate delegate = mDelegates.get(tagName);
|
||||
if (delegate != null) {
|
||||
dr = delegate.createFromXmlInner(context, parser, attrs, null);
|
||||
}
|
||||
if (dr != null) {
|
||||
// Add it to the drawable cache
|
||||
dr.setChangingConfigurations(tv.changingConfigurations);
|
||||
if (addDrawableToCache(context, key, dr) && DEBUG) {
|
||||
Log.i(TAG, "[loadDrawableFromDelegates] Saved drawable to cache: " +
|
||||
context.getResources().getResourceName(resId));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Exception while inflating drawable", e);
|
||||
}
|
||||
}
|
||||
if (dr == null) {
|
||||
// If we reach here then the delegate inflation of the resource failed. Mark it as
|
||||
// bad so we skip the id next time
|
||||
mKnownDrawableIdTags.append(resId, SKIP_DRAWABLE_TAG);
|
||||
}
|
||||
return dr;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Drawable getCachedDrawable(@NonNull final Context context, final long key) {
|
||||
synchronized (mDrawableCacheLock) {
|
||||
final LongSparseArray<WeakReference<ConstantState>> cache
|
||||
= mDrawableCaches.get(context);
|
||||
if (cache == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final WeakReference<ConstantState> wr = cache.get(key);
|
||||
if (wr != null) {
|
||||
// We have the key, and the secret
|
||||
ConstantState entry = wr.get();
|
||||
if (entry != null) {
|
||||
return entry.newDrawable(context.getResources());
|
||||
} else {
|
||||
// Our entry has been purged
|
||||
cache.delete(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean addDrawableToCache(@NonNull final Context context, final long key,
|
||||
@NonNull final Drawable drawable) {
|
||||
final ConstantState cs = drawable.getConstantState();
|
||||
if (cs != null) {
|
||||
synchronized (mDrawableCacheLock) {
|
||||
LongSparseArray<WeakReference<ConstantState>> cache = mDrawableCaches.get(context);
|
||||
if (cache == null) {
|
||||
cache = new LongSparseArray<>();
|
||||
mDrawableCaches.put(context, cache);
|
||||
}
|
||||
cache.put(key, new WeakReference<ConstantState>(cs));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static boolean tintDrawableUsingColorFilter(@NonNull Context context,
|
||||
@DrawableRes final int resId, @NonNull Drawable drawable) {
|
||||
PorterDuff.Mode tintMode = DEFAULT_MODE;
|
||||
boolean colorAttrSet = false;
|
||||
int colorAttr = 0;
|
||||
int alpha = -1;
|
||||
|
||||
if (arrayContains(COLORFILTER_TINT_COLOR_CONTROL_NORMAL, resId)) {
|
||||
colorAttr = R.attr.colorControlNormal;
|
||||
colorAttrSet = true;
|
||||
} else if (arrayContains(COLORFILTER_COLOR_CONTROL_ACTIVATED, resId)) {
|
||||
colorAttr = R.attr.colorControlActivated;
|
||||
colorAttrSet = true;
|
||||
} else if (arrayContains(COLORFILTER_COLOR_BACKGROUND_MULTIPLY, resId)) {
|
||||
colorAttr = android.R.attr.colorBackground;
|
||||
colorAttrSet = true;
|
||||
tintMode = PorterDuff.Mode.MULTIPLY;
|
||||
} else if (resId == R.drawable.abc_list_divider_mtrl_alpha) {
|
||||
colorAttr = android.R.attr.colorForeground;
|
||||
colorAttrSet = true;
|
||||
alpha = Math.round(0.16f * 255);
|
||||
} else if (resId == R.drawable.abc_dialog_material_background) {
|
||||
colorAttr = android.R.attr.colorBackground;
|
||||
colorAttrSet = true;
|
||||
}
|
||||
|
||||
if (colorAttrSet) {
|
||||
if (SkinCompatDrawableUtils.canSafelyMutateDrawable(drawable)) {
|
||||
drawable = drawable.mutate();
|
||||
}
|
||||
|
||||
final int color = getThemeAttrColor(context, colorAttr);
|
||||
drawable.setColorFilter(getPorterDuffColorFilter(color, tintMode));
|
||||
|
||||
if (alpha != -1) {
|
||||
drawable.setAlpha(alpha);
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "[tintDrawableUsingColorFilter] Tinted "
|
||||
+ context.getResources().getResourceName(resId) +
|
||||
" with color: #" + Integer.toHexString(color));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addDelegate(@NonNull String tagName, @NonNull InflateDelegate delegate) {
|
||||
if (mDelegates == null) {
|
||||
mDelegates = new ArrayMap<>();
|
||||
}
|
||||
mDelegates.put(tagName, delegate);
|
||||
}
|
||||
|
||||
private void removeDelegate(@NonNull String tagName, @NonNull InflateDelegate delegate) {
|
||||
if (mDelegates != null && mDelegates.get(tagName) == delegate) {
|
||||
mDelegates.remove(tagName);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean arrayContains(int[] array, int value) {
|
||||
for (int id : array) {
|
||||
if (id == value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static PorterDuff.Mode getTintMode(final int resId) {
|
||||
PorterDuff.Mode mode = null;
|
||||
|
||||
if (resId == R.drawable.abc_switch_thumb_material) {
|
||||
mode = PorterDuff.Mode.MULTIPLY;
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
ColorStateList getTintList(@NonNull Context context, @DrawableRes int resId) {
|
||||
// Try the cache first (if it exists)
|
||||
ColorStateList tint = getTintListFromCache(context, resId);
|
||||
|
||||
if (tint == null) {
|
||||
// ...if the cache did not contain a color state list, try and create one
|
||||
if (resId == R.drawable.abc_edit_text_material) {
|
||||
tint = SkinCompatResources.getColorStateList(context, R.color.abc_tint_edittext);
|
||||
} else if (resId == R.drawable.abc_switch_track_mtrl_alpha) {
|
||||
tint = SkinCompatResources.getColorStateList(context, R.color.abc_tint_switch_track);
|
||||
} else if (resId == R.drawable.abc_switch_thumb_material) {
|
||||
tint = createSwitchThumbColorStateList(context);
|
||||
} else if (resId == R.drawable.abc_btn_default_mtrl_shape) {
|
||||
tint = createDefaultButtonColorStateList(context);
|
||||
} else if (resId == R.drawable.abc_btn_borderless_material) {
|
||||
tint = createBorderlessButtonColorStateList(context);
|
||||
} else if (resId == R.drawable.abc_btn_colored_material) {
|
||||
tint = createColoredButtonColorStateList(context);
|
||||
} else if (resId == R.drawable.abc_spinner_mtrl_am_alpha
|
||||
|| resId == R.drawable.abc_spinner_textfield_background_material) {
|
||||
tint = SkinCompatResources.getColorStateList(context, R.color.abc_tint_spinner);
|
||||
} else if (arrayContains(TINT_COLOR_CONTROL_NORMAL, resId)) {
|
||||
tint = getThemeAttrColorStateList(context, R.attr.colorControlNormal);
|
||||
} else if (arrayContains(TINT_COLOR_CONTROL_STATE_LIST, resId)) {
|
||||
tint = SkinCompatResources.getColorStateList(context, R.color.abc_tint_default);
|
||||
} else if (arrayContains(TINT_CHECKABLE_BUTTON_LIST, resId)) {
|
||||
tint = SkinCompatResources.getColorStateList(context, R.color.abc_tint_btn_checkable);
|
||||
} else if (resId == R.drawable.abc_seekbar_thumb_material) {
|
||||
tint = SkinCompatResources.getColorStateList(context, R.color.abc_tint_seek_thumb);
|
||||
}
|
||||
|
||||
if (tint != null) {
|
||||
addTintListToCache(context, resId, tint);
|
||||
}
|
||||
}
|
||||
return tint;
|
||||
}
|
||||
|
||||
private ColorStateList getTintListFromCache(@NonNull Context context, @DrawableRes int resId) {
|
||||
if (mTintLists != null) {
|
||||
final SparseArray<ColorStateList> tints = mTintLists.get(context);
|
||||
return tints != null ? tints.get(resId) : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void addTintListToCache(@NonNull Context context, @DrawableRes int resId,
|
||||
@NonNull ColorStateList tintList) {
|
||||
if (mTintLists == null) {
|
||||
mTintLists = new WeakHashMap<>();
|
||||
}
|
||||
SparseArray<ColorStateList> themeTints = mTintLists.get(context);
|
||||
if (themeTints == null) {
|
||||
themeTints = new SparseArray<>();
|
||||
mTintLists.put(context, themeTints);
|
||||
}
|
||||
themeTints.append(resId, tintList);
|
||||
}
|
||||
|
||||
private ColorStateList createDefaultButtonColorStateList(@NonNull Context context) {
|
||||
return createButtonColorStateList(context,
|
||||
getThemeAttrColor(context, R.attr.colorButtonNormal));
|
||||
}
|
||||
|
||||
private ColorStateList createBorderlessButtonColorStateList(@NonNull Context context) {
|
||||
// We ignore the custom tint for borderless buttons
|
||||
return createButtonColorStateList(context, Color.TRANSPARENT);
|
||||
}
|
||||
|
||||
private ColorStateList createColoredButtonColorStateList(@NonNull Context context) {
|
||||
return createButtonColorStateList(context,
|
||||
getThemeAttrColor(context, R.attr.colorAccent));
|
||||
}
|
||||
|
||||
private ColorStateList createButtonColorStateList(@NonNull final Context context,
|
||||
@ColorInt final int baseColor) {
|
||||
final int[][] states = new int[4][];
|
||||
final int[] colors = new int[4];
|
||||
int i = 0;
|
||||
|
||||
final int colorControlHighlight = getThemeAttrColor(context, R.attr.colorControlHighlight);
|
||||
final int disabledColor = getDisabledThemeAttrColor(context, R.attr.colorButtonNormal);
|
||||
|
||||
// Disabled state
|
||||
states[i] = SkinCompatThemeUtils.DISABLED_STATE_SET;
|
||||
colors[i] = disabledColor;
|
||||
i++;
|
||||
|
||||
states[i] = SkinCompatThemeUtils.PRESSED_STATE_SET;
|
||||
colors[i] = compositeColors(colorControlHighlight, baseColor);
|
||||
i++;
|
||||
|
||||
states[i] = SkinCompatThemeUtils.FOCUSED_STATE_SET;
|
||||
colors[i] = compositeColors(colorControlHighlight, baseColor);
|
||||
i++;
|
||||
|
||||
// Default enabled state
|
||||
states[i] = SkinCompatThemeUtils.EMPTY_STATE_SET;
|
||||
colors[i] = baseColor;
|
||||
i++;
|
||||
|
||||
return new ColorStateList(states, colors);
|
||||
}
|
||||
|
||||
private ColorStateList createSwitchThumbColorStateList(Context context) {
|
||||
final int[][] states = new int[3][];
|
||||
final int[] colors = new int[3];
|
||||
int i = 0;
|
||||
|
||||
final ColorStateList thumbColor = SkinCompatThemeUtils.getThemeAttrColorStateList(context,
|
||||
R.attr.colorSwitchThumbNormal);
|
||||
|
||||
if (thumbColor != null && thumbColor.isStateful()) {
|
||||
// If colorSwitchThumbNormal is a valid ColorStateList, extract the default and
|
||||
// disabled colors from it
|
||||
|
||||
// Disabled state
|
||||
states[i] = SkinCompatThemeUtils.DISABLED_STATE_SET;
|
||||
colors[i] = thumbColor.getColorForState(states[i], 0);
|
||||
i++;
|
||||
|
||||
states[i] = SkinCompatThemeUtils.CHECKED_STATE_SET;
|
||||
colors[i] = SkinCompatThemeUtils.getThemeAttrColor(context, R.attr.colorControlActivated);
|
||||
i++;
|
||||
|
||||
// Default enabled state
|
||||
states[i] = SkinCompatThemeUtils.EMPTY_STATE_SET;
|
||||
colors[i] = thumbColor.getDefaultColor();
|
||||
i++;
|
||||
} else {
|
||||
// Else we'll use an approximation using the default disabled alpha
|
||||
|
||||
// Disabled state
|
||||
states[i] = SkinCompatThemeUtils.DISABLED_STATE_SET;
|
||||
colors[i] = SkinCompatThemeUtils.getDisabledThemeAttrColor(context, R.attr.colorSwitchThumbNormal);
|
||||
i++;
|
||||
|
||||
states[i] = SkinCompatThemeUtils.CHECKED_STATE_SET;
|
||||
colors[i] = SkinCompatThemeUtils.getThemeAttrColor(context, R.attr.colorControlActivated);
|
||||
i++;
|
||||
|
||||
// Default enabled state
|
||||
states[i] = SkinCompatThemeUtils.EMPTY_STATE_SET;
|
||||
colors[i] = SkinCompatThemeUtils.getThemeAttrColor(context, R.attr.colorSwitchThumbNormal);
|
||||
i++;
|
||||
}
|
||||
|
||||
return new ColorStateList(states, colors);
|
||||
}
|
||||
|
||||
private static class ColorFilterLruCache extends LruCache<Integer, PorterDuffColorFilter> {
|
||||
|
||||
public ColorFilterLruCache(int maxSize) {
|
||||
super(maxSize);
|
||||
}
|
||||
|
||||
PorterDuffColorFilter get(int color, PorterDuff.Mode mode) {
|
||||
return get(generateCacheKey(color, mode));
|
||||
}
|
||||
|
||||
PorterDuffColorFilter put(int color, PorterDuff.Mode mode, PorterDuffColorFilter filter) {
|
||||
return put(generateCacheKey(color, mode), filter);
|
||||
}
|
||||
|
||||
private static int generateCacheKey(int color, PorterDuff.Mode mode) {
|
||||
int hashCode = 1;
|
||||
hashCode = 31 * hashCode + color;
|
||||
hashCode = 31 * hashCode + mode.hashCode();
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
private static PorterDuffColorFilter createTintFilter(ColorStateList tint,
|
||||
PorterDuff.Mode tintMode, final int[] state) {
|
||||
if (tint == null || tintMode == null) {
|
||||
return null;
|
||||
}
|
||||
final int color = tint.getColorForState(state, Color.TRANSPARENT);
|
||||
return getPorterDuffColorFilter(color, tintMode);
|
||||
}
|
||||
|
||||
public static PorterDuffColorFilter getPorterDuffColorFilter(int color, PorterDuff.Mode mode) {
|
||||
// First, lets see if the cache already contains the color filter
|
||||
PorterDuffColorFilter filter = COLOR_FILTER_CACHE.get(color, mode);
|
||||
|
||||
if (filter == null) {
|
||||
// Cache miss, so create a color filter and add it to the cache
|
||||
filter = new PorterDuffColorFilter(color, mode);
|
||||
COLOR_FILTER_CACHE.put(color, mode, filter);
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
private static void setPorterDuffColorFilter(Drawable d, int color, PorterDuff.Mode mode) {
|
||||
if (SkinCompatDrawableUtils.canSafelyMutateDrawable(d)) {
|
||||
d = d.mutate();
|
||||
}
|
||||
d.setColorFilter(getPorterDuffColorFilter(color, mode == null ? DEFAULT_MODE : mode));
|
||||
}
|
||||
|
||||
private void checkVectorDrawableSetup(@NonNull Context context) {
|
||||
if (mHasCheckedVectorDrawableSetup) {
|
||||
// We've already checked so return now...
|
||||
return;
|
||||
}
|
||||
// Here we will check that a known Vector drawable resource inside AppCompat can be
|
||||
// correctly decoded
|
||||
mHasCheckedVectorDrawableSetup = true;
|
||||
final Drawable d = getDrawable(context, R.drawable.abc_vector_test);
|
||||
if (d == null || !isVectorDrawable(d)) {
|
||||
mHasCheckedVectorDrawableSetup = false;
|
||||
throw new IllegalStateException("This app has been built with an incorrect "
|
||||
+ "configuration. Please configure your build for VectorDrawableCompat.");
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isVectorDrawable(@NonNull Drawable d) {
|
||||
return d instanceof VectorDrawableCompat
|
||||
|| PLATFORM_VD_CLAZZ.equals(d.getClass().getName());
|
||||
}
|
||||
|
||||
private static class VdcInflateDelegate implements InflateDelegate {
|
||||
VdcInflateDelegate() {
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Override
|
||||
public Drawable createFromXmlInner(@NonNull Context context, @NonNull XmlPullParser parser,
|
||||
@NonNull AttributeSet attrs, @Nullable Resources.Theme theme) {
|
||||
try {
|
||||
return VectorDrawableCompat
|
||||
.createFromXmlInner(context.getResources(), parser, attrs, theme);
|
||||
} catch (Exception e) {
|
||||
Log.e("VdcInflateDelegate", "Exception while inflating <vector>", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(11)
|
||||
@TargetApi(11)
|
||||
private static class AvdcInflateDelegate implements InflateDelegate {
|
||||
AvdcInflateDelegate() {
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Override
|
||||
public Drawable createFromXmlInner(@NonNull Context context, @NonNull XmlPullParser parser,
|
||||
@NonNull AttributeSet attrs, @Nullable Resources.Theme theme) {
|
||||
try {
|
||||
return AnimatedVectorDrawableCompat
|
||||
.createFromXmlInner(context, context.getResources(), parser, attrs, theme);
|
||||
} catch (Exception e) {
|
||||
Log.e("AvdcInflateDelegate", "Exception while inflating <animated-vector>", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package skin.support.content.res;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.DrawableContainer;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.graphics.drawable.InsetDrawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.graphics.drawable.ScaleDrawable;
|
||||
import android.os.Build;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import skin.support.utils.SkinCompatVersionUtils;
|
||||
|
||||
class SkinCompatDrawableUtils {
|
||||
|
||||
private static final String VECTOR_DRAWABLE_CLAZZ_NAME
|
||||
= "android.graphics.drawable.VectorDrawable";
|
||||
|
||||
/**
|
||||
* Attempt the fix any issues in the given drawable, usually caused by platform bugs in the
|
||||
* implementation. This method should be call after retrieval from
|
||||
* {@link android.content.res.Resources} or a {@link android.content.res.TypedArray}.
|
||||
*/
|
||||
static void fixDrawable(@NonNull final Drawable drawable) {
|
||||
if (Build.VERSION.SDK_INT == 21
|
||||
&& VECTOR_DRAWABLE_CLAZZ_NAME.equals(drawable.getClass().getName())) {
|
||||
fixVectorDrawableTinting(drawable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Some drawable implementations have problems with mutation. This method returns false if
|
||||
* there is a known issue in the given drawable's implementation.
|
||||
*/
|
||||
public static boolean canSafelyMutateDrawable(@NonNull Drawable drawable) {
|
||||
if (Build.VERSION.SDK_INT < 15 && drawable instanceof InsetDrawable) {
|
||||
return false;
|
||||
} else if (Build.VERSION.SDK_INT < 15 && drawable instanceof GradientDrawable) {
|
||||
// GradientDrawable has a bug pre-ICS which results in mutate() resulting
|
||||
// in loss of color
|
||||
return false;
|
||||
} else if (Build.VERSION.SDK_INT < 17 && drawable instanceof LayerDrawable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (drawable instanceof DrawableContainer) {
|
||||
// If we have a DrawableContainer, let's traverse it's child array
|
||||
final Drawable.ConstantState state = drawable.getConstantState();
|
||||
if (state instanceof DrawableContainer.DrawableContainerState) {
|
||||
final DrawableContainer.DrawableContainerState containerState =
|
||||
(DrawableContainer.DrawableContainerState) state;
|
||||
for (final Drawable child : containerState.getChildren()) {
|
||||
if (!canSafelyMutateDrawable(child)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (SkinCompatVersionUtils.isV4DrawableWrapper(drawable)) {
|
||||
return canSafelyMutateDrawable(SkinCompatVersionUtils.getV4DrawableWrapperWrappedDrawable(drawable));
|
||||
} else if (SkinCompatVersionUtils.isV4WrappedDrawable(drawable)) {
|
||||
return canSafelyMutateDrawable(SkinCompatVersionUtils.getV4WrappedDrawableWrappedDrawable(drawable));
|
||||
} else if (SkinCompatVersionUtils.isV7DrawableWrapper(drawable)) {
|
||||
return canSafelyMutateDrawable(SkinCompatVersionUtils.getV7DrawableWrapperWrappedDrawable(drawable));
|
||||
} else if (drawable instanceof ScaleDrawable) {
|
||||
Drawable scaleDrawable = ((ScaleDrawable) drawable).getDrawable();
|
||||
if (scaleDrawable != null) {
|
||||
return canSafelyMutateDrawable(scaleDrawable);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* VectorDrawable has an issue on API 21 where it sometimes doesn't create its tint filter.
|
||||
* Fixed by toggling it's state to force a filter creation.
|
||||
*/
|
||||
private static void fixVectorDrawableTinting(final Drawable drawable) {
|
||||
final int[] originalState = drawable.getState();
|
||||
if (originalState == null || originalState.length == 0) {
|
||||
// The drawable doesn't have a state, so set it to be checked
|
||||
drawable.setState(SkinCompatThemeUtils.CHECKED_STATE_SET);
|
||||
} else {
|
||||
// Else the drawable does have a state, so clear it
|
||||
drawable.setState(SkinCompatThemeUtils.EMPTY_STATE_SET);
|
||||
}
|
||||
// Now set the original state
|
||||
drawable.setState(originalState);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package skin.support.content.res;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import static skin.support.content.res.SkinCompatThemeUtils.getResId;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 2017/3/25.
|
||||
*/
|
||||
|
||||
public class SkinCompatV7ThemeUtils {
|
||||
|
||||
private static final int[] APPCOMPAT_COLOR_PRIMARY_ATTRS = {
|
||||
androidx.appcompat.R.attr.colorPrimary
|
||||
};
|
||||
private static final int[] APPCOMPAT_COLOR_PRIMARY_DARK_ATTRS = {
|
||||
androidx.appcompat.R.attr.colorPrimaryDark
|
||||
};
|
||||
private static final int[] APPCOMPAT_COLOR_ACCENT_ATTRS = {
|
||||
androidx.appcompat.R.attr.colorAccent
|
||||
};
|
||||
|
||||
public static int getColorPrimaryResId(Context context) {
|
||||
return getResId(context, APPCOMPAT_COLOR_PRIMARY_ATTRS);
|
||||
}
|
||||
|
||||
public static int getColorPrimaryDarkResId(Context context) {
|
||||
return getResId(context, APPCOMPAT_COLOR_PRIMARY_DARK_ATTRS);
|
||||
}
|
||||
|
||||
public static int getColorAccentResId(Context context) {
|
||||
return getResId(context, APPCOMPAT_COLOR_ACCENT_ATTRS);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package skin.support.content.res;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
|
||||
public class SkinCompatVectorResources implements SkinResources {
|
||||
private static SkinCompatVectorResources sInstance;
|
||||
|
||||
private SkinCompatVectorResources() {
|
||||
SkinCompatResources.getInstance().addSkinResources(this);
|
||||
}
|
||||
|
||||
public static SkinCompatVectorResources getInstance() {
|
||||
if (sInstance == null) {
|
||||
synchronized (SkinCompatVectorResources.class) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new SkinCompatVectorResources();
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
SkinCompatDrawableManager.get().clearCaches();
|
||||
}
|
||||
|
||||
private Drawable getSkinDrawableCompat(Context context, int resId) {
|
||||
if (AppCompatDelegate.isCompatVectorFromResourcesEnabled()) {
|
||||
if (!SkinCompatResources.getInstance().isDefaultSkin()) {
|
||||
try {
|
||||
return SkinCompatDrawableManager.get().getDrawable(context, resId);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// SkinCompatDrawableManager.get().getDrawable(context, resId) 中会调用getSkinDrawable等方法。
|
||||
// 这里只需要拦截使用默认皮肤的情况。
|
||||
if (!SkinCompatUserThemeManager.get().isColorEmpty()) {
|
||||
ColorStateList colorStateList = SkinCompatUserThemeManager.get().getColorStateList(resId);
|
||||
if (colorStateList != null) {
|
||||
return new ColorDrawable(colorStateList.getDefaultColor());
|
||||
}
|
||||
}
|
||||
if (!SkinCompatUserThemeManager.get().isDrawableEmpty()) {
|
||||
Drawable drawable = SkinCompatUserThemeManager.get().getDrawable(resId);
|
||||
if (drawable != null) {
|
||||
return drawable;
|
||||
}
|
||||
}
|
||||
Drawable drawable = SkinCompatResources.getInstance().getStrategyDrawable(context, resId);
|
||||
if (drawable != null) {
|
||||
return drawable;
|
||||
}
|
||||
return AppCompatResources.getDrawable(context, resId);
|
||||
} else {
|
||||
if (!SkinCompatUserThemeManager.get().isColorEmpty()) {
|
||||
ColorStateList colorStateList = SkinCompatUserThemeManager.get().getColorStateList(resId);
|
||||
if (colorStateList != null) {
|
||||
return new ColorDrawable(colorStateList.getDefaultColor());
|
||||
}
|
||||
}
|
||||
if (!SkinCompatUserThemeManager.get().isDrawableEmpty()) {
|
||||
Drawable drawable = SkinCompatUserThemeManager.get().getDrawable(resId);
|
||||
if (drawable != null) {
|
||||
return drawable;
|
||||
}
|
||||
}
|
||||
Drawable drawable = SkinCompatResources.getInstance().getStrategyDrawable(context, resId);
|
||||
if (drawable != null) {
|
||||
return drawable;
|
||||
}
|
||||
if (!SkinCompatResources.getInstance().isDefaultSkin()) {
|
||||
int targetResId = SkinCompatResources.getInstance().getTargetResId(context, resId);
|
||||
if (targetResId != 0) {
|
||||
return SkinCompatResources.getInstance().getSkinResources().getDrawable(targetResId);
|
||||
}
|
||||
}
|
||||
return AppCompatResources.getDrawable(context, resId);
|
||||
}
|
||||
}
|
||||
|
||||
public static Drawable getDrawableCompat(Context context, int resId) {
|
||||
return getInstance().getSkinDrawableCompat(context, resId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.appcompat.widget.AppCompatAutoCompleteTextView;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import skin.support.appcompat.R;
|
||||
import skin.support.content.res.SkinCompatVectorResources;
|
||||
|
||||
import static skin.support.widget.SkinCompatHelper.INVALID_ID;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 2017/1/13.
|
||||
*/
|
||||
|
||||
public class SkinCompatAutoCompleteTextView extends AppCompatAutoCompleteTextView implements SkinCompatSupportable {
|
||||
private static final int[] TINT_ATTRS = {
|
||||
android.R.attr.popupBackground
|
||||
};
|
||||
private int mDropDownBackgroundResId = INVALID_ID;
|
||||
private SkinCompatTextHelper mTextHelper;
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinCompatAutoCompleteTextView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatAutoCompleteTextView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.autoCompleteTextViewStyle);
|
||||
}
|
||||
|
||||
public SkinCompatAutoCompleteTextView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, TINT_ATTRS, defStyleAttr, 0);
|
||||
if (a.hasValue(0)) {
|
||||
mDropDownBackgroundResId = a.getResourceId(0, INVALID_ID);
|
||||
}
|
||||
a.recycle();
|
||||
applyDropDownBackgroundResource();
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
mTextHelper = SkinCompatTextHelper.create(this);
|
||||
mTextHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDropDownBackgroundResource(@DrawableRes int resId) {
|
||||
super.setDropDownBackgroundResource(resId);
|
||||
mDropDownBackgroundResId = resId;
|
||||
applyDropDownBackgroundResource();
|
||||
}
|
||||
|
||||
private void applyDropDownBackgroundResource() {
|
||||
mDropDownBackgroundResId = SkinCompatHelper.checkResourceId(mDropDownBackgroundResId);
|
||||
if (mDropDownBackgroundResId != INVALID_ID) {
|
||||
Drawable drawable = SkinCompatVectorResources.getDrawableCompat(getContext(), mDropDownBackgroundResId);
|
||||
if (drawable != null) {
|
||||
setDropDownBackgroundDrawable(drawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(@DrawableRes int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextAppearance(int resId) {
|
||||
setTextAppearance(getContext(), resId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextAppearance(Context context, int resId) {
|
||||
super.setTextAppearance(context, resId);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetTextAppearance(context, resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompoundDrawablesRelativeWithIntrinsicBounds(
|
||||
@DrawableRes int start, @DrawableRes int top, @DrawableRes int end, @DrawableRes int bottom) {
|
||||
super.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompoundDrawablesWithIntrinsicBounds(
|
||||
@DrawableRes int left, @DrawableRes int top, @DrawableRes int right, @DrawableRes int bottom) {
|
||||
super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.applySkin();
|
||||
}
|
||||
applyDropDownBackgroundResource();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import skin.support.R;
|
||||
import skin.support.content.res.SkinCompatVectorResources;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 2017/1/10.
|
||||
*/
|
||||
|
||||
public class SkinCompatBackgroundHelper extends SkinCompatHelper {
|
||||
private final View mView;
|
||||
|
||||
private int mBackgroundResId = INVALID_ID;
|
||||
|
||||
public SkinCompatBackgroundHelper(View view) {
|
||||
mView = view;
|
||||
}
|
||||
|
||||
public void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
|
||||
TypedArray a = mView.getContext().obtainStyledAttributes(attrs, R.styleable.SkinBackgroundHelper, defStyleAttr, 0);
|
||||
try {
|
||||
if (a.hasValue(R.styleable.SkinBackgroundHelper_android_background)) {
|
||||
mBackgroundResId = a.getResourceId(
|
||||
R.styleable.SkinBackgroundHelper_android_background, INVALID_ID);
|
||||
}
|
||||
} finally {
|
||||
a.recycle();
|
||||
}
|
||||
applySkin();
|
||||
}
|
||||
|
||||
public void onSetBackgroundResource(int resId) {
|
||||
mBackgroundResId = resId;
|
||||
// Update the default background tint
|
||||
applySkin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
mBackgroundResId = checkResourceId(mBackgroundResId);
|
||||
if (mBackgroundResId == INVALID_ID) {
|
||||
return;
|
||||
}
|
||||
Drawable drawable = SkinCompatVectorResources.getDrawableCompat(mView.getContext(), mBackgroundResId);
|
||||
if (drawable != null) {
|
||||
int paddingLeft = mView.getPaddingLeft();
|
||||
int paddingTop = mView.getPaddingTop();
|
||||
int paddingRight = mView.getPaddingRight();
|
||||
int paddingBottom = mView.getPaddingBottom();
|
||||
ViewCompat.setBackground(mView, drawable);
|
||||
mView.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.appcompat.R;
|
||||
import androidx.appcompat.widget.AppCompatButton;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 17-1-11.
|
||||
*/
|
||||
public class SkinCompatButton extends AppCompatButton implements SkinCompatSupportable {
|
||||
private SkinCompatTextHelper mTextHelper;
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinCompatButton(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatButton(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.buttonStyle);
|
||||
}
|
||||
|
||||
public SkinCompatButton(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
mTextHelper = SkinCompatTextHelper.create(this);
|
||||
mTextHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(@DrawableRes int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextAppearance(int resId) {
|
||||
setTextAppearance(getContext(), resId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextAppearance(Context context, int resId) {
|
||||
super.setTextAppearance(context, resId);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetTextAppearance(context, resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompoundDrawablesRelativeWithIntrinsicBounds(
|
||||
@DrawableRes int start, @DrawableRes int top, @DrawableRes int end, @DrawableRes int bottom) {
|
||||
super.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompoundDrawablesWithIntrinsicBounds(
|
||||
@DrawableRes int left, @DrawableRes int top, @DrawableRes int right, @DrawableRes int bottom) {
|
||||
super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.appcompat.widget.AppCompatCheckBox;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import skin.support.appcompat.R;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 17-1-14.
|
||||
*/
|
||||
|
||||
public class SkinCompatCheckBox extends AppCompatCheckBox implements SkinCompatSupportable {
|
||||
private SkinCompatCompoundButtonHelper mCompoundButtonHelper;
|
||||
private SkinCompatTextHelper mTextHelper;
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinCompatCheckBox(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatCheckBox(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.checkboxStyle);
|
||||
}
|
||||
|
||||
public SkinCompatCheckBox(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mCompoundButtonHelper = new SkinCompatCompoundButtonHelper(this);
|
||||
mCompoundButtonHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
mTextHelper = SkinCompatTextHelper.create(this);
|
||||
mTextHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setButtonDrawable(@DrawableRes int resId) {
|
||||
super.setButtonDrawable(resId);
|
||||
if (mCompoundButtonHelper != null) {
|
||||
mCompoundButtonHelper.setButtonDrawable(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(@DrawableRes int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextAppearance(int resId) {
|
||||
setTextAppearance(getContext(), resId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextAppearance(Context context, int resId) {
|
||||
super.setTextAppearance(context, resId);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetTextAppearance(context, resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompoundDrawablesRelativeWithIntrinsicBounds(
|
||||
@DrawableRes int start, @DrawableRes int top, @DrawableRes int end, @DrawableRes int bottom) {
|
||||
super.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompoundDrawablesWithIntrinsicBounds(
|
||||
@DrawableRes int left, @DrawableRes int top, @DrawableRes int right, @DrawableRes int bottom) {
|
||||
super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mCompoundButtonHelper != null) {
|
||||
mCompoundButtonHelper.applySkin();
|
||||
}
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.appcompat.widget.AppCompatCheckedTextView;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import skin.support.appcompat.R;
|
||||
import skin.support.content.res.SkinCompatVectorResources;
|
||||
|
||||
import static skin.support.widget.SkinCompatHelper.INVALID_ID;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 17-1-14.
|
||||
*/
|
||||
|
||||
public class SkinCompatCheckedTextView extends AppCompatCheckedTextView implements SkinCompatSupportable {
|
||||
|
||||
private static final int[] TINT_ATTRS = {
|
||||
android.R.attr.checkMark
|
||||
};
|
||||
private int mCheckMarkResId = INVALID_ID;
|
||||
|
||||
private SkinCompatTextHelper mTextHelper;
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinCompatCheckedTextView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatCheckedTextView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.checkedTextViewStyle);
|
||||
}
|
||||
|
||||
public SkinCompatCheckedTextView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
mTextHelper = SkinCompatTextHelper.create(this);
|
||||
mTextHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, TINT_ATTRS, defStyleAttr, 0);
|
||||
mCheckMarkResId = a.getResourceId(0, INVALID_ID);
|
||||
a.recycle();
|
||||
applyCheckMark();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCheckMarkDrawable(@DrawableRes int resId) {
|
||||
mCheckMarkResId = resId;
|
||||
applyCheckMark();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(@DrawableRes int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextAppearance(int resId) {
|
||||
setTextAppearance(getContext(), resId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextAppearance(Context context, int resId) {
|
||||
super.setTextAppearance(context, resId);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetTextAppearance(context, resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompoundDrawablesRelativeWithIntrinsicBounds(
|
||||
@DrawableRes int start, @DrawableRes int top, @DrawableRes int end, @DrawableRes int bottom) {
|
||||
super.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompoundDrawablesWithIntrinsicBounds(
|
||||
@DrawableRes int left, @DrawableRes int top, @DrawableRes int right, @DrawableRes int bottom) {
|
||||
super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.applySkin();
|
||||
}
|
||||
applyCheckMark();
|
||||
}
|
||||
|
||||
private void applyCheckMark() {
|
||||
mCheckMarkResId = SkinCompatHelper.checkResourceId(mCheckMarkResId);
|
||||
if (mCheckMarkResId != INVALID_ID) {
|
||||
setCheckMarkDrawable(SkinCompatVectorResources.getDrawableCompat(getContext(), mCheckMarkResId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.res.TypedArray;
|
||||
import androidx.core.widget.CompoundButtonCompat;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.CompoundButton;
|
||||
|
||||
import skin.support.appcompat.R;
|
||||
import skin.support.content.res.SkinCompatResources;
|
||||
import skin.support.content.res.SkinCompatVectorResources;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 17-1-14.
|
||||
*/
|
||||
public class SkinCompatCompoundButtonHelper extends SkinCompatHelper {
|
||||
private final CompoundButton mView;
|
||||
private int mButtonResourceId = INVALID_ID;
|
||||
private int mButtonTintResId = INVALID_ID;
|
||||
|
||||
public SkinCompatCompoundButtonHelper(CompoundButton view) {
|
||||
mView = view;
|
||||
}
|
||||
|
||||
void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
|
||||
TypedArray a = mView.getContext().obtainStyledAttributes(attrs, R.styleable.CompoundButton,
|
||||
defStyleAttr, INVALID_ID);
|
||||
try {
|
||||
if (a.hasValue(R.styleable.CompoundButton_android_button)) {
|
||||
mButtonResourceId = a.getResourceId(
|
||||
R.styleable.CompoundButton_android_button, INVALID_ID);
|
||||
}
|
||||
|
||||
if (a.hasValue(R.styleable.CompoundButton_buttonTint)) {
|
||||
mButtonTintResId = a.getResourceId(R.styleable.CompoundButton_buttonTint, INVALID_ID);
|
||||
}
|
||||
} finally {
|
||||
a.recycle();
|
||||
}
|
||||
applySkin();
|
||||
}
|
||||
|
||||
public void setButtonDrawable(int resId) {
|
||||
mButtonResourceId = resId;
|
||||
applySkin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
mButtonResourceId = SkinCompatHelper.checkResourceId(mButtonResourceId);
|
||||
if (mButtonResourceId != INVALID_ID) {
|
||||
mView.setButtonDrawable(SkinCompatVectorResources.getDrawableCompat(mView.getContext(), mButtonResourceId));
|
||||
}
|
||||
mButtonTintResId = SkinCompatHelper.checkResourceId(mButtonTintResId);
|
||||
if (mButtonTintResId != INVALID_ID) {
|
||||
CompoundButtonCompat.setButtonTintList(mView, SkinCompatResources.getColorStateList(mView.getContext(), mButtonTintResId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.appcompat.R;
|
||||
import androidx.appcompat.widget.AppCompatEditText;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import static skin.support.widget.SkinCompatHelper.INVALID_ID;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 2017/1/10.
|
||||
*/
|
||||
|
||||
public class SkinCompatEditText extends AppCompatEditText implements SkinCompatSupportable {
|
||||
private SkinCompatTextHelper mTextHelper;
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinCompatEditText(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatEditText(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.editTextStyle);
|
||||
}
|
||||
|
||||
public SkinCompatEditText(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
mTextHelper = SkinCompatTextHelper.create(this);
|
||||
mTextHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(@DrawableRes int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextAppearance(int resId) {
|
||||
setTextAppearance(getContext(), resId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextAppearance(Context context, int resId) {
|
||||
super.setTextAppearance(context, resId);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetTextAppearance(context, resId);
|
||||
}
|
||||
}
|
||||
|
||||
public int getTextColorResId() {
|
||||
return mTextHelper != null ? mTextHelper.getTextColorResId() : INVALID_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompoundDrawablesRelativeWithIntrinsicBounds(
|
||||
@DrawableRes int start, @DrawableRes int top, @DrawableRes int end, @DrawableRes int bottom) {
|
||||
super.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompoundDrawablesWithIntrinsicBounds(
|
||||
@DrawableRes int left, @DrawableRes int top, @DrawableRes int right, @DrawableRes int bottom) {
|
||||
super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
/**
|
||||
* Created by pengfengwang on 2017/1/13.
|
||||
*/
|
||||
|
||||
public class SkinCompatFrameLayout extends FrameLayout implements SkinCompatSupportable {
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinCompatFrameLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatFrameLayout(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SkinCompatFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.appcompat.R;
|
||||
import androidx.appcompat.widget.AppCompatImageButton;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 17-1-13.
|
||||
*/
|
||||
|
||||
public class SkinCompatImageButton extends AppCompatImageButton implements SkinCompatSupportable {
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
private SkinCompatImageHelper mImageHelper;
|
||||
|
||||
public SkinCompatImageButton(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatImageButton(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.imageButtonStyle);
|
||||
}
|
||||
|
||||
public SkinCompatImageButton(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
|
||||
mImageHelper = new SkinCompatImageHelper(this);
|
||||
mImageHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(@DrawableRes int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageResource(@DrawableRes int resId) {
|
||||
// Intercept this call and instead retrieve the Drawable via the image helper
|
||||
if (mImageHelper != null) {
|
||||
mImageHelper.setImageResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
if (mImageHelper != null) {
|
||||
mImageHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.core.widget.ImageViewCompat;
|
||||
|
||||
import skin.support.R;
|
||||
import skin.support.content.res.SkinCompatResources;
|
||||
import skin.support.content.res.SkinCompatVectorResources;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 2017/1/12.
|
||||
*/
|
||||
public class SkinCompatImageHelper extends SkinCompatHelper {
|
||||
private static final String TAG = SkinCompatImageHelper.class.getSimpleName();
|
||||
private final ImageView mView;
|
||||
private int mSrcResId = INVALID_ID;
|
||||
private int mSrcCompatResId = INVALID_ID;
|
||||
private int mSrcTintResId = INVALID_ID;
|
||||
|
||||
public SkinCompatImageHelper(ImageView imageView) {
|
||||
mView = imageView;
|
||||
}
|
||||
|
||||
public void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
|
||||
TypedArray a = null;
|
||||
try {
|
||||
a = mView.getContext().obtainStyledAttributes(attrs, R.styleable.SkinCompatImageView, defStyleAttr, 0);
|
||||
mSrcResId = a.getResourceId(R.styleable.SkinCompatImageView_android_src, INVALID_ID);
|
||||
mSrcCompatResId = a.getResourceId(R.styleable.SkinCompatImageView_srcCompat, INVALID_ID);
|
||||
mSrcTintResId = a.getResourceId(R.styleable.SkinCompatImageView_tint, INVALID_ID);
|
||||
if (mSrcTintResId == INVALID_ID) {
|
||||
mSrcTintResId = a.getResourceId(R.styleable.SkinCompatImageView_android_tint, INVALID_ID);
|
||||
}
|
||||
} finally {
|
||||
if (a != null) {
|
||||
a.recycle();
|
||||
}
|
||||
}
|
||||
applySkin();
|
||||
}
|
||||
|
||||
public void setImageResource(int resId) {
|
||||
mSrcResId = resId;
|
||||
mSrcCompatResId = INVALID_ID;
|
||||
applySkin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
mSrcCompatResId = checkResourceId(mSrcCompatResId);
|
||||
if (mSrcCompatResId != INVALID_ID) {
|
||||
Drawable drawable = SkinCompatVectorResources.getDrawableCompat(mView.getContext(), mSrcCompatResId);
|
||||
if (drawable != null) {
|
||||
mView.setImageDrawable(drawable);
|
||||
}
|
||||
} else {
|
||||
mSrcResId = checkResourceId(mSrcResId);
|
||||
if (mSrcResId != INVALID_ID) {
|
||||
Drawable drawable = SkinCompatVectorResources.getDrawableCompat(mView.getContext(), mSrcResId);
|
||||
if (drawable != null) {
|
||||
mView.setImageDrawable(drawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
mSrcTintResId = checkResourceId(mSrcTintResId);
|
||||
if (mSrcTintResId != INVALID_ID) {
|
||||
ColorStateList tintList = SkinCompatResources.getColorStateList(mView.getContext(), mSrcTintResId);
|
||||
ImageViewCompat.setImageTintList(mView, tintList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 2017/1/10.
|
||||
*/
|
||||
|
||||
public class SkinCompatImageView extends AppCompatImageView implements SkinCompatSupportable {
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
private SkinCompatImageHelper mImageHelper;
|
||||
|
||||
public SkinCompatImageView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatImageView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SkinCompatImageView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
|
||||
mImageHelper = new SkinCompatImageHelper(this);
|
||||
mImageHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(@DrawableRes int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageResource(@DrawableRes int resId) {
|
||||
// Intercept this call and instead retrieve the Drawable via the image helper
|
||||
if (mImageHelper != null) {
|
||||
mImageHelper.setImageResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
if (mImageHelper != null) {
|
||||
mImageHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
/**
|
||||
* Created by pengfengwang on 2017/1/13.
|
||||
*/
|
||||
|
||||
public class SkinCompatLinearLayout extends LinearLayout implements SkinCompatSupportable {
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinCompatLinearLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatLinearLayout(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SkinCompatLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.appcompat.widget.AppCompatMultiAutoCompleteTextView;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import skin.support.appcompat.R;
|
||||
import skin.support.content.res.SkinCompatVectorResources;
|
||||
|
||||
import static skin.support.widget.SkinCompatHelper.INVALID_ID;
|
||||
|
||||
/**
|
||||
* @author ximsfei
|
||||
* @date 17-1-14
|
||||
*/
|
||||
|
||||
public class SkinCompatMultiAutoCompleteTextView extends AppCompatMultiAutoCompleteTextView implements SkinCompatSupportable {
|
||||
private static final int[] TINT_ATTRS = {
|
||||
android.R.attr.popupBackground
|
||||
};
|
||||
private int mDropDownBackgroundResId = INVALID_ID;
|
||||
private SkinCompatTextHelper mTextHelper;
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinCompatMultiAutoCompleteTextView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatMultiAutoCompleteTextView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.editTextStyle);
|
||||
}
|
||||
|
||||
public SkinCompatMultiAutoCompleteTextView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, TINT_ATTRS, defStyleAttr, 0);
|
||||
if (a.hasValue(0)) {
|
||||
mDropDownBackgroundResId = a.getResourceId(0, INVALID_ID);
|
||||
}
|
||||
a.recycle();
|
||||
applyDropDownBackgroundResource();
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
mTextHelper = SkinCompatTextHelper.create(this);
|
||||
mTextHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDropDownBackgroundResource(@DrawableRes int resId) {
|
||||
super.setDropDownBackgroundResource(resId);
|
||||
mDropDownBackgroundResId = resId;
|
||||
applyDropDownBackgroundResource();
|
||||
}
|
||||
|
||||
private void applyDropDownBackgroundResource() {
|
||||
mDropDownBackgroundResId = SkinCompatHelper.checkResourceId(mDropDownBackgroundResId);
|
||||
if (mDropDownBackgroundResId != INVALID_ID) {
|
||||
Drawable drawable = SkinCompatVectorResources.getDrawableCompat(getContext(), mDropDownBackgroundResId);
|
||||
if (drawable != null) {
|
||||
setDropDownBackgroundDrawable(drawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(@DrawableRes int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextAppearance(int resId) {
|
||||
setTextAppearance(getContext(), resId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextAppearance(Context context, int resId) {
|
||||
super.setTextAppearance(context, resId);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetTextAppearance(context, resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompoundDrawablesRelativeWithIntrinsicBounds(
|
||||
@DrawableRes int start, @DrawableRes int top, @DrawableRes int end, @DrawableRes int bottom) {
|
||||
super.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompoundDrawablesWithIntrinsicBounds(
|
||||
@DrawableRes int left, @DrawableRes int top, @DrawableRes int right, @DrawableRes int bottom) {
|
||||
super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.applySkin();
|
||||
}
|
||||
applyDropDownBackgroundResource();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 2017/1/19.
|
||||
*/
|
||||
|
||||
public class SkinCompatProgressBar extends ProgressBar implements SkinCompatSupportable {
|
||||
private SkinCompatProgressBarHelper mSkinCompatProgressBarHelper;
|
||||
|
||||
public SkinCompatProgressBar(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatProgressBar(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, android.R.attr.progressBarStyle);
|
||||
}
|
||||
|
||||
public SkinCompatProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mSkinCompatProgressBarHelper = new SkinCompatProgressBarHelper(this);
|
||||
mSkinCompatProgressBarHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mSkinCompatProgressBarHelper != null) {
|
||||
mSkinCompatProgressBarHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapShader;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.drawable.AnimationDrawable;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.ClipDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.graphics.drawable.shapes.RoundRectShape;
|
||||
import android.graphics.drawable.shapes.Shape;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import skin.support.appcompat.R;
|
||||
import skin.support.content.res.SkinCompatResources;
|
||||
import skin.support.content.res.SkinCompatVectorResources;
|
||||
import skin.support.utils.SkinCompatVersionUtils;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 2017/1/20.
|
||||
*/
|
||||
|
||||
public class SkinCompatProgressBarHelper extends SkinCompatHelper {
|
||||
|
||||
private final ProgressBar mView;
|
||||
|
||||
private Bitmap mSampleTile;
|
||||
private int mIndeterminateDrawableResId = INVALID_ID;
|
||||
private int mProgressDrawableResId = INVALID_ID;
|
||||
private int mIndeterminateTintResId = INVALID_ID;
|
||||
|
||||
SkinCompatProgressBarHelper(ProgressBar view) {
|
||||
mView = view;
|
||||
}
|
||||
|
||||
void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
|
||||
TypedArray a = mView.getContext().obtainStyledAttributes(attrs, R.styleable.SkinCompatProgressBar, defStyleAttr, 0);
|
||||
|
||||
mIndeterminateDrawableResId = a.getResourceId(R.styleable.SkinCompatProgressBar_android_indeterminateDrawable, INVALID_ID);
|
||||
mProgressDrawableResId = a.getResourceId(R.styleable.SkinCompatProgressBar_android_progressDrawable, INVALID_ID);
|
||||
|
||||
a.recycle();
|
||||
if (Build.VERSION.SDK_INT > 21) {
|
||||
a = mView.getContext().obtainStyledAttributes(attrs, new int[]{android.R.attr.indeterminateTint}, defStyleAttr, 0);
|
||||
mIndeterminateTintResId = a.getResourceId(0, INVALID_ID);
|
||||
a.recycle();
|
||||
}
|
||||
applySkin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a drawable to a tiled version of itself. It will recursively
|
||||
* traverse layer and state list drawables.
|
||||
*/
|
||||
private Drawable tileify(Drawable drawable, boolean clip) {
|
||||
if (SkinCompatVersionUtils.isV4WrappedDrawable(drawable)) {
|
||||
Drawable inner = SkinCompatVersionUtils.getV4WrappedDrawableWrappedDrawable(drawable);
|
||||
if (inner != null) {
|
||||
inner = tileify(inner, clip);
|
||||
SkinCompatVersionUtils.setV4WrappedDrawableWrappedDrawable(drawable, inner);
|
||||
}
|
||||
} else if (SkinCompatVersionUtils.isV4DrawableWrapper(drawable)) {
|
||||
Drawable inner = SkinCompatVersionUtils.getV4DrawableWrapperWrappedDrawable(drawable);
|
||||
if (inner != null) {
|
||||
inner = tileify(inner, clip);
|
||||
SkinCompatVersionUtils.setV4DrawableWrapperWrappedDrawable(drawable, inner);
|
||||
}
|
||||
} else if (drawable instanceof LayerDrawable) {
|
||||
LayerDrawable background = (LayerDrawable) drawable;
|
||||
final int N = background.getNumberOfLayers();
|
||||
Drawable[] outDrawables = new Drawable[N];
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
int id = background.getId(i);
|
||||
outDrawables[i] = tileify(background.getDrawable(i),
|
||||
(id == android.R.id.progress || id == android.R.id.secondaryProgress));
|
||||
}
|
||||
LayerDrawable newBg = new LayerDrawable(outDrawables);
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
newBg.setId(i, background.getId(i));
|
||||
}
|
||||
|
||||
return newBg;
|
||||
|
||||
} else if (drawable instanceof BitmapDrawable) {
|
||||
final BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
|
||||
final Bitmap tileBitmap = bitmapDrawable.getBitmap();
|
||||
if (mSampleTile == null) {
|
||||
mSampleTile = tileBitmap;
|
||||
}
|
||||
|
||||
final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
|
||||
final BitmapShader bitmapShader = new BitmapShader(tileBitmap,
|
||||
Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
|
||||
shapeDrawable.getPaint().setShader(bitmapShader);
|
||||
shapeDrawable.getPaint().setColorFilter(bitmapDrawable.getPaint().getColorFilter());
|
||||
return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT,
|
||||
ClipDrawable.HORIZONTAL) : shapeDrawable;
|
||||
}
|
||||
|
||||
return drawable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a AnimationDrawable for use as a barberpole animation.
|
||||
* Each frame of the animation is wrapped in a ClipDrawable and
|
||||
* given a tiling BitmapShader.
|
||||
*/
|
||||
private Drawable tileifyIndeterminate(Drawable drawable) {
|
||||
if (drawable instanceof AnimationDrawable) {
|
||||
AnimationDrawable background = (AnimationDrawable) drawable;
|
||||
final int N = background.getNumberOfFrames();
|
||||
AnimationDrawable newBg = new AnimationDrawable();
|
||||
newBg.setOneShot(background.isOneShot());
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
Drawable frame = tileify(background.getFrame(i), true);
|
||||
frame.setLevel(10000);
|
||||
newBg.addFrame(frame, background.getDuration(i));
|
||||
}
|
||||
newBg.setLevel(10000);
|
||||
drawable = newBg;
|
||||
}
|
||||
return drawable;
|
||||
}
|
||||
|
||||
private Shape getDrawableShape() {
|
||||
final float[] roundedCorners = new float[]{5, 5, 5, 5, 5, 5, 5, 5};
|
||||
return new RoundRectShape(roundedCorners, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
mIndeterminateDrawableResId = checkResourceId(mIndeterminateDrawableResId);
|
||||
if (mIndeterminateDrawableResId != INVALID_ID) {
|
||||
Drawable drawable = SkinCompatVectorResources.getDrawableCompat(mView.getContext(), mIndeterminateDrawableResId);
|
||||
drawable.setBounds(mView.getIndeterminateDrawable().getBounds());
|
||||
mView.setIndeterminateDrawable(tileifyIndeterminate(drawable));
|
||||
}
|
||||
|
||||
mProgressDrawableResId = checkProgressDrawableResId(mProgressDrawableResId);
|
||||
if (mProgressDrawableResId != INVALID_ID) {
|
||||
Drawable drawable = SkinCompatVectorResources.getDrawableCompat(mView.getContext(), mProgressDrawableResId);
|
||||
mView.setProgressDrawable(tileify(drawable, false));
|
||||
}
|
||||
if (Build.VERSION.SDK_INT > 21) {
|
||||
mIndeterminateTintResId = checkResourceId(mIndeterminateTintResId);
|
||||
if (mIndeterminateTintResId != INVALID_ID) {
|
||||
mView.setIndeterminateTintList(SkinCompatResources.getColorStateList(mView.getContext(), mIndeterminateTintResId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int checkProgressDrawableResId(int mProgressDrawableResId) {
|
||||
return checkResourceId(mProgressDrawableResId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.appcompat.widget.AppCompatRadioButton;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import skin.support.appcompat.R;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 17-1-14.
|
||||
*/
|
||||
|
||||
public class SkinCompatRadioButton extends AppCompatRadioButton implements SkinCompatSupportable {
|
||||
private SkinCompatTextHelper mTextHelper;
|
||||
private SkinCompatCompoundButtonHelper mCompoundButtonHelper;
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinCompatRadioButton(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatRadioButton(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.radioButtonStyle);
|
||||
}
|
||||
|
||||
public SkinCompatRadioButton(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mCompoundButtonHelper = new SkinCompatCompoundButtonHelper(this);
|
||||
mCompoundButtonHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
mTextHelper = SkinCompatTextHelper.create(this);
|
||||
mTextHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setButtonDrawable(@DrawableRes int resId) {
|
||||
super.setButtonDrawable(resId);
|
||||
if (mCompoundButtonHelper != null) {
|
||||
mCompoundButtonHelper.setButtonDrawable(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextAppearance(int resId) {
|
||||
setTextAppearance(getContext(), resId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextAppearance(Context context, int resId) {
|
||||
super.setTextAppearance(context, resId);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetTextAppearance(context, resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompoundDrawablesRelativeWithIntrinsicBounds(
|
||||
@DrawableRes int start, @DrawableRes int top, @DrawableRes int end, @DrawableRes int bottom) {
|
||||
super.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompoundDrawablesWithIntrinsicBounds(
|
||||
@DrawableRes int left, @DrawableRes int top, @DrawableRes int right, @DrawableRes int bottom) {
|
||||
super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
if (mCompoundButtonHelper != null) {
|
||||
mCompoundButtonHelper.applySkin();
|
||||
}
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.RadioGroup;
|
||||
|
||||
/**
|
||||
* Created by ximsf on 2017/3/23.
|
||||
*/
|
||||
|
||||
public class SkinCompatRadioGroup extends RadioGroup implements SkinCompatSupportable {
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
public SkinCompatRadioGroup(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatRadioGroup(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.appcompat.widget.AppCompatRatingBar;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import skin.support.appcompat.R;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 17-1-21.
|
||||
*/
|
||||
|
||||
public class SkinCompatRatingBar extends AppCompatRatingBar implements SkinCompatSupportable {
|
||||
private SkinCompatProgressBarHelper mSkinCompatProgressBarHelper;
|
||||
|
||||
public SkinCompatRatingBar(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatRatingBar(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.ratingBarStyle);
|
||||
}
|
||||
|
||||
public SkinCompatRatingBar(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mSkinCompatProgressBarHelper = new SkinCompatProgressBarHelper(this);
|
||||
mSkinCompatProgressBarHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mSkinCompatProgressBarHelper != null) {
|
||||
mSkinCompatProgressBarHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
/**
|
||||
* Created by pengfengwang on 2017/1/13.
|
||||
*/
|
||||
|
||||
public class SkinCompatRelativeLayout extends RelativeLayout implements SkinCompatSupportable {
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinCompatRelativeLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatRelativeLayout(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SkinCompatRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
/**
|
||||
* Created by Jungle68 on 2017/6/27.
|
||||
*/
|
||||
public class SkinCompatScrollView extends ScrollView implements SkinCompatSupportable {
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinCompatScrollView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatScrollView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SkinCompatScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(@DrawableRes int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.appcompat.widget.AppCompatSeekBar;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import skin.support.appcompat.R;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 17-1-21.
|
||||
*/
|
||||
|
||||
public class SkinCompatSeekBar extends AppCompatSeekBar implements SkinCompatSupportable {
|
||||
private SkinCompatSeekBarHelper mSkinCompatSeekBarHelper;
|
||||
|
||||
public SkinCompatSeekBar(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatSeekBar(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.seekBarStyle);
|
||||
}
|
||||
|
||||
public SkinCompatSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mSkinCompatSeekBarHelper = new SkinCompatSeekBarHelper(this);
|
||||
mSkinCompatSeekBarHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mSkinCompatSeekBarHelper != null) {
|
||||
mSkinCompatSeekBarHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.SeekBar;
|
||||
|
||||
import skin.support.appcompat.R;
|
||||
import skin.support.content.res.SkinCompatResources;
|
||||
import skin.support.content.res.SkinCompatVectorResources;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 17-1-21.
|
||||
*/
|
||||
public class SkinCompatSeekBarHelper extends SkinCompatProgressBarHelper {
|
||||
private final SeekBar mView;
|
||||
|
||||
private int mThumbResId = INVALID_ID;
|
||||
|
||||
public SkinCompatSeekBarHelper(SeekBar view) {
|
||||
super(view);
|
||||
mView = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
|
||||
super.loadFromAttributes(attrs, defStyleAttr);
|
||||
|
||||
TypedArray a = mView.getContext().obtainStyledAttributes(attrs, R.styleable.AppCompatSeekBar, defStyleAttr, 0);
|
||||
mThumbResId = a.getResourceId(R.styleable.AppCompatSeekBar_android_thumb, INVALID_ID);
|
||||
a.recycle();
|
||||
|
||||
applySkin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
super.applySkin();
|
||||
mThumbResId = checkResourceId(mThumbResId);
|
||||
if (mThumbResId != INVALID_ID) {
|
||||
mView.setThumb(SkinCompatVectorResources.getDrawableCompat(mView.getContext(), mThumbResId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Build;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.appcompat.widget.AppCompatSpinner;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
|
||||
import skin.support.appcompat.R;
|
||||
import skin.support.content.res.SkinCompatVectorResources;
|
||||
|
||||
import static skin.support.widget.SkinCompatHelper.INVALID_ID;
|
||||
import static skin.support.widget.SkinCompatHelper.checkResourceId;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 17-1-21.
|
||||
*/
|
||||
|
||||
public class SkinCompatSpinner extends AppCompatSpinner implements SkinCompatSupportable {
|
||||
private static final String TAG = SkinCompatSpinner.class.getSimpleName();
|
||||
|
||||
private static final int[] ATTRS_ANDROID_SPINNERMODE = {android.R.attr.spinnerMode};
|
||||
|
||||
private static final int MODE_DIALOG = 0;
|
||||
private static final int MODE_DROPDOWN = 1;
|
||||
private static final int MODE_THEME = -1;
|
||||
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
private int mPopupBackgroundResId = INVALID_ID;
|
||||
|
||||
public SkinCompatSpinner(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatSpinner(Context context, int mode) {
|
||||
this(context, null, R.attr.spinnerStyle, mode);
|
||||
}
|
||||
|
||||
public SkinCompatSpinner(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.spinnerStyle);
|
||||
}
|
||||
|
||||
public SkinCompatSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
this(context, attrs, defStyleAttr, MODE_THEME);
|
||||
}
|
||||
|
||||
public SkinCompatSpinner(Context context, AttributeSet attrs, int defStyleAttr, int mode) {
|
||||
this(context, attrs, defStyleAttr, mode, null);
|
||||
}
|
||||
|
||||
public SkinCompatSpinner(Context context, AttributeSet attrs, int defStyleAttr, int mode, Resources.Theme popupTheme) {
|
||||
super(context, attrs, defStyleAttr, mode, popupTheme);
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Spinner, defStyleAttr, 0);
|
||||
|
||||
if (getPopupContext() != null) {
|
||||
if (mode == MODE_THEME) {
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
// If we're running on API v11+ we will try and read android:spinnerMode
|
||||
TypedArray aa = null;
|
||||
try {
|
||||
aa = context.obtainStyledAttributes(attrs, ATTRS_ANDROID_SPINNERMODE,
|
||||
defStyleAttr, 0);
|
||||
if (aa.hasValue(0)) {
|
||||
mode = aa.getInt(0, MODE_DIALOG);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.i(TAG, "Could not read android:spinnerMode", e);
|
||||
} finally {
|
||||
if (aa != null) {
|
||||
aa.recycle();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Else, we use a default mode of dropdown
|
||||
mode = MODE_DROPDOWN;
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == MODE_DROPDOWN) {
|
||||
final TypedArray pa = getPopupContext().obtainStyledAttributes(attrs, R.styleable.Spinner, defStyleAttr, 0);
|
||||
mPopupBackgroundResId = pa.getResourceId(R.styleable.Spinner_android_popupBackground, INVALID_ID);
|
||||
pa.recycle();
|
||||
}
|
||||
}
|
||||
a.recycle();
|
||||
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPopupBackgroundResource(@DrawableRes int resId) {
|
||||
super.setPopupBackgroundResource(resId);
|
||||
mPopupBackgroundResId = resId;
|
||||
applyPopupBackground();
|
||||
}
|
||||
|
||||
private void applyPopupBackground() {
|
||||
mPopupBackgroundResId = checkResourceId(mPopupBackgroundResId);
|
||||
if (mPopupBackgroundResId != INVALID_ID) {
|
||||
setPopupBackgroundDrawable(SkinCompatVectorResources.getDrawableCompat(getContext(), mPopupBackgroundResId));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
applyPopupBackground();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
import skin.support.R;
|
||||
import skin.support.content.res.SkinCompatResources;
|
||||
import skin.support.content.res.SkinCompatVectorResources;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 2017/1/10.
|
||||
*/
|
||||
|
||||
public class SkinCompatTextHelper extends SkinCompatHelper {
|
||||
private static final String TAG = SkinCompatTextHelper.class.getSimpleName();
|
||||
|
||||
public static SkinCompatTextHelper create(TextView textView) {
|
||||
if (Build.VERSION.SDK_INT >= 17) {
|
||||
return new SkinCompatTextHelperV17(textView);
|
||||
}
|
||||
return new SkinCompatTextHelper(textView);
|
||||
}
|
||||
|
||||
final TextView mView;
|
||||
|
||||
private int mTextColorResId = INVALID_ID;
|
||||
private int mTextColorHintResId = INVALID_ID;
|
||||
protected int mDrawableBottomResId = INVALID_ID;
|
||||
protected int mDrawableLeftResId = INVALID_ID;
|
||||
protected int mDrawableRightResId = INVALID_ID;
|
||||
protected int mDrawableTopResId = INVALID_ID;
|
||||
|
||||
public SkinCompatTextHelper(TextView view) {
|
||||
mView = view;
|
||||
}
|
||||
|
||||
public void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
|
||||
final Context context = mView.getContext();
|
||||
|
||||
// First read the TextAppearance style id
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SkinCompatTextHelper, defStyleAttr, 0);
|
||||
final int ap = a.getResourceId(R.styleable.SkinCompatTextHelper_android_textAppearance, INVALID_ID);
|
||||
|
||||
if (a.hasValue(R.styleable.SkinCompatTextHelper_android_drawableLeft)) {
|
||||
mDrawableLeftResId = a.getResourceId(R.styleable.SkinCompatTextHelper_android_drawableLeft, INVALID_ID);
|
||||
}
|
||||
if (a.hasValue(R.styleable.SkinCompatTextHelper_android_drawableTop)) {
|
||||
mDrawableTopResId = a.getResourceId(R.styleable.SkinCompatTextHelper_android_drawableTop, INVALID_ID);
|
||||
}
|
||||
if (a.hasValue(R.styleable.SkinCompatTextHelper_android_drawableRight)) {
|
||||
mDrawableRightResId = a.getResourceId(R.styleable.SkinCompatTextHelper_android_drawableRight, INVALID_ID);
|
||||
}
|
||||
if (a.hasValue(R.styleable.SkinCompatTextHelper_android_drawableBottom)) {
|
||||
mDrawableBottomResId = a.getResourceId(R.styleable.SkinCompatTextHelper_android_drawableBottom, INVALID_ID);
|
||||
}
|
||||
a.recycle();
|
||||
|
||||
if (ap != INVALID_ID) {
|
||||
a = context.obtainStyledAttributes(ap, R.styleable.SkinTextAppearance);
|
||||
if (a.hasValue(R.styleable.SkinTextAppearance_android_textColor)) {
|
||||
mTextColorResId = a.getResourceId(R.styleable.SkinTextAppearance_android_textColor, INVALID_ID);
|
||||
}
|
||||
if (a.hasValue(R.styleable.SkinTextAppearance_android_textColorHint)) {
|
||||
mTextColorHintResId = a.getResourceId(
|
||||
R.styleable.SkinTextAppearance_android_textColorHint, INVALID_ID);
|
||||
}
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
// Now read the style's values
|
||||
a = context.obtainStyledAttributes(attrs, R.styleable.SkinTextAppearance, defStyleAttr, 0);
|
||||
if (a.hasValue(R.styleable.SkinTextAppearance_android_textColor)) {
|
||||
mTextColorResId = a.getResourceId(R.styleable.SkinTextAppearance_android_textColor, INVALID_ID);
|
||||
}
|
||||
if (a.hasValue(R.styleable.SkinTextAppearance_android_textColorHint)) {
|
||||
mTextColorHintResId = a.getResourceId(
|
||||
R.styleable.SkinTextAppearance_android_textColorHint, INVALID_ID);
|
||||
}
|
||||
a.recycle();
|
||||
applySkin();
|
||||
}
|
||||
|
||||
public void onSetTextAppearance(Context context, int resId) {
|
||||
final TypedArray a = context.obtainStyledAttributes(resId, R.styleable.SkinTextAppearance);
|
||||
if (a.hasValue(R.styleable.SkinTextAppearance_android_textColor)) {
|
||||
mTextColorResId = a.getResourceId(R.styleable.SkinTextAppearance_android_textColor, INVALID_ID);
|
||||
}
|
||||
if (a.hasValue(R.styleable.SkinTextAppearance_android_textColorHint)) {
|
||||
mTextColorHintResId = a.getResourceId(R.styleable.SkinTextAppearance_android_textColorHint, INVALID_ID);
|
||||
}
|
||||
a.recycle();
|
||||
applyTextColorResource();
|
||||
applyTextColorHintResource();
|
||||
}
|
||||
|
||||
private void applyTextColorHintResource() {
|
||||
mTextColorHintResId = checkResourceId(mTextColorHintResId);
|
||||
if (mTextColorHintResId != INVALID_ID) {
|
||||
// TODO: HTC_U-3u OS:8.0上调用framework的getColorStateList方法,有可能抛出异常,暂时没有找到更好的解决办法.
|
||||
// issue: https://github.com/ximsfei/Android-skin-support/issues/110
|
||||
try {
|
||||
ColorStateList color = SkinCompatResources.getColorStateList(mView.getContext(), mTextColorHintResId);
|
||||
mView.setHintTextColor(color);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void applyTextColorResource() {
|
||||
mTextColorResId = checkResourceId(mTextColorResId);
|
||||
if (mTextColorResId != INVALID_ID) {
|
||||
// TODO: HTC_U-3u OS:8.0上调用framework的getColorStateList方法,有可能抛出异常,暂时没有找到更好的解决办法.
|
||||
// issue: https://github.com/ximsfei/Android-skin-support/issues/110
|
||||
try {
|
||||
ColorStateList color = SkinCompatResources.getColorStateList(mView.getContext(), mTextColorResId);
|
||||
mView.setTextColor(color);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onSetCompoundDrawablesRelativeWithIntrinsicBounds(
|
||||
@DrawableRes int start, @DrawableRes int top, @DrawableRes int end, @DrawableRes int bottom) {
|
||||
mDrawableLeftResId = start;
|
||||
mDrawableTopResId = top;
|
||||
mDrawableRightResId = end;
|
||||
mDrawableBottomResId = bottom;
|
||||
applyCompoundDrawablesRelativeResource();
|
||||
}
|
||||
|
||||
public void onSetCompoundDrawablesWithIntrinsicBounds(
|
||||
@DrawableRes int left, @DrawableRes int top, @DrawableRes int right, @DrawableRes int bottom) {
|
||||
mDrawableLeftResId = left;
|
||||
mDrawableTopResId = top;
|
||||
mDrawableRightResId = right;
|
||||
mDrawableBottomResId = bottom;
|
||||
applyCompoundDrawablesResource();
|
||||
}
|
||||
|
||||
protected void applyCompoundDrawablesRelativeResource() {
|
||||
applyCompoundDrawablesResource();
|
||||
}
|
||||
|
||||
protected void applyCompoundDrawablesResource() {
|
||||
Drawable drawableLeft = null, drawableTop = null, drawableRight = null, drawableBottom = null;
|
||||
mDrawableLeftResId = checkResourceId(mDrawableLeftResId);
|
||||
if (mDrawableLeftResId != INVALID_ID) {
|
||||
drawableLeft = SkinCompatVectorResources.getDrawableCompat(mView.getContext(), mDrawableLeftResId);
|
||||
}
|
||||
mDrawableTopResId = checkResourceId(mDrawableTopResId);
|
||||
if (mDrawableTopResId != INVALID_ID) {
|
||||
drawableTop = SkinCompatVectorResources.getDrawableCompat(mView.getContext(), mDrawableTopResId);
|
||||
}
|
||||
mDrawableRightResId = checkResourceId(mDrawableRightResId);
|
||||
if (mDrawableRightResId != INVALID_ID) {
|
||||
drawableRight = SkinCompatVectorResources.getDrawableCompat(mView.getContext(), mDrawableRightResId);
|
||||
}
|
||||
mDrawableBottomResId = checkResourceId(mDrawableBottomResId);
|
||||
if (mDrawableBottomResId != INVALID_ID) {
|
||||
drawableBottom = SkinCompatVectorResources.getDrawableCompat(mView.getContext(), mDrawableBottomResId);
|
||||
}
|
||||
if (mDrawableLeftResId != INVALID_ID
|
||||
|| mDrawableTopResId != INVALID_ID
|
||||
|| mDrawableRightResId != INVALID_ID
|
||||
|| mDrawableBottomResId != INVALID_ID) {
|
||||
mView.setCompoundDrawablesWithIntrinsicBounds(drawableLeft, drawableTop, drawableRight, drawableBottom);
|
||||
}
|
||||
}
|
||||
|
||||
public int getTextColorResId() {
|
||||
return mTextColorResId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
applyCompoundDrawablesRelativeResource();
|
||||
applyTextColorResource();
|
||||
applyTextColorHintResource();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
import skin.support.R;
|
||||
import skin.support.content.res.SkinCompatVectorResources;
|
||||
|
||||
/**
|
||||
* Created by pengfengwang on 2017/3/8.
|
||||
*/
|
||||
|
||||
@RequiresApi(17)
|
||||
@TargetApi(17)
|
||||
public class SkinCompatTextHelperV17 extends SkinCompatTextHelper {
|
||||
private int mDrawableStartResId = INVALID_ID;
|
||||
private int mDrawableEndResId = INVALID_ID;
|
||||
|
||||
public SkinCompatTextHelperV17(TextView view) {
|
||||
super(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
|
||||
final Context context = mView.getContext();
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SkinCompatTextHelper,
|
||||
defStyleAttr, 0);
|
||||
if (a.hasValue(R.styleable.SkinCompatTextHelper_android_drawableStart)) {
|
||||
mDrawableStartResId = a.getResourceId(R.styleable.SkinCompatTextHelper_android_drawableStart, INVALID_ID);
|
||||
mDrawableStartResId = SkinCompatHelper.checkResourceId(mDrawableStartResId);
|
||||
}
|
||||
if (a.hasValue(R.styleable.SkinCompatTextHelper_android_drawableEnd)) {
|
||||
mDrawableEndResId = a.getResourceId(R.styleable.SkinCompatTextHelper_android_drawableEnd, INVALID_ID);
|
||||
mDrawableEndResId = SkinCompatHelper.checkResourceId(mDrawableEndResId);
|
||||
}
|
||||
a.recycle();
|
||||
super.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetCompoundDrawablesRelativeWithIntrinsicBounds(
|
||||
@DrawableRes int start, @DrawableRes int top, @DrawableRes int end, @DrawableRes int bottom) {
|
||||
mDrawableStartResId = start;
|
||||
mDrawableTopResId = top;
|
||||
mDrawableEndResId = end;
|
||||
mDrawableBottomResId = bottom;
|
||||
applyCompoundDrawablesRelativeResource();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyCompoundDrawablesRelativeResource() {
|
||||
Drawable drawableLeft = null, drawableTop = null, drawableRight = null, drawableBottom = null,
|
||||
drawableStart = null, drawableEnd = null;
|
||||
mDrawableLeftResId = checkResourceId(mDrawableLeftResId);
|
||||
if (mDrawableLeftResId != INVALID_ID) {
|
||||
drawableLeft = SkinCompatVectorResources.getDrawableCompat(mView.getContext(), mDrawableLeftResId);
|
||||
}
|
||||
mDrawableTopResId = checkResourceId(mDrawableTopResId);
|
||||
if (mDrawableTopResId != INVALID_ID) {
|
||||
drawableTop = SkinCompatVectorResources.getDrawableCompat(mView.getContext(), mDrawableTopResId);
|
||||
}
|
||||
mDrawableRightResId = checkResourceId(mDrawableRightResId);
|
||||
if (mDrawableRightResId != INVALID_ID) {
|
||||
drawableRight = SkinCompatVectorResources.getDrawableCompat(mView.getContext(), mDrawableRightResId);
|
||||
}
|
||||
mDrawableBottomResId = checkResourceId(mDrawableBottomResId);
|
||||
if (mDrawableBottomResId != INVALID_ID) {
|
||||
drawableBottom = SkinCompatVectorResources.getDrawableCompat(mView.getContext(), mDrawableBottomResId);
|
||||
}
|
||||
if (mDrawableStartResId != INVALID_ID) {
|
||||
drawableStart = SkinCompatVectorResources.getDrawableCompat(mView.getContext(), mDrawableStartResId);
|
||||
}
|
||||
if (drawableStart == null) {
|
||||
drawableStart = drawableLeft;
|
||||
}
|
||||
if (mDrawableEndResId != INVALID_ID) {
|
||||
drawableEnd = SkinCompatVectorResources.getDrawableCompat(mView.getContext(), mDrawableEndResId);
|
||||
}
|
||||
if (drawableEnd == null) {
|
||||
drawableEnd = drawableRight;
|
||||
}
|
||||
if (mDrawableLeftResId != INVALID_ID
|
||||
|| mDrawableTopResId != INVALID_ID
|
||||
|| mDrawableRightResId != INVALID_ID
|
||||
|| mDrawableBottomResId != INVALID_ID
|
||||
|| mDrawableStartResId != INVALID_ID
|
||||
|| mDrawableEndResId != INVALID_ID) {
|
||||
mView.setCompoundDrawablesWithIntrinsicBounds(drawableStart, drawableTop, drawableEnd, drawableBottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 2017/1/10.
|
||||
*/
|
||||
|
||||
public class SkinCompatTextView extends AppCompatTextView implements SkinCompatSupportable {
|
||||
private SkinCompatTextHelper mTextHelper;
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinCompatTextView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatTextView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, android.R.attr.textViewStyle);
|
||||
}
|
||||
|
||||
public SkinCompatTextView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
mTextHelper = SkinCompatTextHelper.create(this);
|
||||
mTextHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(@DrawableRes int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextAppearance(int resId) {
|
||||
setTextAppearance(getContext(), resId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextAppearance(Context context, int resId) {
|
||||
super.setTextAppearance(context, resId);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetTextAppearance(context, resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompoundDrawablesRelativeWithIntrinsicBounds(
|
||||
@DrawableRes int start, @DrawableRes int top, @DrawableRes int end, @DrawableRes int bottom) {
|
||||
super.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompoundDrawablesWithIntrinsicBounds(
|
||||
@DrawableRes int left, @DrawableRes int top, @DrawableRes int right, @DrawableRes int bottom) {
|
||||
super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.onSetCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
if (mTextHelper != null) {
|
||||
mTextHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import skin.support.appcompat.R;
|
||||
import skin.support.content.res.SkinCompatResources;
|
||||
import skin.support.content.res.SkinCompatVectorResources;
|
||||
|
||||
import static skin.support.widget.SkinCompatHelper.INVALID_ID;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 17-1-12.
|
||||
*/
|
||||
|
||||
public class SkinCompatToolbar extends Toolbar implements SkinCompatSupportable {
|
||||
private int mTitleTextColorResId = INVALID_ID;
|
||||
private int mSubtitleTextColorResId = INVALID_ID;
|
||||
private int mNavigationIconResId = INVALID_ID;
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinCompatToolbar(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatToolbar(Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.toolbarStyle);
|
||||
}
|
||||
|
||||
public SkinCompatToolbar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Toolbar, defStyleAttr, 0);
|
||||
mNavigationIconResId = a.getResourceId(R.styleable.Toolbar_navigationIcon, INVALID_ID);
|
||||
|
||||
int titleAp = a.getResourceId(R.styleable.Toolbar_titleTextAppearance, INVALID_ID);
|
||||
int subtitleAp = a.getResourceId(R.styleable.Toolbar_subtitleTextAppearance, INVALID_ID);
|
||||
a.recycle();
|
||||
if (titleAp != INVALID_ID) {
|
||||
a = context.obtainStyledAttributes(titleAp, R.styleable.SkinTextAppearance);
|
||||
mTitleTextColorResId = a.getResourceId(R.styleable.SkinTextAppearance_android_textColor, INVALID_ID);
|
||||
a.recycle();
|
||||
}
|
||||
if (subtitleAp != INVALID_ID) {
|
||||
a = context.obtainStyledAttributes(subtitleAp, R.styleable.SkinTextAppearance);
|
||||
mSubtitleTextColorResId = a.getResourceId(R.styleable.SkinTextAppearance_android_textColor, INVALID_ID);
|
||||
a.recycle();
|
||||
}
|
||||
a = context.obtainStyledAttributes(attrs, R.styleable.Toolbar, defStyleAttr, 0);
|
||||
if (a.hasValue(R.styleable.Toolbar_titleTextColor)) {
|
||||
mTitleTextColorResId = a.getResourceId(R.styleable.Toolbar_titleTextColor, INVALID_ID);
|
||||
}
|
||||
if (a.hasValue(R.styleable.Toolbar_subtitleTextColor)) {
|
||||
mSubtitleTextColorResId = a.getResourceId(R.styleable.Toolbar_subtitleTextColor, INVALID_ID);
|
||||
}
|
||||
a.recycle();
|
||||
applyTitleTextColor();
|
||||
applySubtitleTextColor();
|
||||
applyNavigationIcon();
|
||||
}
|
||||
|
||||
private void applyTitleTextColor() {
|
||||
mTitleTextColorResId = SkinCompatHelper.checkResourceId(mTitleTextColorResId);
|
||||
if (mTitleTextColorResId != INVALID_ID) {
|
||||
setTitleTextColor(SkinCompatResources.getColor(getContext(), mTitleTextColorResId));
|
||||
}
|
||||
}
|
||||
|
||||
private void applySubtitleTextColor() {
|
||||
mSubtitleTextColorResId = SkinCompatHelper.checkResourceId(mSubtitleTextColorResId);
|
||||
if (mSubtitleTextColorResId != INVALID_ID) {
|
||||
setSubtitleTextColor(SkinCompatResources.getColor(getContext(), mSubtitleTextColorResId));
|
||||
}
|
||||
}
|
||||
|
||||
private void applyNavigationIcon() {
|
||||
mNavigationIconResId = SkinCompatHelper.checkResourceId(mNavigationIconResId);
|
||||
if (mNavigationIconResId != INVALID_ID) {
|
||||
setNavigationIcon(SkinCompatVectorResources.getDrawableCompat(getContext(), mNavigationIconResId));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(@DrawableRes int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNavigationIcon(@DrawableRes int resId) {
|
||||
super.setNavigationIcon(resId);
|
||||
mNavigationIconResId = resId;
|
||||
applyNavigationIcon();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
applyTitleTextColor();
|
||||
applySubtitleTextColor();
|
||||
applyNavigationIcon();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* Created by pengfengwang on 2017/1/13.
|
||||
*/
|
||||
|
||||
public class SkinCompatView extends View implements SkinCompatSupportable {
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinCompatView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SkinCompatView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
public abstract class SkinCompatViewGroup extends ViewGroup implements SkinCompatSupportable {
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinCompatViewGroup(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatViewGroup(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SkinCompatViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/skin_btn_check_box" android:state_checked="true" />
|
||||
<item android:drawable="@drawable/skin_btn_check_box_outline_blank" />
|
||||
</selector>
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M19,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.11,0 2,-0.9 2,-2L21,5c0,-1.1 -0.89,-2 -2,-2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M19,5v14H5V5h14m0,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/skin_btn_radio_checked" android:state_checked="true" />
|
||||
<item android:drawable="@drawable/skin_btn_radio_unchecked" />
|
||||
</selector>
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,7c-2.76,0 -5,2.24 -5,5s2.24,5 5,5 5,-2.24 5,-5 -2.24,-5 -5,-5zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/parentPanel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/skinAlertDialogBackground"
|
||||
android:gravity="start|left|top"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include layout="@layout/skin_alert_dialog_title" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/contentPanel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<View
|
||||
android:id="@+id/scrollIndicatorUp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_gravity="top"
|
||||
android:background="?attr/skinAlertDialogControlHighlightColor"
|
||||
android:visibility="gone" />
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/scrollView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.legacy.widget.Space
|
||||
android:id="@+id/textSpacerNoTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/abc_dialog_padding_top_material"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/message"
|
||||
style="@style/TextAppearance.AppCompat.Subhead"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="?attr/dialogPreferredPadding"
|
||||
android:paddingRight="?attr/dialogPreferredPadding"
|
||||
android:textColor="?attr/skinAlertDialogMessageTextColor" />
|
||||
|
||||
<androidx.legacy.widget.Space
|
||||
android:id="@+id/textSpacerNoButtons"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/skin_dialog_padding_top"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<View
|
||||
android:id="@+id/scrollIndicatorDown"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="?attr/skinAlertDialogControlHighlightColor"
|
||||
android:visibility="gone" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/customPanel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/custom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</FrameLayout>
|
||||
|
||||
<include
|
||||
layout="@layout/skin_alert_dialog_button_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/buttonPanel"
|
||||
style="?attr/buttonBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fillViewport="true">
|
||||
|
||||
<androidx.appcompat.widget.ButtonBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="bottom"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="4dp"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingTop="4dp">
|
||||
|
||||
<Button
|
||||
android:id="@android:id/button3"
|
||||
style="?attr/buttonBarNeutralButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?attr/skinAlertDialogNeutralButtonTextColor" />
|
||||
|
||||
<androidx.legacy.widget.Space
|
||||
android:id="@+id/spacer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<Button
|
||||
android:id="@android:id/button2"
|
||||
style="?attr/buttonBarNegativeButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?attr/skinAlertDialogNegativeButtonTextColor" />
|
||||
|
||||
<Button
|
||||
android:id="@android:id/button1"
|
||||
style="?attr/buttonBarPositiveButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?attr/skinAlertDialogPositiveButtonTextColor" />
|
||||
|
||||
</androidx.appcompat.widget.ButtonBarLayout>
|
||||
|
||||
</ScrollView>
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/topPanel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- If the client uses a customTitle, it will be added here. -->
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/title_template"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical|start|left"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="?attr/dialogPreferredPadding"
|
||||
android:paddingRight="?attr/dialogPreferredPadding"
|
||||
android:paddingTop="@dimen/skin_dialog_padding_top">
|
||||
|
||||
<ImageView
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="32dip"
|
||||
android:layout_height="32dip"
|
||||
android:layout_marginEnd="8dip"
|
||||
android:layout_marginRight="8dip"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@null" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/alertTitle"
|
||||
style="?android:attr/windowTitleStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?attr/skinAlertDialogTitleTextColor"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.legacy.widget.Space
|
||||
android:id="@+id/titleDividerNoCustom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/skin_dialog_title_divider"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
This layout file is used by the AlertDialog when displaying a list of items.
|
||||
This layout file is inflated and used as the ListView to display the items.
|
||||
Assign an ID so its state will be saved/restored.
|
||||
-->
|
||||
<view xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/select_dialog_listview"
|
||||
style="@style/Widget.AppCompat.ListView"
|
||||
class="androidx.appcompat.app.AlertController$RecycleListView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:cacheColorHint="@null"
|
||||
android:clipToPadding="false"
|
||||
android:divider="?attr/skinAlertDialogListDivider"
|
||||
android:fadingEdge="none"
|
||||
android:overScrollMode="ifContentScrolls"
|
||||
android:scrollbars="vertical"
|
||||
app:paddingBottomNoButtons="@dimen/skin_dialog_list_padding_bottom_no_buttons"
|
||||
app:paddingTopNoTitle="@dimen/skin_dialog_list_padding_top_no_title" />
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
This layout file is used by the AlertDialog when displaying a list of items.
|
||||
This layout file is inflated and used as the TextView to display individual
|
||||
items.
|
||||
-->
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@android:id/text1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="?attr/listPreferredItemHeightSmall"
|
||||
android:paddingLeft="?attr/listPreferredItemPaddingLeft"
|
||||
android:paddingRight="?attr/listPreferredItemPaddingRight"
|
||||
android:textAppearance="?attr/textAppearanceListItemSmall"
|
||||
android:textColor="?attr/skinAlertDialogListItemTextColor" />
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@android:id/text1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="?attr/skinListChoiceIndicatorMultiple"
|
||||
android:drawablePadding="20dp"
|
||||
android:drawableStart="?attr/skinListChoiceIndicatorMultiple"
|
||||
android:ellipsize="marquee"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="?attr/listPreferredItemHeightSmall"
|
||||
android:paddingEnd="?attr/dialogPreferredPadding"
|
||||
android:paddingLeft="@dimen/skin_select_dialog_padding_start"
|
||||
android:paddingRight="?attr/dialogPreferredPadding"
|
||||
android:paddingStart="@dimen/skin_select_dialog_padding_start"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textColor="?attr/skinAlertDialogListItemTextColor" />
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@android:id/text1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="?attr/skinListChoiceIndicatorSingle"
|
||||
android:drawablePadding="20dp"
|
||||
android:drawableStart="?attr/skinListChoiceIndicatorSingle"
|
||||
android:ellipsize="marquee"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="?attr/listPreferredItemHeightSmall"
|
||||
android:paddingEnd="?attr/dialogPreferredPadding"
|
||||
android:paddingLeft="@dimen/skin_select_dialog_padding_start"
|
||||
android:paddingRight="?attr/dialogPreferredPadding"
|
||||
android:paddingStart="@dimen/skin_select_dialog_padding_start"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textColor="?attr/skinAlertDialogListItemTextColor" />
|
||||
14
skin/skin-support-appcompat/src/main/res-alertdialog/values/attrs.xml
Executable file
14
skin/skin-support-appcompat/src/main/res-alertdialog/values/attrs.xml
Executable file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<attr name="skinAlertDialogBackground" format="reference" />
|
||||
<attr name="skinAlertDialogTitleTextColor" format="reference" />
|
||||
<attr name="skinAlertDialogMessageTextColor" format="reference" />
|
||||
<attr name="skinAlertDialogNeutralButtonTextColor" format="reference" />
|
||||
<attr name="skinAlertDialogNegativeButtonTextColor" format="reference" />
|
||||
<attr name="skinAlertDialogPositiveButtonTextColor" format="reference" />
|
||||
<attr name="skinAlertDialogControlHighlightColor" format="reference" />
|
||||
<attr name="skinAlertDialogListDivider" format="reference" />
|
||||
<attr name="skinAlertDialogListItemTextColor" format="reference" />
|
||||
<attr name="skinListChoiceIndicatorMultiple" format="reference" />
|
||||
<attr name="skinListChoiceIndicatorSingle" format="reference" />
|
||||
</resources>
|
||||
8
skin/skin-support-appcompat/src/main/res-alertdialog/values/dimens.xml
Executable file
8
skin/skin-support-appcompat/src/main/res-alertdialog/values/dimens.xml
Executable file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="skin_dialog_padding_top">18dp</dimen>
|
||||
<dimen name="skin_dialog_title_divider">8dp</dimen>
|
||||
<dimen name="skin_dialog_list_padding_bottom_no_buttons">8dp</dimen>
|
||||
<dimen name="skin_dialog_list_padding_top_no_title">8dp</dimen>
|
||||
<dimen name="skin_select_dialog_padding_start">20dp</dimen>
|
||||
</resources>
|
||||
11
skin/skin-support-appcompat/src/main/res-alertdialog/values/styles.xml
Executable file
11
skin/skin-support-appcompat/src/main/res-alertdialog/values/styles.xml
Executable file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="AlertDialog.SkinCompat" parent="Base.AlertDialog.AppCompat">
|
||||
<item name="android:layout">@layout/skin_alert_dialog</item>
|
||||
<item name="listLayout">@layout/skin_select_dialog</item>
|
||||
<item name="listItemLayout">@layout/skin_select_dialog_item</item>
|
||||
<item name="multiChoiceItemLayout">@layout/skin_select_dialog_multichoice</item>
|
||||
<item name="singleChoiceItemLayout">@layout/skin_select_dialog_singlechoice</item>
|
||||
</style>
|
||||
</resources>
|
||||
3
skin/skin-support-appcompat/src/main/res/values/strings.xml
Executable file
3
skin/skin-support-appcompat/src/main/res/values/strings.xml
Executable file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">skin-support-appcompat</string>
|
||||
</resources>
|
||||
1
skin/skin-support-cardview/.gitignore
vendored
Executable file
1
skin/skin-support-cardview/.gitignore
vendored
Executable file
@@ -0,0 +1 @@
|
||||
/build
|
||||
30
skin/skin-support-cardview/build.gradle
Executable file
30
skin/skin-support-cardview/build.gradle
Executable file
@@ -0,0 +1,30 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
||||
// buildToolsVersion rootProject.ext.android.buildToolsVersion
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.android.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.android.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation rootProject.ext.dependencies.androidxcardview
|
||||
implementation project(':skin:skin-support')
|
||||
}
|
||||
|
||||
ext {
|
||||
moduleName = "skin-support-cardview"
|
||||
descContent = "CardView-v7 换肤支持包"
|
||||
}
|
||||
17
skin/skin-support-cardview/proguard-rules.pro
vendored
Executable file
17
skin/skin-support-cardview/proguard-rules.pro
vendored
Executable file
@@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in C:\Users\ximsf\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
2
skin/skin-support-cardview/src/main/AndroidManifest.xml
Executable file
2
skin/skin-support-cardview/src/main/AndroidManifest.xml
Executable file
@@ -0,0 +1,2 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="skin.support.cardview" />
|
||||
@@ -0,0 +1,32 @@
|
||||
package skin.support;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import skin.support.app.SkinCardViewInflater;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 2017/3/5.
|
||||
*/
|
||||
|
||||
public class SkinCardViewManager {
|
||||
private static volatile SkinCardViewManager sInstance;
|
||||
|
||||
public static SkinCardViewManager init(Context context) {
|
||||
if (sInstance == null) {
|
||||
synchronized (SkinCardViewManager.class) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new SkinCardViewManager(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public static SkinCardViewManager getInstance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private SkinCardViewManager(Context context) {
|
||||
SkinCompatManager.init(context).addInflater(new SkinCardViewInflater());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package skin.support.app;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import skin.support.widget.SkinCompatCardView;
|
||||
|
||||
/**
|
||||
* Created by ximsf on 2017/3/5.
|
||||
*/
|
||||
|
||||
public class SkinCardViewInflater implements SkinLayoutInflater {
|
||||
@Override
|
||||
public View createView(@NonNull Context context, final String name, @NonNull AttributeSet attrs) {
|
||||
View view = null;
|
||||
switch (name) {
|
||||
case "androidx.cardview.widget.CardView":
|
||||
view = new SkinCompatCardView(context, attrs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return view;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package skin.support.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import androidx.cardview.widget.CardView;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import skin.support.cardview.R;
|
||||
import skin.support.content.res.SkinCompatResources;
|
||||
|
||||
import static skin.support.widget.SkinCompatHelper.INVALID_ID;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 2017/3/5.
|
||||
*/
|
||||
|
||||
public class SkinCompatCardView extends CardView implements SkinCompatSupportable {
|
||||
private static final int[] COLOR_BACKGROUND_ATTR = {android.R.attr.colorBackground};
|
||||
private int mThemeColorBackgroundResId = INVALID_ID;
|
||||
private int mBackgroundColorResId = INVALID_ID;
|
||||
|
||||
public SkinCompatCardView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatCardView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SkinCompatCardView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CardView, defStyleAttr,
|
||||
R.style.CardView);
|
||||
if (a.hasValue(R.styleable.CardView_cardBackgroundColor)) {
|
||||
mBackgroundColorResId = a.getResourceId(R.styleable.CardView_cardBackgroundColor, INVALID_ID);
|
||||
} else {
|
||||
final TypedArray aa = getContext().obtainStyledAttributes(COLOR_BACKGROUND_ATTR);
|
||||
mThemeColorBackgroundResId = aa.getResourceId(0, INVALID_ID);
|
||||
aa.recycle();
|
||||
}
|
||||
a.recycle();
|
||||
applyBackgroundColorResource();
|
||||
}
|
||||
|
||||
private void applyBackgroundColorResource() {
|
||||
mBackgroundColorResId = SkinCompatHelper.checkResourceId(mBackgroundColorResId);
|
||||
mThemeColorBackgroundResId = SkinCompatHelper.checkResourceId(mThemeColorBackgroundResId);
|
||||
ColorStateList backgroundColor;
|
||||
if (mBackgroundColorResId != INVALID_ID) {
|
||||
backgroundColor = SkinCompatResources.getColorStateList(getContext(), mBackgroundColorResId);
|
||||
setCardBackgroundColor(backgroundColor);
|
||||
} else if (mThemeColorBackgroundResId != INVALID_ID) {
|
||||
int themeColorBackground = SkinCompatResources.getColor(getContext(), mThemeColorBackgroundResId);
|
||||
final float[] hsv = new float[3];
|
||||
Color.colorToHSV(themeColorBackground, hsv);
|
||||
backgroundColor = ColorStateList.valueOf(hsv[2] > 0.5f
|
||||
? getResources().getColor(R.color.cardview_light_background)
|
||||
: getResources().getColor(R.color.cardview_dark_background));
|
||||
setCardBackgroundColor(backgroundColor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
applyBackgroundColorResource();
|
||||
}
|
||||
|
||||
}
|
||||
3
skin/skin-support-cardview/src/main/res/values/strings.xml
Executable file
3
skin/skin-support-cardview/src/main/res/values/strings.xml
Executable file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">Skin-Support-CardView</string>
|
||||
</resources>
|
||||
1
skin/skin-support-constraint-layout/.gitignore
vendored
Executable file
1
skin/skin-support-constraint-layout/.gitignore
vendored
Executable file
@@ -0,0 +1 @@
|
||||
/build
|
||||
31
skin/skin-support-constraint-layout/build.gradle
Executable file
31
skin/skin-support-constraint-layout/build.gradle
Executable file
@@ -0,0 +1,31 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
||||
// buildToolsVersion rootProject.ext.android.buildToolsVersion
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.android.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.android.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation rootProject.ext.dependencies.androidxconstraintlayout
|
||||
implementation project(':skin:skin-support')
|
||||
implementation project(':skin:skin-support-appcompat')
|
||||
}
|
||||
|
||||
ext {
|
||||
moduleName = 'skin-support-constraint-layout'
|
||||
descContent = 'ConstraintLayout控件换肤支持包'
|
||||
}
|
||||
|
||||
25
skin/skin-support-constraint-layout/proguard-rules.pro
vendored
Executable file
25
skin/skin-support-constraint-layout/proguard-rules.pro
vendored
Executable file
@@ -0,0 +1,25 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /Users/ximsfei/Library/Android/sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
2
skin/skin-support-constraint-layout/src/main/AndroidManifest.xml
Executable file
2
skin/skin-support-constraint-layout/src/main/AndroidManifest.xml
Executable file
@@ -0,0 +1,2 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="skin.support.constraint" />
|
||||
@@ -0,0 +1,45 @@
|
||||
package skin.support.constraint;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import skin.support.widget.SkinCompatBackgroundHelper;
|
||||
import skin.support.widget.SkinCompatSupportable;
|
||||
|
||||
/**
|
||||
* Created by pengfengwang on 2017/6/19.
|
||||
*/
|
||||
|
||||
public class SkinCompatConstraintLayout extends ConstraintLayout implements SkinCompatSupportable {
|
||||
private final SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinCompatConstraintLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinCompatConstraintLayout(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SkinCompatConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package skin.support.constraint;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import skin.support.SkinCompatManager;
|
||||
import skin.support.constraint.app.SkinConstraintViewInflater;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 2017/1/13.
|
||||
*/
|
||||
|
||||
public class SkinConstraintManager {
|
||||
private static volatile SkinConstraintManager sInstance;
|
||||
|
||||
public static SkinConstraintManager init(Context context) {
|
||||
if (sInstance == null) {
|
||||
synchronized (SkinConstraintManager.class) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new SkinConstraintManager(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public static SkinConstraintManager getInstance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private SkinConstraintManager(Context context) {
|
||||
SkinCompatManager.init(context).addInflater(new SkinConstraintViewInflater());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package skin.support.constraint.app;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import skin.support.app.SkinLayoutInflater;
|
||||
import skin.support.constraint.SkinCompatConstraintLayout;
|
||||
|
||||
public class SkinConstraintViewInflater implements SkinLayoutInflater {
|
||||
@Override
|
||||
public View createView(Context context, final String name, AttributeSet attrs) {
|
||||
View view = null;
|
||||
switch (name) {
|
||||
case "androidx.constraintlayout.widget.ConstraintLayout":
|
||||
view = new SkinCompatConstraintLayout(context, attrs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return view;
|
||||
}
|
||||
}
|
||||
3
skin/skin-support-constraint-layout/src/main/res/values/strings.xml
Executable file
3
skin/skin-support-constraint-layout/src/main/res/values/strings.xml
Executable file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">Skin-support-constraint-layout</string>
|
||||
</resources>
|
||||
1
skin/skin-support-design/.gitignore
vendored
Executable file
1
skin/skin-support-design/.gitignore
vendored
Executable file
@@ -0,0 +1 @@
|
||||
/build
|
||||
31
skin/skin-support-design/build.gradle
Executable file
31
skin/skin-support-design/build.gradle
Executable file
@@ -0,0 +1,31 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
||||
// buildToolsVersion rootProject.ext.android.buildToolsVersion
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.android.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.android.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation rootProject.ext.dependencies.androidxappcompat
|
||||
implementation rootProject.ext.dependencies.material
|
||||
implementation project(':skin:skin-support')
|
||||
implementation project(':skin:skin-support-appcompat')
|
||||
}
|
||||
|
||||
ext {
|
||||
moduleName = 'skin-support-design'
|
||||
descContent = 'material design控件换肤支持包'
|
||||
}
|
||||
17
skin/skin-support-design/proguard-rules.pro
vendored
Executable file
17
skin/skin-support-design/proguard-rules.pro
vendored
Executable file
@@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /Users/ximsfei/Library/Android/sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
2
skin/skin-support-design/src/main/AndroidManifest.xml
Executable file
2
skin/skin-support-design/src/main/AndroidManifest.xml
Executable file
@@ -0,0 +1,2 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="skin.support.design" />
|
||||
@@ -0,0 +1,33 @@
|
||||
package skin.support.design;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import skin.support.SkinCompatManager;
|
||||
import skin.support.design.app.SkinMaterialViewInflater;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 2017/1/13.
|
||||
*/
|
||||
|
||||
public class SkinMaterialManager {
|
||||
private static volatile SkinMaterialManager sInstance;
|
||||
|
||||
public static SkinMaterialManager init(Context context) {
|
||||
if (sInstance == null) {
|
||||
synchronized (SkinMaterialManager.class) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new SkinMaterialManager(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public static SkinMaterialManager getInstance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private SkinMaterialManager(Context context) {
|
||||
SkinCompatManager.init(context).addInflater(new SkinMaterialViewInflater());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package skin.support.design.app;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import skin.support.app.SkinLayoutInflater;
|
||||
import skin.support.design.widget.SkinMaterialAppBarLayout;
|
||||
import skin.support.design.widget.SkinMaterialBottomNavigationView;
|
||||
import skin.support.design.widget.SkinMaterialCollapsingToolbarLayout;
|
||||
import skin.support.design.widget.SkinMaterialCoordinatorLayout;
|
||||
import skin.support.design.widget.SkinMaterialFloatingActionButton;
|
||||
import skin.support.design.widget.SkinMaterialNavigationView;
|
||||
import skin.support.design.widget.SkinMaterialTabLayout;
|
||||
import skin.support.design.widget.SkinMaterialTextInputEditText;
|
||||
import skin.support.design.widget.SkinMaterialTextInputLayout;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 2017/1/13.
|
||||
*/
|
||||
public class SkinMaterialViewInflater implements SkinLayoutInflater {
|
||||
@Override
|
||||
public View createView(@NonNull Context context, final String name, @NonNull AttributeSet attrs) {
|
||||
if ("androidx.coordinatorlayout.widget.CoordinatorLayout".equals(name)) {
|
||||
return new SkinMaterialCoordinatorLayout(context, attrs);
|
||||
}
|
||||
if (!name.startsWith("com.google.android.material.")) {
|
||||
return null;
|
||||
}
|
||||
View view = null;
|
||||
switch (name) {
|
||||
case "com.google.android.material.appbar.AppBarLayout":
|
||||
view = new SkinMaterialAppBarLayout(context, attrs);
|
||||
break;
|
||||
case "com.google.android.material.tabs.TabLayout":
|
||||
view = new SkinMaterialTabLayout(context, attrs);
|
||||
break;
|
||||
case "com.google.android.material.textfield.TextInputLayout":
|
||||
view = new SkinMaterialTextInputLayout(context, attrs);
|
||||
break;
|
||||
case "com.google.android.material.textfield.TextInputEditText":
|
||||
view = new SkinMaterialTextInputEditText(context, attrs);
|
||||
break;
|
||||
case "com.google.android.material.navigation.NavigationView":
|
||||
view = new SkinMaterialNavigationView(context, attrs);
|
||||
break;
|
||||
case "com.google.android.material.floatingactionbutton.FloatingActionButton":
|
||||
view = new SkinMaterialFloatingActionButton(context, attrs);
|
||||
break;
|
||||
case "com.google.android.material.bottomnavigation.BottomNavigationView":
|
||||
view = new SkinMaterialBottomNavigationView(context, attrs);
|
||||
break;
|
||||
case "com.google.android.material.appbar.CollapsingToolbarLayout":
|
||||
view = new SkinMaterialCollapsingToolbarLayout(context, attrs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return view;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package skin.support.design.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import com.google.android.material.appbar.AppBarLayout;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import skin.support.widget.SkinCompatBackgroundHelper;
|
||||
import skin.support.widget.SkinCompatSupportable;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 2017/1/13.
|
||||
*/
|
||||
|
||||
public class SkinMaterialAppBarLayout extends AppBarLayout implements SkinCompatSupportable {
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinMaterialAppBarLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinMaterialAppBarLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package skin.support.design.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.TypedArray;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
|
||||
import skin.support.content.res.SkinCompatResources;
|
||||
import skin.support.design.R;
|
||||
import skin.support.widget.SkinCompatBackgroundHelper;
|
||||
import skin.support.widget.SkinCompatHelper;
|
||||
import skin.support.widget.SkinCompatSupportable;
|
||||
|
||||
import static skin.support.widget.SkinCompatHelper.INVALID_ID;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 17-3-1.
|
||||
*/
|
||||
|
||||
public class SkinMaterialBottomNavigationView extends BottomNavigationView implements SkinCompatSupportable {
|
||||
private static final int[] DISABLED_STATE_SET = new int[]{-android.R.attr.state_enabled};
|
||||
private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked};
|
||||
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
private int mTextColorResId = INVALID_ID;
|
||||
private int mIconTintResId = INVALID_ID;
|
||||
private int mDefaultTintResId = INVALID_ID;
|
||||
|
||||
public SkinMaterialBottomNavigationView(@NonNull Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinMaterialBottomNavigationView(@NonNull Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SkinMaterialBottomNavigationView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BottomNavigationView, defStyleAttr,
|
||||
R.style.Widget_Design_BottomNavigationView);
|
||||
|
||||
if (a.hasValue(R.styleable.BottomNavigationView_itemIconTint)) {
|
||||
mIconTintResId = a.getResourceId(R.styleable.BottomNavigationView_itemIconTint, INVALID_ID);
|
||||
} else {
|
||||
mDefaultTintResId = resolveColorPrimary();
|
||||
}
|
||||
if (a.hasValue(R.styleable.BottomNavigationView_itemTextColor)) {
|
||||
mTextColorResId = a.getResourceId(R.styleable.BottomNavigationView_itemTextColor, INVALID_ID);
|
||||
} else {
|
||||
mDefaultTintResId = resolveColorPrimary();
|
||||
}
|
||||
a.recycle();
|
||||
applyItemIconTintResource();
|
||||
applyItemTextColorResource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundResource(@DrawableRes int resId) {
|
||||
super.setBackgroundResource(resId);
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.onSetBackgroundResource(resId);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyItemTextColorResource() {
|
||||
mTextColorResId = SkinCompatHelper.checkResourceId(mTextColorResId);
|
||||
if (mTextColorResId != INVALID_ID) {
|
||||
setItemTextColor(SkinCompatResources.getColorStateList(getContext(), mTextColorResId));
|
||||
} else {
|
||||
mDefaultTintResId = SkinCompatHelper.checkResourceId(mDefaultTintResId);
|
||||
if (mDefaultTintResId != INVALID_ID) {
|
||||
setItemTextColor(createDefaultColorStateList(android.R.attr.textColorSecondary));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void applyItemIconTintResource() {
|
||||
mIconTintResId = SkinCompatHelper.checkResourceId(mIconTintResId);
|
||||
if (mIconTintResId != INVALID_ID) {
|
||||
setItemIconTintList(SkinCompatResources.getColorStateList(getContext(), mIconTintResId));
|
||||
} else {
|
||||
mDefaultTintResId = SkinCompatHelper.checkResourceId(mDefaultTintResId);
|
||||
if (mDefaultTintResId != INVALID_ID) {
|
||||
setItemIconTintList(createDefaultColorStateList(android.R.attr.textColorSecondary));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ColorStateList createDefaultColorStateList(int baseColorThemeAttr) {
|
||||
final TypedValue value = new TypedValue();
|
||||
if (!getContext().getTheme().resolveAttribute(baseColorThemeAttr, value, true)) {
|
||||
return null;
|
||||
}
|
||||
ColorStateList baseColor = SkinCompatResources.getColorStateList(getContext(), value.resourceId);
|
||||
|
||||
int colorPrimary = SkinCompatResources.getColor(getContext(), mDefaultTintResId);
|
||||
int defaultColor = baseColor.getDefaultColor();
|
||||
return new ColorStateList(new int[][]{
|
||||
DISABLED_STATE_SET,
|
||||
CHECKED_STATE_SET,
|
||||
EMPTY_STATE_SET
|
||||
}, new int[]{
|
||||
baseColor.getColorForState(DISABLED_STATE_SET, defaultColor),
|
||||
colorPrimary,
|
||||
defaultColor
|
||||
});
|
||||
}
|
||||
|
||||
private int resolveColorPrimary() {
|
||||
final TypedValue value = new TypedValue();
|
||||
if (!getContext().getTheme().resolveAttribute(
|
||||
R.attr.colorPrimary, value, true)) {
|
||||
return INVALID_ID;
|
||||
}
|
||||
return value.resourceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
applyItemIconTintResource();
|
||||
applyItemTextColorResource();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package skin.support.design.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import skin.support.content.res.SkinCompatVectorResources;
|
||||
import skin.support.design.R;
|
||||
import skin.support.widget.SkinCompatBackgroundHelper;
|
||||
import skin.support.widget.SkinCompatHelper;
|
||||
import skin.support.widget.SkinCompatSupportable;
|
||||
|
||||
import static skin.support.widget.SkinCompatHelper.INVALID_ID;
|
||||
|
||||
/**
|
||||
* Created by ximsfei on 17-3-2.
|
||||
*/
|
||||
|
||||
public class SkinMaterialCollapsingToolbarLayout extends CollapsingToolbarLayout implements SkinCompatSupportable {
|
||||
private int mContentScrimResId = INVALID_ID;
|
||||
private int mStatusBarScrimResId = INVALID_ID;
|
||||
private SkinCompatBackgroundHelper mBackgroundTintHelper;
|
||||
|
||||
public SkinMaterialCollapsingToolbarLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SkinMaterialCollapsingToolbarLayout(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SkinMaterialCollapsingToolbarLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.CollapsingToolbarLayout, defStyleAttr,
|
||||
R.style.Widget_Design_CollapsingToolbar);
|
||||
mContentScrimResId = a.getResourceId(R.styleable.CollapsingToolbarLayout_contentScrim, INVALID_ID);
|
||||
mStatusBarScrimResId = a.getResourceId(R.styleable.CollapsingToolbarLayout_statusBarScrim, INVALID_ID);
|
||||
a.recycle();
|
||||
applyContentScrimResource();
|
||||
applyStatusBarScrimResource();
|
||||
mBackgroundTintHelper = new SkinCompatBackgroundHelper(this);
|
||||
mBackgroundTintHelper.loadFromAttributes(attrs, 0);
|
||||
}
|
||||
|
||||
private void applyStatusBarScrimResource() {
|
||||
mStatusBarScrimResId = SkinCompatHelper.checkResourceId(mStatusBarScrimResId);
|
||||
if (mStatusBarScrimResId != INVALID_ID) {
|
||||
Drawable drawable = SkinCompatVectorResources.getDrawableCompat(getContext(), mStatusBarScrimResId);
|
||||
if (drawable != null) {
|
||||
setStatusBarScrim(drawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void applyContentScrimResource() {
|
||||
mContentScrimResId = SkinCompatHelper.checkResourceId(mContentScrimResId);
|
||||
if (mContentScrimResId != INVALID_ID) {
|
||||
Drawable drawable = SkinCompatVectorResources.getDrawableCompat(getContext(), mContentScrimResId);
|
||||
if (drawable != null) {
|
||||
setContentScrim(drawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin() {
|
||||
applyContentScrimResource();
|
||||
applyStatusBarScrimResource();
|
||||
if (mBackgroundTintHelper != null) {
|
||||
mBackgroundTintHelper.applySkin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user