Merge remote-tracking branch 'origin/feature/v1.0.0' into feature/v1.0.0
# Conflicts: # modules/mogo-module-tanlu/build.gradle
1
.idea/gradle.xml
generated
@@ -19,6 +19,7 @@
|
||||
<option value="$PROJECT_DIR$/libraries/mogo-map-api" />
|
||||
<option value="$PROJECT_DIR$/modules" />
|
||||
<option value="$PROJECT_DIR$/modules/mogo-module-apps" />
|
||||
<option value="$PROJECT_DIR$/modules/mogo-module-back" />
|
||||
<option value="$PROJECT_DIR$/modules/mogo-module-common" />
|
||||
<option value="$PROJECT_DIR$/modules/mogo-module-extensions" />
|
||||
<option value="$PROJECT_DIR$/modules/mogo-module-main" />
|
||||
|
||||
2
.idea/misc.xml
generated
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="JDK" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -10,7 +10,6 @@ import com.mogo.commons.AbsMogoApplication;
|
||||
import com.mogo.commons.debug.DebugConfig;
|
||||
import com.mogo.launcher.news.FreshNewsConstants;
|
||||
import com.mogo.module.adcard.AdCardConstants;
|
||||
import com.mogo.module.back.BackToMainHomeManager;
|
||||
import com.mogo.module.carchatting.card.CallChatConstant;
|
||||
import com.mogo.module.common.MogoModule;
|
||||
import com.mogo.module.common.MogoModulePaths;
|
||||
@@ -21,6 +20,8 @@ import com.mogo.module.tanlu.constant.TanluConstants;
|
||||
import com.mogo.module.v2x.V2XConst;
|
||||
import com.mogo.service.MogoServicePaths;
|
||||
import com.mogo.service.connection.IMogoSocketManager;
|
||||
import com.mogo.utils.logger.LogLevel;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
|
||||
//import com.mogo.module.onlinecar.OnLineCarConstants;
|
||||
|
||||
@@ -41,6 +42,8 @@ public class MogoApplication extends AbsMogoApplication {
|
||||
//设置debug模式,日志不上传
|
||||
crashSystem.setDebug(BuildConfig.DEBUG);
|
||||
|
||||
Logger.init( BuildConfig.DEBUG ? LogLevel.DEBUG : LogLevel.OFF );
|
||||
|
||||
// MogoModulePaths.addModule( new MogoModule( DemoConstants.TAG, "CARD_DEMO" ) );
|
||||
// MogoModulePaths.addModule( new MogoModule( Demo2Constants.TAG, "CARD_DEMO2" ) );
|
||||
DebugConfig.setNetMode(BuildConfig.NET_ENV);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<item name="android:windowContentOverlay">@null</item>
|
||||
<item name="android:windowBackground">@color/app_window_background</item>
|
||||
<item name="android:windowTranslucentNavigation">false</item>
|
||||
<item name="android:windowFullscreen">true</item>
|
||||
<item name="android:windowAnimationStyle">@style/Animation</item>
|
||||
</style>
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ ext {
|
||||
dependencies = [
|
||||
// androidx
|
||||
androidxappcompat : "androidx.appcompat:appcompat:1.0.2",
|
||||
androidxccorektx : "androidx.core:core-ktx:1.0.2",
|
||||
androidxconstraintlayout : "androidx.constraintlayout:constraintlayout:1.1.3",
|
||||
androidxmultidex : "androidx.multidex:multidex:2.0.1",
|
||||
androidxviewpager2 : "androidx.viewpager2:viewpager2:1.0.0",
|
||||
@@ -109,7 +110,7 @@ ext {
|
||||
moduleadcard : "com.mogo.module:module-adcard:${MOGO_MODULE_AD_CARD_VERSION}",
|
||||
modulefreshnews : "com.mogo.module:module-freshnews:${MOGO_MODULE_FRESH_NEWS_VERSION}",
|
||||
//统一返回键
|
||||
mogomoduleback : "com.mogo.module:module-back:${MOGO_MODULE_BACK_VERSION}",
|
||||
mogomoduleback : "com.mogo.module:module-back:${MOGO_MODULE_BACK_VERSION}",
|
||||
// 长链
|
||||
socketsdk : 'com.zhidao.socketsdk:socketsdk:2.1.0',
|
||||
socketsdkconnsvrprotoco : 'com.zhidao.ptech:connsvr-protoco:0.1.23',
|
||||
@@ -122,5 +123,13 @@ ext {
|
||||
accountsdk : "com.zhidao.accountservice:account-sdk:1.0.5",
|
||||
// crash
|
||||
crashSdk : "com.zhidaoauto.crash.log:library:1.0.5",
|
||||
kotlinstdlibjdk7 : "org.jetbrains.kotlin:kotlin-stdlib-jdk7",
|
||||
|
||||
//探路
|
||||
videoarmv7 : "com.shuyu:gsyVideoPlayer-armv7a:7.1.2",
|
||||
videoarm64 : "com.shuyu:gsyVideoPlayer-arm64:7.1.2",
|
||||
videojava : "com.shuyu:gsyVideoPlayer-java:7.1.2",
|
||||
eventbus : "org.greenrobot:eventbus:3.1.1",
|
||||
|
||||
]
|
||||
}
|
||||
@@ -62,7 +62,7 @@ public class AbsMogoApplication extends Application {
|
||||
Analytics.getInstance().setAppKey( "6bbe7e0e1ecd8e2f8dc336e1678a2791" );
|
||||
// 0 - debug 近实时上报,积累一条埋点上报,或者积累3秒上报一次。
|
||||
// 2 - 本地缓存,聚合上报,积累30条埋点上报,或者积累60秒上报一次。
|
||||
AnalyticsConfig.getInstance( sApp ).setMode( DebugConfig.isDebug() ? 0 : 2 );
|
||||
AnalyticsConfig.getInstance( sApp ).setMode( DebugConfig.isDebug() ? 2 : 2 );
|
||||
AnalyticsConfig.getInstance( sApp ).shouldLog( DebugConfig.isDebug() );
|
||||
|
||||
// 初始化 arouter
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.mogo.utils.glide;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -12,6 +13,7 @@ import com.bumptech.glide.load.engine.Resource;
|
||||
import com.bumptech.glide.load.engine.cache.ExternalPreferredCacheDiskCacheFactory;
|
||||
import com.bumptech.glide.load.engine.cache.LruResourceCache;
|
||||
import com.bumptech.glide.load.engine.cache.MemoryCache;
|
||||
import com.bumptech.glide.load.engine.executor.GlideExecutor;
|
||||
import com.bumptech.glide.module.AppGlideModule;
|
||||
|
||||
/**
|
||||
@@ -32,7 +34,9 @@ public class BaseGlideModule extends AppGlideModule {
|
||||
*
|
||||
* 是在sdcard/Android/data/包名/cache/DISK_CACHE_NAME目录当中
|
||||
*/
|
||||
builder.setLogLevel(Log.VERBOSE);
|
||||
builder.setMemoryCache( new LruResourceCache( MEMORY_CACHE_SIZE ) );
|
||||
builder.setDiskCache( new ExternalPreferredCacheDiskCacheFactory( context, DISK_CACHE_NAME, DISK_CACHE_SIZE ) );
|
||||
builder.setDiskCacheExecutor(GlideExecutor.newDiskCacheExecutor(GlideExecutor.UncaughtThrowableStrategy.DEFAULT));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import android.content.SharedPreferences;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class SharedPrefsMgr {
|
||||
|
||||
private static final String File_Name = "app_shared_pref";
|
||||
@@ -128,4 +130,17 @@ public class SharedPrefsMgr {
|
||||
}
|
||||
}
|
||||
|
||||
public void putStringSet( String key, Set< String > values ) {
|
||||
try {
|
||||
SharedPreferences.Editor editor = sSharedPrefs.edit();
|
||||
editor.putStringSet( key, values );
|
||||
editor.apply();
|
||||
} catch ( Exception e ) {
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getStringSet( String key ) {
|
||||
return sSharedPrefs.getStringSet( key, null );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -118,7 +118,7 @@ public class AMapNaviViewWrapper implements IMogoMapView,
|
||||
// 设置是否显示道路信息view
|
||||
options.setLaneInfoShow( false );
|
||||
// 设置是否自动改变缩放等级
|
||||
options.setAutoChangeZoom( false );
|
||||
options.setAutoChangeZoom( true );
|
||||
// 设置是否自动全览模式,即在算路成功后自动进入全览模式
|
||||
options.setAutoDisplayOverview( false );
|
||||
// 设置路线转向箭头隐藏和显示
|
||||
|
||||
@@ -298,6 +298,7 @@ public class AMapMarkerWrapper implements IMogoMarker, Observer {
|
||||
return mMarker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MogoMarkerOptions getMogoMarkerOptions() {
|
||||
return mMogoMarkerOptions;
|
||||
}
|
||||
|
||||
@@ -222,4 +222,11 @@ public interface IMogoMarker {
|
||||
* @param position window 的位置。
|
||||
*/
|
||||
void setPositionByPixels( Point position );
|
||||
|
||||
/**
|
||||
* Marker 配置
|
||||
* @return
|
||||
*/
|
||||
MogoMarkerOptions getMogoMarkerOptions();
|
||||
|
||||
}
|
||||
|
||||
@@ -4,8 +4,13 @@ import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
|
||||
import com.mogo.module.apps.model.AppEnum;
|
||||
import com.mogo.module.apps.model.AppEnumHelper;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
@@ -18,6 +23,7 @@ public class AppFilterImpl implements AppFilter {
|
||||
private final Context mContext;
|
||||
private List< String > mFilterPackages;
|
||||
|
||||
|
||||
public AppFilterImpl( Context context ) {
|
||||
mContext = context;
|
||||
final String[] values = context.getResources().getStringArray( R.array.module_apps_array_filter_packages );
|
||||
@@ -37,6 +43,9 @@ public class AppFilterImpl implements AppFilter {
|
||||
if ( noLaunchIntent( packageInfo ) ) {
|
||||
return true;
|
||||
}
|
||||
if ( !AppEnumHelper.isCustomizedApp( packageInfo.packageName ) ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,11 @@ public class AppsAdapter extends BaseAdapter {
|
||||
holder = ( ( AppViewHolder ) convertView.getTag() );
|
||||
}
|
||||
AppInfo appInfo = getItem( position );
|
||||
holder.mIcon.setImageDrawable( appInfo.getIcon() );
|
||||
if ( appInfo.getIconResId() <= 0 ) {
|
||||
holder.mIcon.setImageDrawable( appInfo.getIcon() );
|
||||
} else {
|
||||
holder.mIcon.setImageResource( appInfo.getIconResId() );
|
||||
}
|
||||
holder.mName.setText( appInfo.getName() );
|
||||
return holder.mItemView;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import com.alibaba.android.arouter.launcher.ARouter;
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||
import com.mogo.commons.mvp.MvpFragment;
|
||||
import com.mogo.module.apps.model.AppInfo;
|
||||
import com.mogo.module.apps.view.LinePageIndicator;
|
||||
import com.mogo.module.apps.view.PagerSlidingTabStripV2;
|
||||
import com.mogo.service.MogoServicePaths;
|
||||
import com.mogo.service.fragmentmanager.IMogoFragmentManager;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
@@ -40,7 +40,7 @@ public class AppsFragment extends MvpFragment< AppsView, AppsPresenter > impleme
|
||||
private IMogoFragmentManager mMogoFragmentManager;
|
||||
|
||||
private View mLoadingView;
|
||||
private LinePageIndicator mIndicator;
|
||||
private PagerSlidingTabStripV2 mIndicator;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
@@ -77,6 +77,7 @@ public class AppsFragment extends MvpFragment< AppsView, AppsPresenter > impleme
|
||||
mLoadingView = findViewById( R.id.module_apps_id_loading );
|
||||
mLoadingView.setVisibility( View.VISIBLE );
|
||||
mIndicator = findViewById( R.id.module_apps_id_indicator );
|
||||
mIndicator.setOpenPadding( true );
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -93,6 +94,7 @@ public class AppsFragment extends MvpFragment< AppsView, AppsPresenter > impleme
|
||||
|
||||
@Override
|
||||
public void renderApps( Map< Integer, List< AppInfo > > appInfos ) {
|
||||
mAppsPager.setOffscreenPageLimit( appInfos.size() );
|
||||
mLoadingView.setVisibility( View.GONE );
|
||||
if ( mAppsPagerAdapter == null ) {
|
||||
mAppsPagerAdapter = new AppsPagerAdapter( appInfos );
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.mogo.module.apps;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -8,8 +9,12 @@ import android.widget.GridView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.mogo.module.apps.model.AppInfo;
|
||||
import com.mogo.module.apps.view.PagerIndicator;
|
||||
import com.mogo.module.apps.view.PagerSlidingTabStripV2;
|
||||
import com.mogo.utils.ResourcesHelper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -20,7 +25,7 @@ import java.util.Map;
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class AppsPagerAdapter extends PagerAdapter {
|
||||
public class AppsPagerAdapter extends PagerAdapter implements PagerSlidingTabStripV2.ViewTabProvider {
|
||||
|
||||
private Map< Integer, List< AppInfo > > mPagedApps;
|
||||
private OnAppClickedListener mOnAppClickedListener;
|
||||
@@ -82,4 +87,9 @@ public class AppsPagerAdapter extends PagerAdapter {
|
||||
public interface OnAppClickedListener {
|
||||
void onClick( AppInfo appInfo, int position );
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getPageTabView( Context context, int position ) {
|
||||
return new PagerIndicator( context );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import com.mogo.service.analytics.IMogoAnalytics;
|
||||
import com.mogo.service.cardmanager.IMogoCardManager;
|
||||
import com.mogo.utils.ThreadPoolService;
|
||||
import com.mogo.utils.UiThreadHandler;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -58,6 +59,8 @@ public class AppsPresenter extends Presenter< AppsView > {
|
||||
private void renderAppsList() {
|
||||
ThreadPoolService.execute( () -> {
|
||||
AppsModel.getInstance( getContext() ).load( appInfoList -> {
|
||||
|
||||
Logger.d( TAG, "apps: %s", appInfoList );
|
||||
UiThreadHandler.post( () -> {
|
||||
if ( mView != null ) {
|
||||
mView.renderApps( appInfoList );
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.mogo.module.apps.model;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-02-12
|
||||
* <p>
|
||||
* 定制化的 app 列表
|
||||
* <p>
|
||||
* <p>
|
||||
* 自研类:QQ音乐、车聊聊、探路、新鲜事、福利、蘑菇小队、行车记录仪、懒人听书、一键清理、系统升级
|
||||
* 第三方:车机微信助手、爱奇艺、喜马拉雅
|
||||
* 基础类:均衡器、方控学习、蓝牙、FM、车载设置、AUX
|
||||
*/
|
||||
public enum AppEnum {
|
||||
|
||||
//"QQ音乐",
|
||||
QQMusic( "com.pvetec.musics", 0 ),
|
||||
|
||||
//"车聊聊",
|
||||
Im( "com.zhidao.imdemo", 0 ),
|
||||
|
||||
//"探路",
|
||||
RoadCondition( "com.zhidao.roadcondition", 0 ),
|
||||
RoadConditionSlit( "com.zhidao.roadcondition.split", 0 ),
|
||||
|
||||
//"福利",
|
||||
Welfare( "com.zhidaohulian.welfare.car", 0 ),
|
||||
|
||||
//"蘑菇小队",
|
||||
Fleet( "com.zhidao.fleet", 0 ),
|
||||
|
||||
//"行车记录仪",
|
||||
CarCorder( "com.zhidao.carcorder", 0 ),
|
||||
|
||||
//"懒人听书",
|
||||
Lrts( "com.zhidao.lrts", 0 ),
|
||||
|
||||
//"一键清理",
|
||||
CleanMaster( "com.zhidao.cleanmaster", 0 ),
|
||||
|
||||
//"系统升级",
|
||||
Fota( "com.abupdate.fota_demo_iot", 0 ),
|
||||
|
||||
//"微信车机助手",
|
||||
WecahtHelper( "com.zhidao.wechathelper", 0 ),
|
||||
|
||||
//"爱奇艺HD",
|
||||
Qiyi( "com.qiyi.video.pad", 0 ),
|
||||
|
||||
//"喜马拉雅",
|
||||
Ximalaya( "com.ximalaya.ting.android.car", 0 ),
|
||||
|
||||
//"均衡器",
|
||||
Equlizer( "com.zhidao.equalizer", 0 ),
|
||||
|
||||
//"方控学习",
|
||||
SteerProduct( "com.zd.steerproduct", 0 ),
|
||||
|
||||
//"蓝牙音乐",
|
||||
BTMusic( "com.nwd.bt.music", 0 ),
|
||||
|
||||
//"车载设置",
|
||||
CarSettings( "com.zhidao.settings", 0 ),
|
||||
|
||||
//"AUX",
|
||||
AUX( "com.nwd.auxin", 0 ),
|
||||
|
||||
//FM
|
||||
FM( " com.nwd.radio", 0 ),
|
||||
|
||||
// 新鲜事
|
||||
FreshThins( "com.zhidao.fresh.things", 0 ),
|
||||
;
|
||||
|
||||
private String mPkg;
|
||||
private int mIconResId;
|
||||
|
||||
AppEnum( String pkg, int iconResId ) {
|
||||
this.mPkg = pkg;
|
||||
this.mIconResId = iconResId;
|
||||
}
|
||||
|
||||
public String getPkg() {
|
||||
return mPkg;
|
||||
}
|
||||
|
||||
public int getIconResId() {
|
||||
return mIconResId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.mogo.module.apps.model;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-02-12
|
||||
* <p>
|
||||
* 定制化的app
|
||||
*/
|
||||
public class AppEnumHelper {
|
||||
|
||||
private static Map< String, AppEnum > sCustomizedApps = new HashMap<>();
|
||||
|
||||
static {
|
||||
AppEnum[] customizedApps = AppEnum.values();
|
||||
for ( AppEnum customizedApp : customizedApps ) {
|
||||
sCustomizedApps.put( customizedApp.getPkg(), customizedApp );
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isCustomizedApp( String pkg ) {
|
||||
return sCustomizedApps.containsKey( pkg );
|
||||
}
|
||||
|
||||
public static int getCustomizedAppIconResId( String pkg ) {
|
||||
AppEnum appEnum = sCustomizedApps.get( pkg );
|
||||
if ( appEnum != null ) {
|
||||
return appEnum.getIconResId();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -15,13 +15,19 @@ public class AppInfo {
|
||||
private final String mVersionName;
|
||||
private final int mVersionCode;
|
||||
private final Drawable mIcon;
|
||||
private final int mIconResId;
|
||||
|
||||
public AppInfo( String name, String mPackageName, String mVersionName, int versionCode, Drawable icon ) {
|
||||
this.mName = name;
|
||||
public AppInfo( String mName, String mPackageName, String mVersionName, int mVersionCode, Drawable mIcon, int mIconResId ) {
|
||||
this.mName = mName;
|
||||
this.mPackageName = mPackageName;
|
||||
this.mVersionName = mVersionName;
|
||||
this.mVersionCode = versionCode;
|
||||
this.mIcon = icon;
|
||||
this.mVersionCode = mVersionCode;
|
||||
this.mIcon = mIcon;
|
||||
this.mIconResId = mIconResId;
|
||||
}
|
||||
|
||||
public int getIconResId() {
|
||||
return mIconResId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
||||
@@ -79,7 +79,7 @@ public class AppsModel {
|
||||
String versionName = packageInfo.versionName;
|
||||
int versionCode = packageInfo.versionCode;
|
||||
Drawable appIcon = packageInfo.applicationInfo.loadIcon( packageManager );
|
||||
AppInfo appInfo = new AppInfo( appName, packageName, versionName, versionCode, appIcon );
|
||||
AppInfo appInfo = new AppInfo( appName, packageName, versionName, versionCode, appIcon, AppEnumHelper.getCustomizedAppIconResId( packageName ) );
|
||||
mPagedApps.get( page ).add( appInfo );
|
||||
}
|
||||
if ( callback != null ) {
|
||||
@@ -106,7 +106,7 @@ public class AppsModel {
|
||||
String versionName = packageInfo.versionName;
|
||||
int versionCode = packageInfo.versionCode;
|
||||
Drawable appIcon = packageInfo.applicationInfo.loadIcon( packageManager );
|
||||
AppInfo appInfo = new AppInfo( appName, packageName, versionName, versionCode, appIcon );
|
||||
AppInfo appInfo = new AppInfo( appName, packageName, versionName, versionCode, appIcon, AppEnumHelper.getCustomizedAppIconResId( packageName ) );
|
||||
int pageIndex = getPageIndex( packageName, true );
|
||||
if ( !mPagedApps.containsKey( pageIndex ) ) {
|
||||
mPagedApps.put( pageIndex, new ArrayList<>() );
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.mogo.module.apps.model;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-02-09
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class CardAppInfo extends AppInfo {
|
||||
|
||||
private String mCardType;
|
||||
|
||||
public CardAppInfo( AppInfo app, String cardType ) {
|
||||
super( app.getName(), app.getPackageName(), app.getVersionName(), app.getVersionCode(), app.getIcon() );
|
||||
this.mCardType = cardType;
|
||||
}
|
||||
}
|
||||
@@ -1,455 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Jake Wharton
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.mogo.module.apps.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import androidx.core.view.MotionEventCompat;
|
||||
import androidx.core.view.ViewConfigurationCompat;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.mogo.module.apps.R;
|
||||
|
||||
/**
|
||||
* Draws a line for each page. The current page line is colored differently
|
||||
* than the unselected page lines.
|
||||
*/
|
||||
public class LinePageIndicator extends View implements PageIndicator {
|
||||
private static final int INVALID_POINTER = -1;
|
||||
|
||||
private final Paint mPaintUnselected = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
private final Paint mPaintSelected = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
private ViewPager mViewPager;
|
||||
private ViewPager.OnPageChangeListener mListener;
|
||||
private int mCurrentPage;
|
||||
private boolean mCentered;
|
||||
private float mLineWidth;
|
||||
private float mGapWidth;
|
||||
|
||||
private int mTouchSlop;
|
||||
private float mLastMotionX = -1;
|
||||
private int mActivePointerId = INVALID_POINTER;
|
||||
private boolean mIsDragging;
|
||||
|
||||
|
||||
public LinePageIndicator(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public LinePageIndicator(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.vpiLinePageIndicatorStyle);
|
||||
}
|
||||
|
||||
public LinePageIndicator(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
if (isInEditMode()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Resources res = getResources();
|
||||
|
||||
//Load defaults from resources
|
||||
final int defaultSelectedColor = res.getColor(R.color.default_line_indicator_selected_color);
|
||||
final int defaultUnselectedColor = res.getColor(R.color.default_line_indicator_unselected_color);
|
||||
final float defaultLineWidth = res.getDimension(R.dimen.default_line_indicator_line_width);
|
||||
final float defaultGapWidth = res.getDimension(R.dimen.default_line_indicator_gap_width);
|
||||
final float defaultStrokeWidth = res.getDimension(R.dimen.default_line_indicator_stroke_width);
|
||||
final boolean defaultCentered = res.getBoolean(R.bool.default_line_indicator_centered);
|
||||
|
||||
//Retrieve styles attributes
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LinePageIndicator, defStyle, 0);
|
||||
|
||||
mCentered = a.getBoolean(R.styleable.LinePageIndicator_centered, defaultCentered);
|
||||
mLineWidth = a.getDimension(R.styleable.LinePageIndicator_lineWidth, defaultLineWidth);
|
||||
mGapWidth = a.getDimension(R.styleable.LinePageIndicator_gapWidth, defaultGapWidth);
|
||||
setStrokeWidth(a.getDimension(R.styleable.LinePageIndicator_strokeWidth, defaultStrokeWidth));
|
||||
mPaintUnselected.setColor(a.getColor(R.styleable.LinePageIndicator_unselectedColor, defaultUnselectedColor));
|
||||
mPaintSelected.setColor(a.getColor(R.styleable.LinePageIndicator_selectedColor, defaultSelectedColor));
|
||||
|
||||
Drawable background = a.getDrawable(R.styleable.LinePageIndicator_android_background);
|
||||
if (background != null) {
|
||||
setBackgroundDrawable(background);
|
||||
}
|
||||
|
||||
a.recycle();
|
||||
|
||||
final ViewConfiguration configuration = ViewConfiguration.get(context);
|
||||
mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
|
||||
}
|
||||
|
||||
|
||||
public void setCentered(boolean centered) {
|
||||
mCentered = centered;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public boolean isCentered() {
|
||||
return mCentered;
|
||||
}
|
||||
|
||||
public void setUnselectedColor(int unselectedColor) {
|
||||
mPaintUnselected.setColor(unselectedColor);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public int getUnselectedColor() {
|
||||
return mPaintUnselected.getColor();
|
||||
}
|
||||
|
||||
public void setSelectedColor(int selectedColor) {
|
||||
mPaintSelected.setColor(selectedColor);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public int getSelectedColor() {
|
||||
return mPaintSelected.getColor();
|
||||
}
|
||||
|
||||
public void setLineWidth(float lineWidth) {
|
||||
mLineWidth = lineWidth;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public float getLineWidth() {
|
||||
return mLineWidth;
|
||||
}
|
||||
|
||||
public void setStrokeWidth(float lineHeight) {
|
||||
mPaintSelected.setStrokeWidth(lineHeight);
|
||||
mPaintUnselected.setStrokeWidth(lineHeight);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public float getStrokeWidth() {
|
||||
return mPaintSelected.getStrokeWidth();
|
||||
}
|
||||
|
||||
public void setGapWidth(float gapWidth) {
|
||||
mGapWidth = gapWidth;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public float getGapWidth() {
|
||||
return mGapWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
if (mViewPager == null) {
|
||||
return;
|
||||
}
|
||||
final int count = mViewPager.getAdapter().getCount();
|
||||
if (count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCurrentPage >= count) {
|
||||
setCurrentItem(count - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
final float lineWidthAndGap = mLineWidth + mGapWidth;
|
||||
final float indicatorWidth = (count * lineWidthAndGap) - mGapWidth;
|
||||
final float paddingTop = getPaddingTop();
|
||||
final float paddingLeft = getPaddingLeft();
|
||||
final float paddingRight = getPaddingRight();
|
||||
|
||||
float verticalOffset = paddingTop + ((getHeight() - paddingTop - getPaddingBottom()) / 2.0f);
|
||||
float horizontalOffset = paddingLeft;
|
||||
if (mCentered) {
|
||||
horizontalOffset += ((getWidth() - paddingLeft - paddingRight) / 2.0f) - (indicatorWidth / 2.0f);
|
||||
}
|
||||
|
||||
//Draw stroked circles
|
||||
for (int i = 0; i < count; i++) {
|
||||
float dx1 = horizontalOffset + (i * lineWidthAndGap);
|
||||
float dx2 = dx1 + mLineWidth;
|
||||
canvas.drawLine(dx1, verticalOffset, dx2, verticalOffset, (i == mCurrentPage) ? mPaintSelected : mPaintUnselected);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
if (super.onTouchEvent(ev)) {
|
||||
return true;
|
||||
}
|
||||
if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
|
||||
mLastMotionX = ev.getX();
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
|
||||
final float x = MotionEventCompat.getX(ev, activePointerIndex);
|
||||
final float deltaX = x - mLastMotionX;
|
||||
|
||||
if (!mIsDragging) {
|
||||
if (Math.abs(deltaX) > mTouchSlop) {
|
||||
mIsDragging = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mIsDragging) {
|
||||
mLastMotionX = x;
|
||||
if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) {
|
||||
mViewPager.fakeDragBy(deltaX);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
case MotionEvent.ACTION_UP:
|
||||
if (!mIsDragging) {
|
||||
final int count = mViewPager.getAdapter().getCount();
|
||||
final int width = getWidth();
|
||||
final float halfWidth = width / 2f;
|
||||
final float sixthWidth = width / 6f;
|
||||
|
||||
if ((mCurrentPage > 0) && (ev.getX() < halfWidth - sixthWidth)) {
|
||||
if (action != MotionEvent.ACTION_CANCEL) {
|
||||
mViewPager.setCurrentItem(mCurrentPage - 1);
|
||||
}
|
||||
return true;
|
||||
} else if ((mCurrentPage < count - 1) && (ev.getX() > halfWidth + sixthWidth)) {
|
||||
if (action != MotionEvent.ACTION_CANCEL) {
|
||||
mViewPager.setCurrentItem(mCurrentPage + 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
mIsDragging = false;
|
||||
mActivePointerId = INVALID_POINTER;
|
||||
if (mViewPager.isFakeDragging()) {
|
||||
mViewPager.endFakeDrag();
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionEventCompat.ACTION_POINTER_DOWN: {
|
||||
final int index = MotionEventCompat.getActionIndex(ev);
|
||||
mLastMotionX = MotionEventCompat.getX(ev, index);
|
||||
mActivePointerId = MotionEventCompat.getPointerId(ev, index);
|
||||
break;
|
||||
}
|
||||
|
||||
case MotionEventCompat.ACTION_POINTER_UP:
|
||||
final int pointerIndex = MotionEventCompat.getActionIndex(ev);
|
||||
final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
|
||||
if (pointerId == mActivePointerId) {
|
||||
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
|
||||
mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
|
||||
}
|
||||
mLastMotionX = MotionEventCompat.getX(ev, MotionEventCompat.findPointerIndex(ev, mActivePointerId));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setViewPager(ViewPager viewPager) {
|
||||
if (mViewPager == viewPager) {
|
||||
return;
|
||||
}
|
||||
if (mViewPager != null) {
|
||||
//Clear us from the old pager.
|
||||
// mViewPager.setOnPageChangeListener(null);
|
||||
}
|
||||
if (viewPager.getAdapter() == null) {
|
||||
throw new IllegalStateException("ViewPager does not have adapter instance.");
|
||||
}
|
||||
mViewPager = viewPager;
|
||||
mViewPager.setOnPageChangeListener(this);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setViewPager(ViewPager view, int initialPosition) {
|
||||
setViewPager(view);
|
||||
setCurrentItem(initialPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentItem(int item) {
|
||||
if (mViewPager == null) {
|
||||
throw new IllegalStateException("ViewPager has not been bound.");
|
||||
}
|
||||
mViewPager.setCurrentItem(item);
|
||||
mCurrentPage = item;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyDataSetChanged() {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
if (mListener != null) {
|
||||
mListener.onPageScrollStateChanged(state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
if (mListener != null) {
|
||||
mListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
mCurrentPage = position;
|
||||
invalidate();
|
||||
|
||||
if (mListener != null) {
|
||||
mListener.onPageSelected(position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the width of this view
|
||||
*
|
||||
* @param measureSpec
|
||||
* A measureSpec packed into an int
|
||||
* @return The width of the view, honoring constraints from measureSpec
|
||||
*/
|
||||
private int measureWidth(int measureSpec) {
|
||||
float result;
|
||||
int specMode = MeasureSpec.getMode(measureSpec);
|
||||
int specSize = MeasureSpec.getSize(measureSpec);
|
||||
|
||||
if ((specMode == MeasureSpec.EXACTLY) || (mViewPager == null)) {
|
||||
//We were told how big to be
|
||||
result = specSize;
|
||||
} else {
|
||||
//Calculate the width according the views count
|
||||
final int count = mViewPager.getAdapter().getCount();
|
||||
result = getPaddingLeft() + getPaddingRight() + (count * mLineWidth) + ((count - 1) * mGapWidth);
|
||||
//Respect AT_MOST value if that was what is called for by measureSpec
|
||||
if (specMode == MeasureSpec.AT_MOST) {
|
||||
result = Math.min(result, specSize);
|
||||
}
|
||||
}
|
||||
return (int)Math.ceil(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the height of this view
|
||||
*
|
||||
* @param measureSpec
|
||||
* A measureSpec packed into an int
|
||||
* @return The height of the view, honoring constraints from measureSpec
|
||||
*/
|
||||
private int measureHeight(int measureSpec) {
|
||||
float result;
|
||||
int specMode = MeasureSpec.getMode(measureSpec);
|
||||
int specSize = MeasureSpec.getSize(measureSpec);
|
||||
|
||||
if (specMode == MeasureSpec.EXACTLY) {
|
||||
//We were told how big to be
|
||||
result = specSize;
|
||||
} else {
|
||||
//Measure the height
|
||||
result = mPaintSelected.getStrokeWidth() + getPaddingTop() + getPaddingBottom();
|
||||
//Respect AT_MOST value if that was what is called for by measureSpec
|
||||
if (specMode == MeasureSpec.AT_MOST) {
|
||||
result = Math.min(result, specSize);
|
||||
}
|
||||
}
|
||||
return (int)Math.ceil(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreInstanceState(Parcelable state) {
|
||||
SavedState savedState = (SavedState)state;
|
||||
super.onRestoreInstanceState(savedState.getSuperState());
|
||||
mCurrentPage = savedState.currentPage;
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parcelable onSaveInstanceState() {
|
||||
Parcelable superState = super.onSaveInstanceState();
|
||||
SavedState savedState = new SavedState(superState);
|
||||
savedState.currentPage = mCurrentPage;
|
||||
return savedState;
|
||||
}
|
||||
|
||||
static class SavedState extends BaseSavedState {
|
||||
int currentPage;
|
||||
|
||||
public SavedState(Parcelable superState) {
|
||||
super(superState);
|
||||
}
|
||||
|
||||
private SavedState(Parcel in) {
|
||||
super(in);
|
||||
currentPage = in.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
dest.writeInt(currentPage);
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
|
||||
@Override
|
||||
public SavedState createFromParcel(Parcel in) {
|
||||
return new SavedState(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavedState[] newArray(int size) {
|
||||
return new SavedState[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Patrik Akerfeldt
|
||||
* Copyright (C) 2011 Jake Wharton
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.mogo.module.apps.view;
|
||||
|
||||
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
/**
|
||||
* A PageIndicator is responsible to show an visual indicator on the total views
|
||||
* number and the current visible view.
|
||||
*/
|
||||
public interface PageIndicator extends ViewPager.OnPageChangeListener {
|
||||
/**
|
||||
* Bind the indicator to a ViewPager.
|
||||
*
|
||||
* @param view
|
||||
*/
|
||||
void setViewPager( ViewPager view );
|
||||
|
||||
/**
|
||||
* Bind the indicator to a ViewPager.
|
||||
*
|
||||
* @param view
|
||||
* @param initialPosition
|
||||
*/
|
||||
void setViewPager( ViewPager view, int initialPosition );
|
||||
|
||||
/**
|
||||
* <p>Set the current page of both the ViewPager and indicator.</p>
|
||||
*
|
||||
* <p>This <strong>must</strong> be used if you need to set the page before
|
||||
* the views are drawn on screen (e.g., default start page).</p>
|
||||
*
|
||||
* @param item
|
||||
*/
|
||||
void setCurrentItem( int item );
|
||||
|
||||
/**
|
||||
* Set a page change listener which will receive forwarded events.
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
void setOnPageChangeListener( ViewPager.OnPageChangeListener listener );
|
||||
|
||||
/**
|
||||
* Notify the indicator that the fragment list has changed.
|
||||
*/
|
||||
void notifyDataSetChanged();
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.mogo.module.apps.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.mogo.module.apps.R;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-02-11
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class PagerIndicator extends LinearLayout implements PagerSlidingTabStripV2.SelectedState {
|
||||
|
||||
private View mIndicator;
|
||||
|
||||
public PagerIndicator( Context context ) {
|
||||
this( context, null );
|
||||
}
|
||||
|
||||
public PagerIndicator( Context context, @Nullable AttributeSet attrs ) {
|
||||
this( context, attrs, 0 );
|
||||
}
|
||||
|
||||
public PagerIndicator( Context context, @Nullable AttributeSet attrs, int defStyleAttr ) {
|
||||
super( context, attrs, defStyleAttr );
|
||||
LayoutInflater.from( context ).inflate( R.layout.modle_apps_page_indicator, this, true );
|
||||
mIndicator = findViewById( R.id.module_apps_id_indicator_dot );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedState( boolean isSelected ) {
|
||||
mIndicator.setSelected( isSelected );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,763 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Andreas Stuetz <andreas.stuetz@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.mogo.module.apps.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
|
||||
import android.widget.HorizontalScrollView;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
|
||||
import com.mogo.module.apps.R;
|
||||
import com.mogo.utils.WindowUtils;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Reference : http://doc.okbase.net/HarryWeasley/archive/121430.html
|
||||
*/
|
||||
public class PagerSlidingTabStripV2 extends HorizontalScrollView {
|
||||
|
||||
public interface IconTabProvider {
|
||||
public int getPageIconResId( int position );
|
||||
}
|
||||
|
||||
public interface ViewTabProvider {
|
||||
public View getPageTabView( Context context, int position );
|
||||
}
|
||||
|
||||
public interface SelectedState {
|
||||
void setSelectedState( boolean isSelected );
|
||||
}
|
||||
|
||||
// @formatter:off
|
||||
private static final int[] ATTRS = new int[]{
|
||||
android.R.attr.textSize,
|
||||
android.R.attr.textColor
|
||||
};
|
||||
// @formatter:on
|
||||
|
||||
public interface OnBeforeTabAction {
|
||||
boolean doAction( int position );
|
||||
}
|
||||
|
||||
private LinearLayout.LayoutParams defaultTabLayoutParams;
|
||||
private LinearLayout.LayoutParams expandedTabLayoutParams;
|
||||
|
||||
private final PageListener pageListener = new PageListener();
|
||||
public ViewPager.OnPageChangeListener delegatePageListener;
|
||||
|
||||
private LinearLayout tabsContainer;
|
||||
private ViewPager pager;
|
||||
|
||||
private int tabCount;
|
||||
|
||||
private int currentPosition = 0;
|
||||
private int selectedPosition = 0;
|
||||
private float currentPositionOffset = 0f;
|
||||
|
||||
private Paint rectPaint;
|
||||
private Paint dividerPaint;
|
||||
|
||||
private int indicatorColor = 0xFF666666;
|
||||
private int underlineColor = 0x1A000000;
|
||||
private int dividerColor = 0x1A000000;
|
||||
|
||||
private boolean shouldExpand = false;
|
||||
private boolean textAllCaps = true;
|
||||
|
||||
private int scrollOffset = 52;
|
||||
private int indicatorHeight = 8;
|
||||
private int underlineHeight = 2;
|
||||
private int dividerPadding = 12;
|
||||
private int tabPadding = 24;
|
||||
private int dividerWidth = 1;
|
||||
private int indicatorMarginBottom = 0;
|
||||
private int indicatorMarginLeft = 0;
|
||||
private int indicatorMarginRight = 0;
|
||||
|
||||
private int tabTextSize = 13;
|
||||
private int tabTextColor = 0xFF666666;
|
||||
private int selectedTabTextColor = 0xFF666666;
|
||||
|
||||
private Typeface tabTypeface = null;
|
||||
private int tabTypefaceStyle = Typeface.NORMAL;
|
||||
|
||||
private int lastScrollX = 0;
|
||||
|
||||
private int tabBackgroundResId = R.drawable.module_apps_pager_sliding_background_tab;
|
||||
|
||||
public static final int INDICATOR_MODE_UNDERLINE = -1;
|
||||
public static final int INDICATOR_MODE_SHADOW = 1;
|
||||
public static final int INDICATOR_MODE_RES = 2;
|
||||
private int indicatorMode = INDICATOR_MODE_SHADOW;
|
||||
|
||||
private Drawable indicatorRes;
|
||||
|
||||
public static final int INDICATOR_FIT_MODE_AUTO = 0;
|
||||
public static final int INDICATOR_FIT_MODE_FIXED = 1;
|
||||
private int indicatorFitMode = INDICATOR_FIT_MODE_AUTO;
|
||||
|
||||
private float indicatorFixedSize = 0;
|
||||
|
||||
private Locale locale;
|
||||
|
||||
private OnBeforeTabAction onBeforeTabAction;
|
||||
private boolean openPadding = false;
|
||||
|
||||
|
||||
public boolean isOpenPadding() {
|
||||
return openPadding;
|
||||
}
|
||||
|
||||
public void setOpenPadding( boolean openPadding ) {
|
||||
this.openPadding = openPadding;
|
||||
}
|
||||
|
||||
public PagerSlidingTabStripV2( Context context ) {
|
||||
this( context, null );
|
||||
}
|
||||
|
||||
public PagerSlidingTabStripV2( Context context, AttributeSet attrs ) {
|
||||
this( context, attrs, 0 );
|
||||
}
|
||||
|
||||
public PagerSlidingTabStripV2( Context context, AttributeSet attrs, int defStyle ) {
|
||||
super( context, attrs, defStyle );
|
||||
|
||||
setFillViewport( true );
|
||||
setWillNotDraw( false );
|
||||
|
||||
tabsContainer = new LinearLayout( context );
|
||||
tabsContainer.setOrientation( LinearLayout.HORIZONTAL );
|
||||
tabsContainer.setLayoutParams( new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT ) );
|
||||
addView( tabsContainer );
|
||||
|
||||
DisplayMetrics dm = getResources().getDisplayMetrics();
|
||||
|
||||
scrollOffset = ( int ) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, scrollOffset, dm );
|
||||
indicatorHeight = ( int ) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, indicatorHeight, dm );
|
||||
underlineHeight = ( int ) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, underlineHeight, dm );
|
||||
dividerPadding = ( int ) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dividerPadding, dm );
|
||||
tabPadding = ( int ) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, tabPadding, dm );
|
||||
dividerWidth = ( int ) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dividerWidth, dm );
|
||||
tabTextSize = ( int ) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, tabTextSize, dm );
|
||||
indicatorMarginBottom = ( int ) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, indicatorMarginBottom, dm );
|
||||
indicatorMarginLeft = ( int ) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, indicatorMarginLeft, dm );
|
||||
indicatorMarginRight = ( int ) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, indicatorMarginRight, dm );
|
||||
|
||||
// get system attrs (android:textSize and android:textColor)
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes( attrs, ATTRS );
|
||||
|
||||
tabTextSize = a.getDimensionPixelSize( 0, tabTextSize );
|
||||
tabTextColor = a.getColor( 1, tabTextColor );
|
||||
|
||||
a.recycle();
|
||||
|
||||
// get custom attrs
|
||||
|
||||
a = context.obtainStyledAttributes( attrs, R.styleable.PagerSlidingTabStripV2 );
|
||||
|
||||
indicatorColor = a.getColor( R.styleable.PagerSlidingTabStripV2_pstsV2IndicatorColor, indicatorColor );
|
||||
//tab文字选中时的颜色,默认和滑动指示器的颜色一致
|
||||
selectedTabTextColor = a.getColor( R.styleable.PagerSlidingTabStripV2_pstsV2SelectedTabTextColor, indicatorColor );
|
||||
tabTextColor = a.getColor( R.styleable.PagerSlidingTabStripV2_pstsV2TabTextColorValue, tabTextColor );
|
||||
underlineColor = a.getColor( R.styleable.PagerSlidingTabStripV2_pstsV2UnderlineColor, underlineColor );
|
||||
dividerColor = a.getColor( R.styleable.PagerSlidingTabStripV2_pstsV2DividerColor, dividerColor );
|
||||
indicatorHeight = a.getDimensionPixelSize( R.styleable.PagerSlidingTabStripV2_pstsV2IndicatorHeight, indicatorHeight );
|
||||
underlineHeight = a.getDimensionPixelSize( R.styleable.PagerSlidingTabStripV2_pstsV2UnderlineHeight, underlineHeight );
|
||||
dividerPadding = a.getDimensionPixelSize( R.styleable.PagerSlidingTabStripV2_pstsV2DividerPadding, dividerPadding );
|
||||
tabPadding = a.getDimensionPixelSize( R.styleable.PagerSlidingTabStripV2_pstsV2TabPaddingLeftRight, tabPadding );
|
||||
tabBackgroundResId = a.getResourceId( R.styleable.PagerSlidingTabStripV2_pstsV2TabBackground, tabBackgroundResId );
|
||||
shouldExpand = a.getBoolean( R.styleable.PagerSlidingTabStripV2_pstsV2ShouldExpand, shouldExpand );
|
||||
scrollOffset = a.getDimensionPixelSize( R.styleable.PagerSlidingTabStripV2_pstsV2ScrollOffset, scrollOffset );
|
||||
textAllCaps = a.getBoolean( R.styleable.PagerSlidingTabStripV2_pstsV2TextAllCaps, textAllCaps );
|
||||
indicatorMarginBottom = a.getDimensionPixelSize( R.styleable.PagerSlidingTabStripV2_pstsV2IndicatorMarginBottom, indicatorMarginBottom );
|
||||
indicatorMarginLeft = a.getDimensionPixelSize( R.styleable.PagerSlidingTabStripV2_pstsV2IndicatorMarginLeft, indicatorMarginLeft );
|
||||
indicatorMarginRight = a.getDimensionPixelSize( R.styleable.PagerSlidingTabStripV2_pstsV2IndicatorMarginRight, indicatorMarginRight );
|
||||
indicatorMode = a.getInt( R.styleable.PagerSlidingTabStripV2_pstsV2IndicatorMode, INDICATOR_MODE_SHADOW );
|
||||
indicatorRes = a.getDrawable( R.styleable.PagerSlidingTabStripV2_pstsV2IndicatorRes );
|
||||
a.recycle();
|
||||
|
||||
rectPaint = new Paint();
|
||||
rectPaint.setAntiAlias( true );
|
||||
rectPaint.setStyle( Style.FILL );
|
||||
|
||||
dividerPaint = new Paint();
|
||||
dividerPaint.setAntiAlias( true );
|
||||
dividerPaint.setStrokeWidth( dividerWidth );
|
||||
|
||||
defaultTabLayoutParams = new LinearLayout.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT );
|
||||
expandedTabLayoutParams = new LinearLayout.LayoutParams( 0, LayoutParams.MATCH_PARENT, 1.0f );
|
||||
|
||||
if ( locale == null ) {
|
||||
locale = getResources().getConfiguration().locale;
|
||||
}
|
||||
}
|
||||
|
||||
public OnBeforeTabAction getOnBeforeTabAction() {
|
||||
return onBeforeTabAction;
|
||||
}
|
||||
|
||||
public void setOnBeforeTabAction( OnBeforeTabAction onBeforeTabAction ) {
|
||||
this.onBeforeTabAction = onBeforeTabAction;
|
||||
}
|
||||
|
||||
public void setViewPager( ViewPager pager ) {
|
||||
this.pager = pager;
|
||||
this.currentPosition = this.selectedPosition = pager.getCurrentItem();
|
||||
|
||||
if ( pager.getAdapter() == null ) {
|
||||
throw new IllegalStateException( "ViewPager does not have adapter instance." );
|
||||
}
|
||||
|
||||
pager.removeOnPageChangeListener( pageListener );
|
||||
pager.addOnPageChangeListener( pageListener );
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void setOnPageChangeListener( ViewPager.OnPageChangeListener listener ) {
|
||||
this.delegatePageListener = listener;
|
||||
}
|
||||
|
||||
public void notifyDataSetChanged() {
|
||||
|
||||
indicatorLineOffset = -1;
|
||||
tabsContainer.removeAllViews();
|
||||
|
||||
tabCount = pager.getAdapter().getCount();
|
||||
|
||||
for ( int i = 0; i < tabCount; i++ ) {
|
||||
|
||||
if ( pager.getAdapter() instanceof ViewTabProvider ) {
|
||||
addViewTab( i, ( ( ViewTabProvider ) pager.getAdapter() ).getPageTabView( getContext(), i ) );
|
||||
} else {
|
||||
addTextTab( i, TextUtils.isEmpty( pager.getAdapter().getPageTitle( i ) ) ? "" : pager.getAdapter().getPageTitle( i ).toString() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
updateTabStyles();
|
||||
|
||||
getViewTreeObserver().addOnGlobalLayoutListener( new OnGlobalLayoutListener() {
|
||||
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
getViewTreeObserver().removeGlobalOnLayoutListener( this );
|
||||
currentPosition = pager.getCurrentItem();
|
||||
scrollToChild( currentPosition, 0 );
|
||||
}
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
private void addTextTab( final int position, String title ) {
|
||||
|
||||
TextView tab = new TextView( getContext() );
|
||||
tab.setText( title );
|
||||
tab.setGravity( Gravity.CENTER );
|
||||
tab.setSingleLine();
|
||||
tab.setPadding( WindowUtils.dip2px( getContext(), 10 ),
|
||||
WindowUtils.dip2px( getContext(), 3 ),
|
||||
WindowUtils.dip2px( getContext(), 10 ),
|
||||
WindowUtils.dip2px( getContext(), 3 ) );
|
||||
|
||||
LinearLayout linearLayout = new LinearLayout( getContext() );
|
||||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT );
|
||||
linearLayout.addView( tab, layoutParams );
|
||||
linearLayout.setGravity( Gravity.CENTER );
|
||||
addTab( position, linearLayout );
|
||||
}
|
||||
|
||||
private void addIconTab( final int position, int resId ) {
|
||||
|
||||
ImageButton tab = new ImageButton( getContext() );
|
||||
tab.setImageResource( resId );
|
||||
|
||||
addTab( position, tab );
|
||||
|
||||
}
|
||||
|
||||
private void addViewTab( final int position, View v ) {
|
||||
addTab( position, v );
|
||||
}
|
||||
|
||||
public void setCurrentTab( final int position ) {
|
||||
pager.post( new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
pager.setCurrentItem( position, false );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
private void addTab( final int position, View tab ) {
|
||||
tab.setFocusable( true );
|
||||
tab.setOnClickListener( new OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View v ) {
|
||||
if ( getOnBeforeTabAction() != null ) {
|
||||
if ( getOnBeforeTabAction().doAction( position ) ) {
|
||||
pager.setCurrentItem( position, false );
|
||||
}
|
||||
} else {
|
||||
pager.setCurrentItem( position, false );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
if ( openPadding ) {
|
||||
tab.setPadding( position == 0 ? 0 : tabPadding, 0, tabPadding, 0 );
|
||||
}
|
||||
|
||||
tabsContainer.addView( tab, position, shouldExpand ? expandedTabLayoutParams : defaultTabLayoutParams );
|
||||
}
|
||||
|
||||
private void updateTabStyles() {
|
||||
|
||||
for ( int i = 0; i < tabCount; i++ ) {
|
||||
|
||||
View v = tabsContainer.getChildAt( i );
|
||||
|
||||
if ( v instanceof SelectedState ) {
|
||||
( ( SelectedState ) v ).setSelectedState( i == selectedPosition );
|
||||
} else if ( v instanceof LinearLayout ) {
|
||||
|
||||
TextView tab = ( TextView ) ( ( LinearLayout ) v ).getChildAt( 0 );
|
||||
tab.setTextSize( TypedValue.COMPLEX_UNIT_PX, tabTextSize );
|
||||
tab.setTypeface( tabTypeface, tabTypefaceStyle );
|
||||
tab.setTextColor( tabTextColor );
|
||||
|
||||
if ( textAllCaps ) {
|
||||
tab.setAllCaps( true );
|
||||
}
|
||||
|
||||
if ( i == selectedPosition ) {
|
||||
tab.setTextColor( selectedTabTextColor );
|
||||
if ( indicatorMode == INDICATOR_MODE_SHADOW ) {
|
||||
tab.setBackgroundResource( R.drawable.module_apps_shape_deep_blue );
|
||||
}
|
||||
} else {
|
||||
tab.setTextColor( tabTextColor );
|
||||
tab.setBackgroundResource( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void scrollToChild( int position, int offset ) {
|
||||
|
||||
if ( tabCount == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
int newScrollX = tabsContainer.getChildAt( position ).getLeft() + offset;
|
||||
|
||||
if ( position > 0 || offset > 0 ) {
|
||||
newScrollX -= scrollOffset;
|
||||
}
|
||||
|
||||
if ( newScrollX != lastScrollX ) {
|
||||
lastScrollX = newScrollX;
|
||||
scrollTo( newScrollX, 0 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw( Canvas canvas ) {
|
||||
super.onDraw( canvas );
|
||||
|
||||
if ( isInEditMode() || tabCount == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int height = getHeight();
|
||||
|
||||
|
||||
// draw indicator line
|
||||
|
||||
rectPaint.setColor( indicatorColor );
|
||||
|
||||
// default: line below current tab
|
||||
View currentTab = tabsContainer.getChildAt( currentPosition );
|
||||
float lineLeft = currentTab.getLeft();
|
||||
float lineRight = currentTab.getRight();
|
||||
|
||||
// if there is an offset, start interpolating left and right coordinates between current and next tab
|
||||
if ( currentPositionOffset > 0f && currentPosition < tabCount - 1 ) {
|
||||
|
||||
View nextTab = tabsContainer.getChildAt( currentPosition + 1 );
|
||||
final float nextTabLeft = nextTab.getLeft();
|
||||
final float nextTabRight = nextTab.getRight();
|
||||
|
||||
lineLeft = ( currentPositionOffset * nextTabLeft + ( 1f - currentPositionOffset ) * lineLeft );
|
||||
lineRight = ( currentPositionOffset * nextTabRight + ( 1f - currentPositionOffset ) * lineRight );
|
||||
}
|
||||
|
||||
if ( indicatorMode == INDICATOR_MODE_UNDERLINE ) {
|
||||
float lineOffset = getLineOffset();
|
||||
float left, right, top, bottom;
|
||||
if ( indicatorFitMode == INDICATOR_FIT_MODE_AUTO ) {
|
||||
left = lineLeft + lineOffset + indicatorMarginLeft;
|
||||
right = lineRight - lineOffset - indicatorMarginRight;
|
||||
top = height - indicatorHeight - indicatorMarginBottom;
|
||||
bottom = height - indicatorMarginBottom;
|
||||
} else {
|
||||
left = lineLeft + lineOffset;
|
||||
right = lineRight - lineOffset;
|
||||
top = height - indicatorHeight - indicatorMarginBottom;
|
||||
bottom = height - indicatorMarginBottom;
|
||||
}
|
||||
|
||||
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ) {
|
||||
canvas.drawRoundRect( left, top, right, bottom, 90, 90, rectPaint );
|
||||
} else {
|
||||
canvas.drawRect( left, top, right, bottom, rectPaint );
|
||||
}
|
||||
}
|
||||
|
||||
if ( indicatorMode == INDICATOR_MODE_RES ) {
|
||||
if ( indicatorRes != null ) {
|
||||
int lineOffset = ( int ) getLineOffset();
|
||||
int left, right, top, bottom;
|
||||
int width = indicatorRes.getIntrinsicWidth();
|
||||
left = ( int ) lineLeft + lineOffset;
|
||||
right = ( int ) lineRight - lineOffset;
|
||||
top = height - indicatorRes.getIntrinsicHeight() - indicatorMarginBottom;
|
||||
left = left + ( right - left - width ) / 2;
|
||||
right = left + width;
|
||||
bottom = height - indicatorMarginBottom;
|
||||
indicatorRes.setBounds( left, top, right, bottom );
|
||||
indicatorRes.draw( canvas );
|
||||
}
|
||||
}
|
||||
|
||||
// draw underline
|
||||
|
||||
rectPaint.setColor( underlineColor );
|
||||
canvas.drawRect( 0, height - underlineHeight, tabsContainer.getWidth(), height, rectPaint );
|
||||
|
||||
// draw divider
|
||||
|
||||
dividerPaint.setColor( dividerColor );
|
||||
for ( int i = 0; i < tabCount - 1; i++ ) {
|
||||
View tab = tabsContainer.getChildAt( i );
|
||||
canvas.drawLine( tab.getRight(), dividerPadding, tab.getRight(), height - dividerPadding, dividerPaint );
|
||||
}
|
||||
}
|
||||
|
||||
private float indicatorLineOffset = -1;
|
||||
|
||||
private float getLineOffset() {
|
||||
|
||||
if ( tabsContainer.getChildCount() == 0 ) {
|
||||
return 0;
|
||||
}
|
||||
if ( !shouldExpand ) {
|
||||
return 0;
|
||||
}
|
||||
if ( indicatorLineOffset != -1 ) {
|
||||
return indicatorLineOffset;
|
||||
}
|
||||
|
||||
float minViewMeasuredWidth = tabsContainer.getChildAt( 0 ).getMeasuredWidth();
|
||||
float minContentWidth = getTabContentWidth( tabsContainer.getChildAt( 0 ) );
|
||||
for ( int i = 1; i < tabsContainer.getChildCount(); i++ ) {
|
||||
float nextContentWidth = getTabContentWidth( tabsContainer.getChildAt( i ) );
|
||||
if ( minContentWidth > nextContentWidth ) {
|
||||
minContentWidth = nextContentWidth;
|
||||
}
|
||||
}
|
||||
float offset = ( minViewMeasuredWidth - minContentWidth ) / 2;
|
||||
return indicatorLineOffset = offset == 0 ? WindowUtils.dip2px( getContext(), 25 ) : offset;
|
||||
}
|
||||
|
||||
private float getTabContentWidth( View tab ) {
|
||||
if ( tab instanceof TextView ) {
|
||||
TextPaint paint = ( ( TextView ) tab ).getPaint();
|
||||
return paint.measureText( ( ( TextView ) tab ).getText().toString() );
|
||||
}
|
||||
return tab.getMeasuredWidth();
|
||||
}
|
||||
|
||||
private class PageListener implements ViewPager.OnPageChangeListener {
|
||||
|
||||
@Override
|
||||
public void onPageScrolled( int position, float positionOffset, int positionOffsetPixels ) {
|
||||
|
||||
currentPosition = position;
|
||||
currentPositionOffset = positionOffset;
|
||||
|
||||
scrollToChild( position, ( int ) ( positionOffset * tabsContainer.getChildAt( position ).getWidth() ) );
|
||||
|
||||
invalidate();
|
||||
|
||||
if ( delegatePageListener != null ) {
|
||||
delegatePageListener.onPageScrolled( position, positionOffset, positionOffsetPixels );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged( int state ) {
|
||||
if ( state == ViewPager.SCROLL_STATE_IDLE ) {
|
||||
scrollToChild( pager.getCurrentItem(), 0 );
|
||||
}
|
||||
|
||||
if ( delegatePageListener != null ) {
|
||||
delegatePageListener.onPageScrollStateChanged( state );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected( int position ) {
|
||||
selectedPosition = position;
|
||||
updateTabStyles();
|
||||
if ( delegatePageListener != null ) {
|
||||
delegatePageListener.onPageSelected( position );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setIndicatorColor( int indicatorColor ) {
|
||||
this.indicatorColor = indicatorColor;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setIndicatorColorResource( int resId ) {
|
||||
this.indicatorColor = getResources().getColor( resId );
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public int getIndicatorColor() {
|
||||
return this.indicatorColor;
|
||||
}
|
||||
|
||||
public void setIndicatorHeight( int indicatorLineHeightPx ) {
|
||||
this.indicatorHeight = indicatorLineHeightPx;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public int getIndicatorHeight() {
|
||||
return indicatorHeight;
|
||||
}
|
||||
|
||||
public void setUnderlineColor( int underlineColor ) {
|
||||
this.underlineColor = underlineColor;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setUnderlineColorResource( int resId ) {
|
||||
this.underlineColor = getResources().getColor( resId );
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public int getUnderlineColor() {
|
||||
return underlineColor;
|
||||
}
|
||||
|
||||
public void setDividerColor( int dividerColor ) {
|
||||
this.dividerColor = dividerColor;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setDividerColorResource( int resId ) {
|
||||
this.dividerColor = getResources().getColor( resId );
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public int getDividerColor() {
|
||||
return dividerColor;
|
||||
}
|
||||
|
||||
public void setUnderlineHeight( int underlineHeightPx ) {
|
||||
this.underlineHeight = underlineHeightPx;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public int getUnderlineHeight() {
|
||||
return underlineHeight;
|
||||
}
|
||||
|
||||
public void setDividerPadding( int dividerPaddingPx ) {
|
||||
this.dividerPadding = dividerPaddingPx;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public int getDividerPadding() {
|
||||
return dividerPadding;
|
||||
}
|
||||
|
||||
public void setScrollOffset( int scrollOffsetPx ) {
|
||||
this.scrollOffset = scrollOffsetPx;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public int getScrollOffset() {
|
||||
return scrollOffset;
|
||||
}
|
||||
|
||||
public void setShouldExpand( boolean shouldExpand ) {
|
||||
this.shouldExpand = shouldExpand;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public boolean getShouldExpand() {
|
||||
return shouldExpand;
|
||||
}
|
||||
|
||||
public boolean isTextAllCaps() {
|
||||
return textAllCaps;
|
||||
}
|
||||
|
||||
public void setAllCaps( boolean textAllCaps ) {
|
||||
this.textAllCaps = textAllCaps;
|
||||
}
|
||||
|
||||
public void setTextSize( int textSizePx ) {
|
||||
this.tabTextSize = textSizePx;
|
||||
updateTabStyles();
|
||||
}
|
||||
|
||||
public int getTextSize() {
|
||||
return tabTextSize;
|
||||
}
|
||||
|
||||
public void setTextColor( int textColor ) {
|
||||
this.tabTextColor = textColor;
|
||||
updateTabStyles();
|
||||
}
|
||||
|
||||
public void setTextColorResource( int resId ) {
|
||||
this.tabTextColor = getResources().getColor( resId );
|
||||
updateTabStyles();
|
||||
}
|
||||
|
||||
public int getTextColor() {
|
||||
return tabTextColor;
|
||||
}
|
||||
|
||||
public void setSelectedTextColor( int textColor ) {
|
||||
this.selectedTabTextColor = textColor;
|
||||
updateTabStyles();
|
||||
}
|
||||
|
||||
public void setSelectedTextColorResource( int resId ) {
|
||||
this.selectedTabTextColor = getResources().getColor( resId );
|
||||
updateTabStyles();
|
||||
}
|
||||
|
||||
public int getSelectedTextColor() {
|
||||
return selectedTabTextColor;
|
||||
}
|
||||
|
||||
public void setTypeface( Typeface typeface, int style ) {
|
||||
this.tabTypeface = typeface;
|
||||
this.tabTypefaceStyle = style;
|
||||
updateTabStyles();
|
||||
}
|
||||
|
||||
public void setTabBackground( int resId ) {
|
||||
this.tabBackgroundResId = resId;
|
||||
updateTabStyles();
|
||||
}
|
||||
|
||||
public int getTabBackground() {
|
||||
return tabBackgroundResId;
|
||||
}
|
||||
|
||||
public void setTabPaddingLeftRight( int paddingPx ) {
|
||||
this.tabPadding = paddingPx;
|
||||
updateTabStyles();
|
||||
}
|
||||
|
||||
public int getTabPaddingLeftRight() {
|
||||
return tabPadding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreInstanceState( Parcelable state ) {
|
||||
SavedState savedState = ( SavedState ) state;
|
||||
super.onRestoreInstanceState( savedState.getSuperState() );
|
||||
currentPosition = savedState.currentPosition;
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parcelable onSaveInstanceState() {
|
||||
Parcelable superState = super.onSaveInstanceState();
|
||||
SavedState savedState = new SavedState( superState );
|
||||
savedState.currentPosition = currentPosition;
|
||||
return savedState;
|
||||
}
|
||||
|
||||
static class SavedState extends BaseSavedState {
|
||||
int currentPosition;
|
||||
|
||||
public SavedState( Parcelable superState ) {
|
||||
super( superState );
|
||||
}
|
||||
|
||||
private SavedState( Parcel in ) {
|
||||
super( in );
|
||||
currentPosition = in.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel( Parcel dest, int flags ) {
|
||||
super.writeToParcel( dest, flags );
|
||||
dest.writeInt( currentPosition );
|
||||
}
|
||||
|
||||
public static final Creator< SavedState > CREATOR = new Creator< SavedState >() {
|
||||
@Override
|
||||
public SavedState createFromParcel( Parcel in ) {
|
||||
return new SavedState( in );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavedState[] newArray( int size ) {
|
||||
return new SavedState[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_selected="false">
|
||||
<shape android:shape="rectangle">
|
||||
|
||||
<!-- 填充的颜色 -->
|
||||
<solid android:color="#4DFFFFFF" />
|
||||
<!-- 设置矩形的四个角为弧形 -->
|
||||
<!-- android:radius 弧形的半径 -->
|
||||
<corners android:radius="90px" />
|
||||
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_selected="true">
|
||||
<shape android:shape="rectangle">
|
||||
|
||||
<!-- 填充的颜色 -->
|
||||
<solid android:color="#FFFFFF" />
|
||||
<!-- 设置矩形的四个角为弧形 -->
|
||||
<!-- android:radius 弧形的半径 -->
|
||||
<corners android:radius="90px" />
|
||||
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="@android:integer/config_shortAnimTime">
|
||||
|
||||
<item android:state_pressed="true" android:drawable="@android:color/transparent" />
|
||||
<item android:state_focused="true" android:drawable="@android:color/transparent"/>
|
||||
<item android:drawable="@android:color/transparent"/>
|
||||
|
||||
</selector>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle" >
|
||||
|
||||
<!-- 填充的颜色 -->
|
||||
<solid android:color="#409EEA" />
|
||||
<!-- 设置矩形的四个角为弧形 -->
|
||||
<!-- android:radius 弧形的半径 -->
|
||||
<corners android:radius="18dp" />
|
||||
|
||||
</shape>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<View
|
||||
android:id="@+id/module_apps_id_indicator_dot"
|
||||
android:layout_width="@dimen/module_apps_indicator_width"
|
||||
android:background="@drawable/module_apps_pager_indicator"
|
||||
android:layout_height="@dimen/module_apps_indicator_height" />
|
||||
</LinearLayout>
|
||||
@@ -41,16 +41,13 @@
|
||||
android:layout_marginTop="@dimen/module_apps_pager_marginTop"
|
||||
android:overScrollMode="never" />
|
||||
|
||||
<com.mogo.module.apps.view.LinePageIndicator
|
||||
<com.mogo.module.apps.view.PagerSlidingTabStripV2
|
||||
android:id="@+id/module_apps_id_indicator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dp_2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:layout_marginBottom="@dimen/module_apps_indicator_marginBottom"
|
||||
app:lineWidth="@dimen/module_apps_indicator_width"
|
||||
app:selectedColor="#ffffffff"
|
||||
app:strokeWidth="@dimen/module_apps_indicator_height"
|
||||
app:unselectedColor="#33ffffff" />
|
||||
app:pstsV2TabPaddingLeftRight="@dimen/module_apps_indicator_interval" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/module_apps_id_loading"
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<ImageView
|
||||
android:id="@+id/module_apps_id_app_icon"
|
||||
android:layout_width="@dimen/module_apps_navigation_icon_width"
|
||||
android:scaleType="fitXY"
|
||||
android:layout_height="@dimen/module_apps_navigation_icon_height" />
|
||||
|
||||
<TextView
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<dimen name="module_apps_pager_marginTop">117px</dimen>
|
||||
<dimen name="module_apps_indicator_height">2.7px</dimen>
|
||||
<dimen name="module_apps_indicator_width">16px</dimen>
|
||||
<dimen name="module_apps_indicator_interval">2.3px</dimen>
|
||||
<dimen name="module_apps_indicator_marginBottom">54.9px</dimen>
|
||||
<dimen name="module_apps_navigation_icon_width">64px</dimen>
|
||||
<dimen name="module_apps_navigation_icon_height">64px</dimen>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<dimen name="module_apps_pager_marginTop">260px</dimen>
|
||||
<dimen name="module_apps_indicator_height">5px</dimen>
|
||||
<dimen name="module_apps_indicator_width">30px</dimen>
|
||||
<dimen name="module_apps_indicator_interval">4px</dimen>
|
||||
<dimen name="module_apps_indicator_marginBottom">103px</dimen>
|
||||
<dimen name="module_apps_navigation_icon_width">120px</dimen>
|
||||
<dimen name="module_apps_navigation_icon_height">120px</dimen>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<dimen name="module_apps_pager_marginTop">260px</dimen>
|
||||
<dimen name="module_apps_indicator_height">5px</dimen>
|
||||
<dimen name="module_apps_indicator_width">30px</dimen>
|
||||
<dimen name="module_apps_indicator_interval">2.3px</dimen>
|
||||
<dimen name="module_apps_indicator_marginBottom">103px</dimen>
|
||||
<dimen name="module_apps_navigation_icon_width">120px</dimen>
|
||||
<dimen name="module_apps_navigation_icon_height">120px</dimen>
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="LinePageIndicator">
|
||||
<!-- Whether or not the indicators should be centered. -->
|
||||
<attr name="centered" />
|
||||
<!-- Color of the unselected lines that represent the pages. -->
|
||||
<attr name="unselectedColor" />
|
||||
<!-- Color of the selected line that represents the current page. -->
|
||||
<attr name="selectedColor" />
|
||||
<!-- Width of each indicator line. -->
|
||||
<attr name="lineWidth" format="dimension" />
|
||||
<!-- Width of each indicator line's stroke. -->
|
||||
<attr name="strokeWidth" />
|
||||
<!-- Width of the gap between each indicator line. -->
|
||||
<attr name="gapWidth" format="dimension" />
|
||||
<!-- View background -->
|
||||
<attr name="android:background" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="card_common_margin_left">@dimen/dp_15</dimen>
|
||||
<dimen name="default_line_indicator_line_width">12dp</dimen>
|
||||
<dimen name="default_line_indicator_gap_width">4dp</dimen>
|
||||
<dimen name="default_line_indicator_stroke_width">1dp</dimen>
|
||||
<color name="default_line_indicator_selected_color">#FF33B5E5</color>
|
||||
<color name="default_line_indicator_unselected_color">#FFBBBBBB</color>
|
||||
<bool name="default_line_indicator_centered">true</bool>
|
||||
|
||||
<declare-styleable name="ViewPagerIndicator">
|
||||
<!-- Style of the circle indicator. -->
|
||||
<attr name="vpiCirclePageIndicatorStyle" format="reference" />
|
||||
<!-- Style of the icon indicator's views. -->
|
||||
<attr name="vpiIconPageIndicatorStyle" format="reference" />
|
||||
<!-- Style of the line indicator. -->
|
||||
<attr name="vpiLinePageIndicatorStyle" format="reference" />
|
||||
<!-- Style of the title indicator. -->
|
||||
<attr name="vpiTitlePageIndicatorStyle" format="reference" />
|
||||
<!-- Style of the tab indicator's tabs. -->
|
||||
<attr name="vpiTabPageIndicatorStyle" format="reference" />
|
||||
<!-- Style of the underline indicator. -->
|
||||
<attr name="vpiUnderlinePageIndicatorStyle" format="reference" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="PagerSlidingTabStripV2">
|
||||
<attr name="pstsV2IndicatorColor" format="color" />
|
||||
<attr name="pstsV2UnderlineColor" format="color" />
|
||||
<attr name="pstsV2DividerColor" format="color" />
|
||||
<attr name="pstsV2IndicatorHeight" format="dimension" />
|
||||
<attr name="pstsV2UnderlineHeight" format="dimension" />
|
||||
<attr name="pstsV2DividerPadding" format="dimension" />
|
||||
<attr name="pstsV2TabPaddingLeftRight" format="dimension" />
|
||||
<attr name="pstsV2ScrollOffset" format="dimension" />
|
||||
<attr name="pstsV2TabBackground" format="reference" />
|
||||
<attr name="pstsV2ShouldExpand" format="boolean" />
|
||||
<attr name="pstsV2TextAllCaps" format="boolean" />
|
||||
<attr name="pstsV2SelectedTabTextColor" format="color" />
|
||||
<attr name="pstsV2TabTextColorValue" format="color" />
|
||||
<attr name="pstsV2IndicatorMarginBottom" format="dimension" />
|
||||
<attr name="pstsV2IndicatorMarginLeft" format="dimension" />
|
||||
<attr name="pstsV2IndicatorMarginRight" format="dimension" />
|
||||
<attr name="pstsV2IndicatorMode" format="enum">
|
||||
<enum name="underline" value="-1" />
|
||||
<enum name="shadow" value="1" />
|
||||
<enum name="res" value="2" />
|
||||
</attr>
|
||||
<attr name="pstsV2IndicatorRes" format="reference" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
@@ -37,14 +37,9 @@ android {
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||
implementation 'androidx.core:core-ktx:1.0.2'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
implementation rootProject.ext.dependencies.kotlinstdlibjdk7
|
||||
implementation rootProject.ext.dependencies.androidxappcompat
|
||||
implementation rootProject.ext.dependencies.androidxccorektx
|
||||
implementation rootProject.ext.dependencies.androidxconstraintlayout
|
||||
implementation rootProject.ext.dependencies.arouter
|
||||
annotationProcessor rootProject.ext.dependencies.aroutercompiler
|
||||
|
||||
@@ -14,64 +14,77 @@ public class MarkerUserInfo implements Serializable {
|
||||
private String userName;//用户昵称
|
||||
private String userHead;//用户头像
|
||||
private String gender;//gender": "男|女|无(也可以0|1|2根据实际库存返回即可)
|
||||
private int age;// 年龄段,可以为空,与车聊聊一致
|
||||
private Integer age;// 年龄段,可以为空,与车聊聊一致
|
||||
|
||||
public void setAge(int age) {
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public int getAgeNumber() {
|
||||
return age;
|
||||
if (age != null) {
|
||||
return age;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public String getAge() {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
int year = cal.get(Calendar.YEAR);
|
||||
try {
|
||||
if (getAgeNumber() >= 0) {
|
||||
|
||||
//2020-30=1990
|
||||
double ageDiffer = year - age;
|
||||
String ageStr = "" + ageDiffer;
|
||||
char[] ageChars = ageStr.toCharArray();
|
||||
Calendar cal = Calendar.getInstance();
|
||||
int year = cal.get(Calendar.YEAR);
|
||||
|
||||
//1990
|
||||
char ageChar = ageChars[2];
|
||||
//2020-30=1990
|
||||
double ageDiffer = year - getAgeNumber();
|
||||
String ageStr = "" + ageDiffer;
|
||||
char[] ageChars = ageStr.toCharArray();
|
||||
|
||||
String ageString = "未设置";
|
||||
//1990
|
||||
char ageChar = ageChars[2];
|
||||
|
||||
switch (ageChar) {
|
||||
case '0':
|
||||
ageString = "00后";
|
||||
break;
|
||||
case '1':
|
||||
ageString = "10后";
|
||||
break;
|
||||
case '2':
|
||||
ageString = "20后";
|
||||
break;
|
||||
case '3':
|
||||
ageString = "30后";
|
||||
break;
|
||||
case '4':
|
||||
ageString = "40后";
|
||||
break;
|
||||
case '5':
|
||||
ageString = "50后";
|
||||
break;
|
||||
case '6':
|
||||
ageString = "60后";
|
||||
break;
|
||||
case '7':
|
||||
ageString = "70后";
|
||||
break;
|
||||
case '8':
|
||||
ageString = "80后";
|
||||
break;
|
||||
case '9':
|
||||
ageString = "90后";
|
||||
break;
|
||||
String ageString = "未设置";
|
||||
|
||||
switch (ageChar) {
|
||||
case '0':
|
||||
ageString = "00后";
|
||||
break;
|
||||
case '1':
|
||||
ageString = "10后";
|
||||
break;
|
||||
case '2':
|
||||
ageString = "20后";
|
||||
break;
|
||||
case '3':
|
||||
ageString = "30后";
|
||||
break;
|
||||
case '4':
|
||||
ageString = "40后";
|
||||
break;
|
||||
case '5':
|
||||
ageString = "50后";
|
||||
break;
|
||||
case '6':
|
||||
ageString = "60后";
|
||||
break;
|
||||
case '7':
|
||||
ageString = "70后";
|
||||
break;
|
||||
case '8':
|
||||
ageString = "80后";
|
||||
break;
|
||||
case '9':
|
||||
ageString = "90后";
|
||||
break;
|
||||
}
|
||||
|
||||
return ageString;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
|
||||
return ageString;
|
||||
}
|
||||
|
||||
public int getGenderValue() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.mogo.module.extensions;
|
||||
|
||||
import android.graphics.drawable.AnimationDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
@@ -18,6 +19,7 @@ import com.mogo.service.MogoServicePaths;
|
||||
import com.mogo.service.analytics.IMogoAnalytics;
|
||||
import com.mogo.service.fragmentmanager.IMogoFragmentManager;
|
||||
import com.mogo.utils.UiThreadHandler;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
@@ -27,8 +29,11 @@ import com.mogo.utils.UiThreadHandler;
|
||||
*/
|
||||
public class ExtensionsFragment extends MvpFragment< ExtensionsView, ExtensionsPresenter > implements ExtensionsView {
|
||||
|
||||
private JSurfaceView mVoiceIcon;
|
||||
private View mVoiceMsg;
|
||||
private static final String TAG = "ExtensionsFragment";
|
||||
|
||||
private ImageView mVoiceIcon;
|
||||
private AnimationDrawable mAnim;
|
||||
private TextView mVoiceMsg;
|
||||
|
||||
private TextView mTime;
|
||||
private TextView mDate;
|
||||
@@ -52,6 +57,7 @@ public class ExtensionsFragment extends MvpFragment< ExtensionsView, ExtensionsP
|
||||
@Override
|
||||
protected void initViews() {
|
||||
mVoiceIcon = findViewById( R.id.module_ext_id_voice );
|
||||
mAnim = ( AnimationDrawable ) mVoiceIcon.getBackground();
|
||||
mVoiceMsg = findViewById( R.id.module_ext_id_voice_msg );
|
||||
|
||||
mVoiceIcon.setOnClickListener( view -> {
|
||||
@@ -76,7 +82,7 @@ public class ExtensionsFragment extends MvpFragment< ExtensionsView, ExtensionsP
|
||||
} );
|
||||
mMsgCounter = findViewById( R.id.module_ext_id_msg_counter );
|
||||
|
||||
mVoiceIcon.setFrames( AnimRes.sRes );
|
||||
// mVoiceIcon.setFrames( AnimRes.sRes );
|
||||
|
||||
mMogoFragmentManager = ( IMogoFragmentManager ) ARouter.getInstance().build( MogoServicePaths.PATH_FRAGMENT_MANAGER ).navigation( getContext() );
|
||||
mMogoFragmentManager.addMainFragmentStackTransactionListener( size -> {
|
||||
@@ -98,19 +104,22 @@ public class ExtensionsFragment extends MvpFragment< ExtensionsView, ExtensionsP
|
||||
public void onActivityCreated( @Nullable Bundle savedInstanceState ) {
|
||||
super.onActivityCreated( savedInstanceState );
|
||||
mAnalytics = ( IMogoAnalytics ) ARouter.getInstance().build( MogoServicePaths.PATH_UTILS_ANALYTICS ).navigation( getContext() );
|
||||
mVoiceIcon.startAnim();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mVoiceIcon.startAnim();
|
||||
if ( mAnim != null ) {
|
||||
mAnim.start();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
mVoiceIcon.stop();
|
||||
if ( mAnim != null ) {
|
||||
mAnim.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -141,4 +150,12 @@ public class ExtensionsFragment extends MvpFragment< ExtensionsView, ExtensionsP
|
||||
mMsgContainer.setVisibility( hasMsg ? View.VISIBLE : View.GONE );
|
||||
mMsgCounter.setText( amount > 99 ? getString( R.string.module_ext_str_dots ) : String.valueOf( amount ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderAITipWords( String word ) {
|
||||
if ( !TextUtils.isEmpty( word ) ) {
|
||||
Logger.d( TAG, "current word: %s", word );
|
||||
mVoiceMsg.setText( word );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
@@ -19,7 +22,16 @@ import com.mogo.service.statusmanager.IMogoMsgCenter;
|
||||
import com.mogo.service.statusmanager.IMogoMsgCenterListener;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
@@ -36,6 +48,31 @@ public class ExtensionsPresenter extends Presenter< ExtensionsView > implements
|
||||
|
||||
private WeatherModel mWeatherModel;
|
||||
|
||||
public static final int MSG_SWITCH_AI_TIP_WORDS = 4000;
|
||||
public static final long INTERVAL_TIME = 8_000L;
|
||||
private String[] mAITipWords;
|
||||
private int mCurrentIndex = 0;
|
||||
private Handler mHandler = new Handler( Looper.getMainLooper() ) {
|
||||
@Override
|
||||
public void handleMessage( Message msg ) {
|
||||
super.handleMessage( msg );
|
||||
if ( msg.what == MSG_SWITCH_AI_TIP_WORDS ) {
|
||||
if ( mView != null ) {
|
||||
if ( mCurrentIndex < mAITipWords.length ) {
|
||||
mView.renderAITipWords( mAITipWords[mCurrentIndex++] );
|
||||
} else {
|
||||
mCurrentIndex = 0;
|
||||
mHasTipWords = generateTipWordsSequence();
|
||||
}
|
||||
}
|
||||
if ( mHasTipWords ) {
|
||||
mHandler.sendEmptyMessageDelayed( MSG_SWITCH_AI_TIP_WORDS, INTERVAL_TIME );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
private boolean mHasTipWords = false;
|
||||
|
||||
/**
|
||||
* 接收时间变化的广播
|
||||
*/
|
||||
@@ -52,10 +89,30 @@ public class ExtensionsPresenter extends Presenter< ExtensionsView > implements
|
||||
|
||||
private IMogoMsgCenter mMsgCenter;
|
||||
|
||||
private boolean generateTipWordsSequence() {
|
||||
if ( mAITipWords != null && mAITipWords.length > 0 ) {
|
||||
Random random = new Random( System.currentTimeMillis() );
|
||||
int loop = mAITipWords.length / 2;
|
||||
int bound = mAITipWords.length;
|
||||
for ( int i = 0; i < loop; i++ ) {
|
||||
int target = random.nextInt( bound );
|
||||
int sweepTarget = random.nextInt( bound );
|
||||
if ( target != sweepTarget ) {
|
||||
String targetStr = mAITipWords[target];
|
||||
mAITipWords[target] = mAITipWords[sweepTarget];
|
||||
mAITipWords[sweepTarget] = targetStr;
|
||||
}
|
||||
}
|
||||
Logger.d( TAG, "next generate sequence: " + mAITipWords );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ExtensionsPresenter( ExtensionsView view ) {
|
||||
super( view );
|
||||
mWeeks = getContext().getResources().getStringArray( R.array.module_ext_str_arr_week );
|
||||
mAITipWords = getContext().getResources().getStringArray( R.array.module_ext_str_arr_ai_tips );
|
||||
mWeatherModel = new WeatherModel( getContext() );
|
||||
}
|
||||
|
||||
@@ -68,6 +125,7 @@ public class ExtensionsPresenter extends Presenter< ExtensionsView > implements
|
||||
refreshTimeAndDate();
|
||||
mMsgCenter = ( IMogoMsgCenter ) ARouter.getInstance().build( MogoServicePaths.PATH_MSG_CENTER ).navigation();
|
||||
mMsgCenter.registerMsgCenterListener( this );
|
||||
mHasTipWords = generateTipWordsSequence();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,6 +173,22 @@ public class ExtensionsPresenter extends Presenter< ExtensionsView > implements
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume( @NonNull LifecycleOwner owner ) {
|
||||
super.onResume( owner );
|
||||
if ( mHasTipWords ) {
|
||||
mHandler.sendEmptyMessageDelayed( MSG_SWITCH_AI_TIP_WORDS, INTERVAL_TIME );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause( @NonNull LifecycleOwner owner ) {
|
||||
super.onPause( owner );
|
||||
if ( mHasTipWords ) {
|
||||
mHandler.removeMessages( MSG_SWITCH_AI_TIP_WORDS );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy( @NonNull LifecycleOwner owner ) {
|
||||
super.onDestroy( owner );
|
||||
|
||||
@@ -35,4 +35,11 @@ public interface ExtensionsView extends IView {
|
||||
* @param amount 消息数量
|
||||
*/
|
||||
void renderMsgInfo( boolean hasMsg, int amount );
|
||||
|
||||
/**
|
||||
* 更换小智语音提示词
|
||||
*
|
||||
* @param word
|
||||
*/
|
||||
void renderAITipWords( String word );
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ public class JSurfaceView extends SurfaceView implements Runnable, SurfaceHolder
|
||||
*/
|
||||
private int[] mFrames;
|
||||
|
||||
private Thread mThread;
|
||||
|
||||
// 使用 BitmapFactory.Option.inBitmap 属性复用 bitmap 对象
|
||||
private Bitmap mContainerBitmap = null;
|
||||
|
||||
@@ -78,12 +80,20 @@ public class JSurfaceView extends SurfaceView implements Runnable, SurfaceHolder
|
||||
if ( bRunning ) {
|
||||
return;
|
||||
}
|
||||
ThreadPoolService.execute( this );
|
||||
bRunning = true;
|
||||
mThread = new Thread( this );
|
||||
mThread.setName( TAG + "thread" );
|
||||
mThread.start();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
bRunning = false;
|
||||
try {
|
||||
mThread.interrupt();
|
||||
mThread = null;
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
|
Before Width: | Height: | Size: 403 B After Width: | Height: | Size: 442 B |
|
Before Width: | Height: | Size: 402 B After Width: | Height: | Size: 465 B |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |