Merge remote-tracking branch 'origin/feature/v1.0.0' into feature/v1.0.0

# Conflicts:
#	config.gradle
This commit is contained in:
zhangyuanzhen
2019-12-31 16:21:25 +08:00
139 changed files with 7626 additions and 607 deletions

1
modules/mogo-module-apps/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,59 @@
apply plugin: 'com.android.library'
apply plugin: 'com.alibaba.arouter'
android {
compileSdkVersion rootProject.ext.android.compileSdkVersion
buildToolsVersion rootProject.ext.android.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
versionCode Integer.valueOf(VERSION_CODE)
versionName getValueFromRootProperties("${project.name.replace("-", "_").toUpperCase()}_VERSION")
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation rootProject.ext.dependencies.androidxappcompat
implementation rootProject.ext.dependencies.androidxconstraintlayout
implementation rootProject.ext.dependencies.arouter
implementation rootProject.ext.dependencies.material
annotationProcessor rootProject.ext.dependencies.aroutercompiler
implementation rootProject.ext.dependencies.androidxrecyclerview
if (Boolean.valueOf(RELEASE)) {
implementation rootProject.ext.dependencies.mogomap
implementation rootProject.ext.dependencies.mogomapapi
implementation rootProject.ext.dependencies.mogoutils
api rootProject.ext.dependencies.mogocommons
api rootProject.ext.dependencies.mogoserviceapi
implementation rootProject.ext.dependencies.modulecommon
} else {
implementation project(":libraries:mogo-map")
implementation project(":libraries:mogo-map-api")
implementation project(":foudations:mogo-utils")
api project(":foudations:mogo-commons")
api project(':services:mogo-service-api')
implementation project(':modules:mogo-module-common')
}
}
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()

View File

@@ -0,0 +1,3 @@
GROUP=com.mogo.module
POM_ARTIFACT_ID=module-apps
VERSION_CODE=1

View 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 mName 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 mName.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,27 @@
package com.mogo.mogo.module.apps;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith( AndroidJUnit4.class )
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals( "com.mogo.mogo.module.apps.test", appContext.getPackageName() );
}
}

View File

@@ -0,0 +1,26 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mogo.module.apps">
<application>
<receiver
android:name=".receiver.AppInstallReceiver"
android:label="@string/app_name">
<intent-filter>
<!-- 一个新应用包已经安装在设备上,数据包括包名(最新安装的包程序不能接收到这个广播)-->
<action android:name="android.intent.action.PACKAGE_ADDED" />
<!-- 一个新版本的应用安装到设备,替换之前已经存在的版本-->
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<!-- 一个已存在的应用程序包已经从设备上移除,包括包名(正在被安装的包程序不能接收到这个广播)-->
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<!-- 一个已存在的应用程序包已经改变,包括包名-->
<action android:name="android.intent.action.ACTION_PACKAGE_CHANGED" />
<!-- 用户重新开始一个包,包的所有进程将被杀死,所有与其联系的运行时间状态应该被移除,包括包名(重新开始包程序不能接收到这个广播-->
<action android:name="android.intent.action.ACTION_PACKAGE_RESTARTED" />
<!-- 用户已经清楚一个包的数据,包括包名(清除包程序不能接收到这个广播)-->
<action android:name="android.intent.action.ACTION_PACKAGE_DATA_CLEARED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -0,0 +1,64 @@
package com.mogo.module.apps;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.mogo.module.apps.model.AppInfo;
import java.util.List;
/**
* @author congtaowang
* @since 2019-12-30
* <p>
* 描述
*/
public class AppsAdapter extends RecyclerView.Adapter< AppsAdapter.AppsViewHolder > {
private List< AppInfo > mAppInfos;
public AppsAdapter( List< AppInfo > appInfos ) {
this.mAppInfos = appInfos;
}
public void refreshAppInfos( List< AppInfo > mAppInfos ) {
this.mAppInfos = mAppInfos;
notifyDataSetChanged();
}
@NonNull
@Override
public AppsViewHolder onCreateViewHolder( @NonNull ViewGroup parent, int viewType ) {
return new AppsViewHolder( LayoutInflater.from( parent.getContext() ).inflate( R.layout.module_apps_item_app, null ) );
}
@Override
public void onBindViewHolder( @NonNull AppsViewHolder holder, int position ) {
final AppInfo appInfo = mAppInfos.get( position );
holder.mIcon.setImageDrawable( appInfo.getIcon() );
holder.mName.setText( appInfo.getName() );
}
@Override
public int getItemCount() {
return mAppInfos == null ? 0 : mAppInfos.size();
}
public static class AppsViewHolder extends RecyclerView.ViewHolder {
public ImageView mIcon;
public TextView mName;
public AppsViewHolder( @NonNull View itemView ) {
super( itemView );
mIcon = itemView.findViewById( R.id.module_apps_id_app_icon );
mName = itemView.findViewById( R.id.module_apps_id_app_name );
}
}
}

View File

@@ -0,0 +1,76 @@
package com.mogo.module.apps;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.mogo.commons.mvp.MvpFragment;
import com.mogo.module.apps.model.AppInfo;
import java.util.List;
/**
* @author congtaowang
* @since 2019-12-30
* <p>
* 描述
*/
public class AppsFragment extends MvpFragment< AppsView, AppsPresenter > implements AppsView {
private BottomSheetBehavior mBottomSheetBehavior;
private RecyclerView mAppsList;
private AppsAdapter mAppsAdapter;
@Override
protected int getLayoutId() {
return R.layout.module_apps_fragment_apps;
}
@Override
protected void initViews() {
mAppsList = findViewById( R.id.module_apps_id_apps );
mAppsList.setLayoutManager( new GridLayoutManager( getContext(), 3 ) );
mBottomSheetBehavior = BottomSheetBehavior.from( mAppsList );
mBottomSheetBehavior.setSkipCollapsed( true );
mBottomSheetBehavior.setBottomSheetCallback( new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged( @NonNull View bottomSheet, int newState ) {
}
@Override
public void onSlide( @NonNull View bottomSheet, float slideOffset ) {
}
} );
mBottomSheetBehavior.setState( BottomSheetBehavior.STATE_COLLAPSED );
}
@NonNull
@Override
protected AppsPresenter createPresenter() {
return new AppsPresenter( this );
}
@Override
public void onActivityCreated( @Nullable Bundle savedInstanceState ) {
super.onActivityCreated( savedInstanceState );
}
@Override
public void renderApps( List< AppInfo > appInfos ) {
if ( mAppsAdapter == null ) {
mAppsAdapter = new AppsAdapter( appInfos );
mAppsList.setAdapter( mAppsAdapter );
} else {
mAppsAdapter.refreshAppInfos( appInfos );
}
}
}

View File

@@ -0,0 +1,77 @@
package com.mogo.module.apps;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.mogo.map.listener.IMogoMapListener;
import com.mogo.map.location.IMogoLocationListener;
import com.mogo.map.navi.IMogoNaviListener;
import com.mogo.module.common.MogoModulePaths;
import com.mogo.service.module.IMogoModuleLifecycle;
import com.mogo.service.module.IMogoModuleProvider;
/**
* @author congtaowang
* @since 2019-12-30
* <p>
* 描述
*/
@Route( path = MogoModulePaths.PATH_MODULE_APPS )
public class AppsFragmentProvider implements IMogoModuleProvider {
private AppsFragment mAppsFragment;
@Override
public Fragment createFragment( Context context, Bundle data ) {
mAppsFragment = new AppsFragment();
mAppsFragment.setArguments( data );
return mAppsFragment;
}
@Override
public View createView( Context context ) {
return null;
}
@NonNull
@Override
public String getModuleName() {
return MogoModulePaths.PATH_MODULE_APPS;
}
@Override
public IMogoModuleLifecycle getCardLifecycle() {
return null;
}
@Override
public IMogoMapListener getMapListener() {
return null;
}
@Override
public int getType() {
return IMogoModuleProvider.TYPE_FRAGMENT;
}
@Override
public IMogoNaviListener getNaviListener() {
return null;
}
@Override
public IMogoLocationListener getLocationListener() {
return null;
}
@Override
public void init( Context context ) {
}
}

View File

@@ -0,0 +1,86 @@
package com.mogo.module.apps;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.Observer;
import com.mogo.commons.mvp.Presenter;
import com.mogo.module.apps.model.AppInfo;
import com.mogo.utils.ThreadPoolService;
import com.mogo.utils.UiThreadHandler;
import com.mogo.utils.logger.Logger;
import java.util.ArrayList;
import java.util.List;
/**
* @author congtaowang
* @since 2019-12-30
* <p>
* 描述
*/
public class AppsPresenter extends Presenter< AppsView > {
private static final String TAG = "AppsPresenter";
public AppsPresenter( AppsView view ) {
super( view );
RefreshAppsListLiveData.getInstance().observeForever( new Observer< String >() {
@Override
public void onChanged( String s ) {
renderAppsList();
}
} );
}
@Override
public void onCreate( @NonNull LifecycleOwner owner ) {
super.onCreate( owner );
renderAppsList();
}
private void renderAppsList() {
ThreadPoolService.execute( new Runnable() {
@Override
public void run() {
final List< AppInfo > appInfoList = loadAppsList();
UiThreadHandler.post( new Runnable() {
@Override
public void run() {
if ( mView != null ) {
mView.renderApps( appInfoList );
}
}
} );
}
} );
}
private List< AppInfo > loadAppsList() {
Logger.i( TAG, "load apps list." );
final List< AppInfo > appInfos = new ArrayList<>();
final PackageManager packageManager = getContext().getPackageManager();
List< PackageInfo > packages = packageManager.getInstalledPackages( 0 );
for ( int i = 0; i < packages.size(); ++i ) {
PackageInfo packageInfo = packages.get( i );
//获取非系统应用
if ( ( packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM ) == 0 ) {
String appName = packageInfo.applicationInfo.loadLabel( packageManager ).toString();
String packageName = packageInfo.packageName;
String versionName = packageInfo.versionName;
int versionCode = packageInfo.versionCode;
Drawable appIcon = packageInfo.applicationInfo.loadIcon( packageManager );
AppInfo appInfo = new AppInfo( appName, packageName, versionName, versionCode, appIcon );
appInfos.add( appInfo );
}
}
return appInfos;
}
}

View File

@@ -0,0 +1,22 @@
package com.mogo.module.apps;
import com.mogo.commons.mvp.IView;
import com.mogo.module.apps.model.AppInfo;
import java.util.List;
/**
* @author congtaowang
* @since 2019-12-30
* <p>
* 描述
*/
public interface AppsView extends IView {
/**
* 显示加载的app列表
*
* @param appInfos
*/
void renderApps( List< AppInfo > appInfos );
}

View File

@@ -0,0 +1,32 @@
package com.mogo.module.apps;
import androidx.lifecycle.MutableLiveData;
/**
* @author congtaowang
* @since 2019-12-30
* <p>
* 刷新app列表
*/
public class RefreshAppsListLiveData extends MutableLiveData< String > {
private static volatile RefreshAppsListLiveData sInstance;
private RefreshAppsListLiveData() {
}
public static RefreshAppsListLiveData getInstance() {
if ( sInstance == null ) {
synchronized ( RefreshAppsListLiveData.class ) {
if ( sInstance == null ) {
sInstance = new RefreshAppsListLiveData();
}
}
}
return sInstance;
}
public synchronized void release() {
sInstance = null;
}
}

View File

@@ -0,0 +1,46 @@
package com.mogo.module.apps.model;
import android.graphics.drawable.Drawable;
/**
* @author congtaowang
* @since 2019-12-30
* <p>
* app 信息
*/
public class AppInfo {
private final String mName;
private final String mPackageName;
private final String mVersionName;
private final int mVersionCode;
private final Drawable mIcon;
public AppInfo( String name, String mPackageName, String mVersionName, int versionCode, Drawable icon ) {
this.mName = name;
this.mPackageName = mPackageName;
this.mVersionName = mVersionName;
this.mVersionCode = versionCode;
this.mIcon = icon;
}
public String getName() {
return mName;
}
public String getPackageName() {
return mPackageName;
}
public String getVersionName() {
return mVersionName;
}
public int getVersionCode() {
return mVersionCode;
}
public Drawable getIcon() {
return mIcon;
}
}

View File

@@ -0,0 +1,42 @@
package com.mogo.module.apps.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
public class AppInstallReceiver extends BroadcastReceiver {
@Override
public void onReceive( Context context, Intent intent ) {
if ( intent.getAction().equals( Intent.ACTION_PACKAGE_ADDED ) ) {
String packageName = intent.getData().getSchemeSpecificPart();
notifyRefreshAppsList( packageName );
}
if ( intent.getAction().equals( Intent.ACTION_PACKAGE_REMOVED ) ) {
String packageName = intent.getData().getSchemeSpecificPart();
notifyRefreshAppsList( packageName );
}
if ( intent.getAction().equals( Intent.ACTION_PACKAGE_REPLACED ) ) {
String packageName = intent.getData().getSchemeSpecificPart();
notifyRefreshAppsList( packageName );
}
if ( intent.getAction().equals( Intent.ACTION_PACKAGE_CHANGED ) ) {
String packageName = intent.getData().getSchemeSpecificPart();
notifyRefreshAppsList( packageName );
}
if ( intent.getAction().equals( Intent.ACTION_PACKAGE_RESTARTED ) ) {
String packageName = intent.getData().getSchemeSpecificPart();
notifyRefreshAppsList( packageName );
}
if ( intent.getAction().equals( Intent.ACTION_PACKAGE_DATA_CLEARED ) ) {
String packageName = intent.getData().getSchemeSpecificPart();
notifyRefreshAppsList( packageName );
}
}
private void notifyRefreshAppsList( String packageName ) {
}
}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/module_apps_id_apps"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:behavior_hideable="false"
app:behavior_peekHeight="50dp"
app:layout_behavior="@string/bottom_sheet_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/module_apps_id_app_icon"
android:layout_width="75dp"
android:layout_height="75dp" />
<TextView
android:id="@+id/module_apps_id_app_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">mogo-module-apps</string>
</resources>

View File

@@ -0,0 +1,17 @@
package com.mogo.mogo.module.apps;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals( 4, 2 + 2 );
}
}

View File

@@ -1,15 +1,13 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
compileSdkVersion rootProject.ext.android.compileSdkVersion
buildToolsVersion rootProject.ext.android.buildToolsVersion
defaultConfig {
minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
versionCode Integer.valueOf(VERSION_CODE)
versionName getValueFromRootProperties("${project.name.replace("-", "_").toUpperCase()}_VERSION")
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
@@ -27,8 +25,11 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation rootProject.ext.dependencies.androidxappcompat
if (Boolean.valueOf(RELEASE)) {
} else {
}
}
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()

View File

@@ -0,0 +1,3 @@
GROUP=com.mogo.module
POM_ARTIFACT_ID=module-common
VERSION_CODE=1

View File

@@ -1,5 +1,13 @@
package com.mogo.module.common;
import android.text.TextUtils;
import androidx.annotation.Keep;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
/**
* @author congtaowang
* @since 2019-12-23
@@ -8,13 +16,27 @@ package com.mogo.module.common;
*/
public class MogoModulePaths {
private static List< String > mModulesPath = new ArrayList<>();
/**
* 地图模块 fragment 路径
*/
public static final String PATH_MODULE_MAP = "/module/map";
public static final String PATH_MODULE_MAP = "/map/ui";
/**
* 测试模块
* app列表模块实例化路径
*/
public static final String PATH_MODULE_DEMO = "/demo/module/demo";
@Keep
public static final String PATH_MODULE_APPS = "/appslist/ui";
public static void addModule( String path ) {
if ( TextUtils.isEmpty( path.replace( " ", "" ) ) ) {
throw new IllegalArgumentException( "module path can't be empty or null or blank" );
}
mModulesPath.add( path );
}
public static List< String > getModulesPath() {
return mModulesPath;
}
}

View File

@@ -1,15 +1,13 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
compileSdkVersion rootProject.ext.android.compileSdkVersion
buildToolsVersion rootProject.ext.android.buildToolsVersion
defaultConfig {
minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
versionCode Integer.valueOf(VERSION_CODE)
versionName getValueFromRootProperties("${project.name.replace("-", "_").toUpperCase()}_VERSION")
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
@@ -33,15 +31,27 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(":foudations:mogo-utils")
implementation project(":foudations:mogo-commons")
implementation project(':modules:mogo-module-common')
implementation project(':modules:mogo-module-map')
implementation project(':services:mogo-service-api')
implementation project(':services:mogo-service')
implementation project(':demo:demo-module-map')
implementation rootProject.ext.dependencies.androidxappcompat
implementation rootProject.ext.dependencies.androidxconstraintlayout
implementation rootProject.ext.dependencies.arouter
annotationProcessor rootProject.ext.dependencies.aroutercompiler
if (Boolean.valueOf(RELEASE)) {
implementation rootProject.ext.dependencies.mogoutils
implementation rootProject.ext.dependencies.mogocommons
implementation rootProject.ext.dependencies.modulecommon
implementation rootProject.ext.dependencies.modulemap
implementation rootProject.ext.dependencies.mogoserviceapi
implementation rootProject.ext.dependencies.mogoservice
implementation rootProject.ext.dependencies.moduleapps
} else {
implementation project(":foudations:mogo-utils")
implementation project(":foudations:mogo-commons")
implementation project(':modules:mogo-module-common')
implementation project(':modules:mogo-module-map')
implementation project(':services:mogo-service-api')
implementation project(':services:mogo-service')
implementation project(':modules:mogo-module-apps')
}
}
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()

View File

@@ -0,0 +1,3 @@
GROUP=com.mogo.module
POM_ARTIFACT_ID=module-main
VERSION_CODE=1

View File

@@ -1,17 +1,30 @@
package com.mogo.module.main;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.annotation.Nullable;
import androidx.viewpager.widget.ViewPager;
import com.alibaba.android.arouter.launcher.ARouter;
import com.mogo.commons.mvp.MvpActivity;
import com.mogo.map.location.IMogoLocationClient;
import com.mogo.map.location.IMogoLocationListener;
import com.mogo.map.location.MogoLocation;
import com.mogo.map.marker.IMogoMarker;
import com.mogo.map.marker.IMogoMarkerClickListener;
import com.mogo.module.main.cards.CardModulesAdapter;
import com.mogo.module.main.cards.MogoModulesHandler;
import com.mogo.module.main.cards.MogoModulesManager;
import com.mogo.module.main.cards.OrientedViewPager;
import com.mogo.module.main.cards.VerticalStackTransformer;
import com.mogo.service.MogoServicePaths;
import com.mogo.service.map.IMogoMapService;
import com.mogo.service.module.IMogoModuleProvider;
import com.mogo.utils.logger.Logger;
import java.util.Collection;
import java.util.List;
/**
* @author congtaowang
@@ -19,10 +32,24 @@ import java.util.Collection;
* <p>
* 描述
*/
public class MainActivity extends MvpActivity< MainView, MainPresenter > implements MainView {
public class MainActivity extends MvpActivity< MainView, MainPresenter > implements MainView,
IMogoLocationListener,
IMogoMarkerClickListener {
IMogoMapService mMogoMapService;
MogoModulesHandler mMogoModuleHandler;
private static final String TAG = "MainActivity";
private IMogoMapService mMogoMapService;
private MogoModulesHandler mMogoModuleHandler;
private OrientedViewPager mCardsContainer;
private CardModulesAdapter mCardModulesAdapter;
/**
* 主模块管控定位,可以向各个模块发送统一定位信息
*/
private IMogoLocationClient mLocationClient;
private int mCurrentPosition = 1;
@Override
protected int getLayoutId() {
@@ -31,35 +58,129 @@ public class MainActivity extends MvpActivity< MainView, MainPresenter > impleme
@Override
protected void initViews() {
mCardsContainer = findViewById( R.id.module_main_id_cards_container );
mCardsContainer.setOrientation( OrientedViewPager.Orientation.VERTICAL );
mMogoModuleHandler = new MogoModulesManager( this );
mMogoMapService = ( IMogoMapService ) ARouter.getInstance().build( MogoServicePaths.PATH_SERVICES_MAP ).navigation();
if ( mMogoMapService != null ) {
mMogoMapService.registerHostMapListener( mMogoModuleHandler );
mMogoMapService.registerHostNaviListener( mMogoModuleHandler );
}
mMogoModuleHandler.loadMap( R.id.module_main_id_map_fragment_container );
mCardsContainer.setOnPageChangeListener( new ViewPager.OnPageChangeListener() {
Collection< IMogoModuleProvider > providers = mMogoModuleHandler.loadCards();
for ( IMogoModuleProvider provider : providers ) {
if ( provider == null ) {
continue;
}
if ( provider.getType() == IMogoModuleProvider.TYPE_FRAGMENT ) {
final Fragment fragment = provider.createFragment( this, null );
if ( fragment != null ) {
getSupportFragmentManager().beginTransaction()
.add( R.id.module_main_id_fragment_container, fragment )
.commitAllowingStateLoss();
private int mLastPosition = -1;
@Override
public void onPageScrolled( int position, float positionOffset, int positionOffsetPixels ) {
Logger.i( TAG, "position = " + position );
if ( mLastPosition != position ) {
if ( mCardModulesAdapter != null ) {
mCardModulesAdapter.render( position );
}
mLastPosition = position;
}
}
}
mMogoModuleHandler.setEnable( providers.iterator().next().getModuleName() );
@Override
public void onPageSelected( int position ) {
try {
mCurrentPosition = position;
mMogoModuleHandler.setEnable( mCardModulesAdapter.getProvider( position ).getModuleName() );
} catch ( Exception e ) {
e.printStackTrace();
}
}
@Override
public void onPageScrollStateChanged( int state ) {
if ( state == ViewPager.SCROLL_STATE_IDLE ) {
if ( mCurrentPosition == 0 ) {
mCurrentPosition = mCardModulesAdapter.getCount() - 3;
mCardsContainer.setCurrentItem( mCurrentPosition, false );
} else if ( mCurrentPosition == mCardModulesAdapter.getCount() - 2 ) {
mCurrentPosition = 1;
mCardsContainer.setCurrentItem( mCurrentPosition, false );
}
}
}
} );
}
public int getCurrentPosition() {
return mCurrentPosition;
}
public OrientedViewPager getCardsContainer() {
return mCardsContainer;
}
@Override
protected void onCreate( @Nullable Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
mMogoModuleHandler = new MogoModulesManager( this );
mMogoModuleHandler.onMapLoadedCallback( new Runnable() {
@Override
public void run() {
Logger.d( TAG, "map loaded." + Thread.currentThread().getName() );
loadModules();
}
} );
mMogoMapService = ( IMogoMapService ) ARouter.getInstance().build( MogoServicePaths.PATH_SERVICES_MAP ).navigation();
if ( mMogoMapService != null ) {
mMogoMapService.getHostListenerRegister().registerHostMapListener( mMogoModuleHandler );
mMogoMapService.getHostListenerRegister().registerHostNaviListener( mMogoModuleHandler );
mMogoMapService.getHostListenerRegister().registerMarkerClickListener( this );
}
// 加载地图,触发地图加载完毕回调,在初始化其他卡片模块,保证卡片模块可以正确获取地图相关服务。
mMogoModuleHandler.loadMap( R.id.module_main_id_map_fragment_container );
mLocationClient = mMogoMapService.getSingletonLocationClient( getApplicationContext() );
mLocationClient.addLocationListener( this );
mLocationClient.start();
mMogoModuleHandler.loadAppsList( R.id.module_main_id_fragment_container );
}
private void loadModules() {
List< IMogoModuleProvider > providers = mMogoModuleHandler.loadCards();
mCardModulesAdapter = new CardModulesAdapter( this, providers );
mCardsContainer.setOffscreenPageLimit( providers.size() + 2 );
mCardsContainer.setPageTransformer( true, new VerticalStackTransformer( this ) );
mCardsContainer.setAdapter( mCardModulesAdapter );
mCardsContainer.setCurrentItem( mCurrentPosition );
}
@NonNull
@Override
protected MainPresenter createPresenter() {
return new MainPresenter( this );
}
@Override
public void onLocationChanged( MogoLocation location ) {
if ( mMogoModuleHandler != null ) {
mMogoModuleHandler.onLocationChanged( location );
}
}
@Override
public boolean onMarkerClicked( IMogoMarker marker ) {
// int mappedCardPosition = mCardModulesAdapter.getNextCardPosition( marker.getOwner(), mCurrentPosition );
// mCardsContainer.setCurrentItem( mappedCardPosition, true );
return false;
}
@Override
protected void onDestroy() {
super.onDestroy();
if ( mLocationClient != null ) {
mLocationClient.removeLocationListener( this );
mLocationClient.destroy();
}
mLocationClient = null;
mMogoMapService = null;
if ( mMogoModuleHandler != null ) {
mMogoModuleHandler.destroy();
mMogoModuleHandler = null;
}
}
}

View File

@@ -0,0 +1,128 @@
package com.mogo.module.main.cards;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentStatePagerAdapter;
import com.mogo.module.main.MainActivity;
import com.mogo.service.module.IMogoModuleProvider;
import com.mogo.utils.logger.Logger;
import java.util.ArrayList;
import java.util.List;
/**
* @author congtaowang
* @since 2019-12-30
* <p>
* 描述
*/
public class CardModulesAdapter extends FragmentStatePagerAdapter {
private static final String TAG = "CardModulesAdapter";
private final MainActivity mActivity;
private List< IMogoModuleProvider > mProviders;
private PlaceholderFragmentProvider mLastPH;
private PlaceholderFragmentProvider mFirstPH;
private PlaceholderFragmentProvider mPH;
public CardModulesAdapter( @NonNull MainActivity fragmentActivity, List< IMogoModuleProvider > providers ) {
super( fragmentActivity.getSupportFragmentManager() );
mActivity = fragmentActivity;
this.mProviders = new ArrayList<>( providers );
this.mProviders.add( 0, mLastPH = new PlaceholderFragmentProvider() );
this.mProviders.add( mFirstPH = new PlaceholderFragmentProvider() );
this.mProviders.add( mPH = new PlaceholderFragmentProvider() );
}
@NonNull
@Override
public Fragment getItem( int position ) {
int factPosition = getFactPosition( position );
Bundle bundle = new Bundle();
bundle.putInt( "position", factPosition );
Logger.d( TAG, "here" );
final Fragment f = mProviders.get( factPosition ).createFragment( mActivity, bundle );
if ( position == 0 ) {
mLastPH.setCopyTarget( f );
} else if ( position == getCount() - 2 ) {
mFirstPH.setCopyTarget( f );
}
return f;
}
@Override
public int getCount() {
return mProviders.size();
// return Integer.MAX_VALUE;
}
public IMogoModuleProvider getProvider( int position ) {
return mProviders.get( getFactPosition( position ) );
}
public int getFactPosition( int position ) {
return position % mProviders.size();
}
@Override
public int getItemPosition( Object object ) {
return POSITION_NONE;
}
/**
* marker、卡片、语音等通过 launcher 切换到其他卡片。
*
* @param providerTag 卡片类型
* @param currentPosition 当前卡片位置
* @return 需要跳转到的卡片实际位置
*/
public int getNextCardPosition( String providerTag, int currentPosition ) {
int position = 0;
int currentFactPosition = getFactPosition( currentPosition );
for ( IMogoModuleProvider provider : mProviders ) {
if ( TextUtils.equals( providerTag, provider.getModuleName() ) ) {
break;
}
position++;
}
int offset = 0;
if ( currentFactPosition > position ) {
// 下一个卡片在当前卡片前面
offset = position - mProviders.size();
} else if ( currentFactPosition < position ) {
// 下一个卡片在当前卡片后面
offset = mProviders.size() - position;
}
return currentPosition + offset;
}
@Override
public void destroyItem( @NonNull ViewGroup container, int position, @NonNull Object object ) {
// super.destroyItem( container, position, object );
// Logger.d( TAG, "destroy " + object );
}
@Override
public void finishUpdate( @NonNull ViewGroup container ) {
super.finishUpdate( container );
}
public void render( int position ) {
if ( position == 1 ) {
mLastPH.renderTargetUI();
} else if ( position == getCount() - 2 ) {
mFirstPH.renderTargetUI();
}
}
}

View File

@@ -1,10 +1,16 @@
package com.mogo.module.main.cards;
import com.mogo.map.listener.IMogoMapListener;
import com.mogo.map.location.IMogoLocationClient;
import com.mogo.map.location.IMogoLocationListener;
import com.mogo.map.marker.IMogoMarkerClickListener;
import com.mogo.map.navi.IMogoNaviListener;
import com.mogo.service.module.IMogoModuleProvider;
import java.util.Collection;
import java.util.List;
import javax.security.auth.callback.Callback;
/**
* @author congtaowang
@@ -12,14 +18,18 @@ import java.util.Collection;
* <p>
* 卡片管理
*/
public interface MogoModulesHandler extends IMogoMapListener, IMogoNaviListener {
public interface MogoModulesHandler extends IMogoMapListener,
IMogoNaviListener,
IMogoLocationListener {
void onMapLoadedCallback( Runnable callback );
/**
* 加载卡片
*
* @return
*/
Collection< IMogoModuleProvider > loadCards();
List< IMogoModuleProvider > loadCards();
/**
* 加载小智语音
@@ -42,10 +52,22 @@ public interface MogoModulesHandler extends IMogoMapListener, IMogoNaviListener
*/
void loadMap( int containerId );
/**
* 加载所有应用
*
* @param containerId 容器id
*/
void loadAppsList( int containerId );
/**
* 设置某一个module可用
*
* @param module
*/
void setEnable( String module );
/**
* 销毁
*/
void destroy();
}

View File

@@ -9,18 +9,22 @@ import androidx.fragment.app.Fragment;
import com.alibaba.android.arouter.launcher.ARouter;
import com.mogo.map.MogoLatLng;
import com.mogo.map.listener.IMogoMapListener;
import com.mogo.map.location.IMogoLocationListener;
import com.mogo.map.location.MogoLocation;
import com.mogo.map.model.MogoPoi;
import com.mogo.map.navi.IMogoNaviListener;
import com.mogo.map.navi.MogoNaviInfo;
import com.mogo.map.uicontroller.EnumMapUI;
import com.mogo.module.common.MogoModulePaths;
import com.mogo.module.main.MainActivity;
import com.mogo.service.module.IMogoModuleLifecycle;
import com.mogo.service.module.IMogoModuleProvider;
import com.mogo.utils.ResourcesHelper;
import com.mogo.utils.logger.Logger;
import java.util.Collection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -31,14 +35,18 @@ import java.util.Set;
* 卡片加载
*/
public class MogoModulesManager implements MogoModulesHandler,
IMogoMapListener, IMogoNaviListener {
IMogoMapListener,
IMogoNaviListener,
IMogoLocationListener {
private static final String TAG = "MogoModulesManager";
private MainActivity mActivity;
private final Map< String, IMogoModuleProvider > mCardProviders = new HashMap<>();
private IMogoModuleProvider mMapProvider;
private IMogoModuleProvider mAppsListProvider;
private String mEnableModuleName = null;
private Runnable mMapLoadedCallback;
public MogoModulesManager( MainActivity activity ) {
if ( activity == null ) {
@@ -56,10 +64,22 @@ public class MogoModulesManager implements MogoModulesHandler,
}
@Override
public Collection< IMogoModuleProvider > loadCards() {
IMogoModuleProvider demo = load( MogoModulePaths.PATH_MODULE_DEMO );
mCardProviders.put( demo.getModuleName(), demo );
return mCardProviders.values();
public void onMapLoadedCallback( Runnable callback ) {
mMapLoadedCallback = callback;
}
@Override
public List< IMogoModuleProvider > loadCards() {
final List< String > modulePaths = MogoModulePaths.getModulesPath();
final ArrayList< IMogoModuleProvider > providers = new ArrayList<>();
if ( modulePaths != null && !modulePaths.isEmpty() ) {
for ( String modulePath : modulePaths ) {
IMogoModuleProvider provider = load( modulePath );
providers.add( provider );
mCardProviders.put( provider.getModuleName(), provider );
}
}
return providers;
}
@Override
@@ -82,6 +102,12 @@ public class MogoModulesManager implements MogoModulesHandler,
addFragment( mMapProvider, containerId );
}
@Override
public void loadAppsList( int containerId ) {
mAppsListProvider = load( MogoModulePaths.PATH_MODULE_APPS );
addFragment( mAppsListProvider, containerId );
}
private IMogoModuleProvider load( String path ) {
return ( IMogoModuleProvider ) ARouter.getInstance().build( path ).navigation( getContext() );
}
@@ -109,20 +135,30 @@ public class MogoModulesManager implements MogoModulesHandler,
for ( Map.Entry< String, IMogoModuleProvider > entry : entries ) {
final String key = entry.getKey();
final IMogoModuleProvider provider = entry.getValue();
if ( TextUtils.equals( key, module ) ) {
provider.getCardLifecycle().onPerform();
} else {
provider.getCardLifecycle().onDisable();
final IMogoModuleLifecycle lifecycle = provider.getCardLifecycle();
if ( lifecycle != null ) {
if ( TextUtils.equals( key, mEnableModuleName ) ) {
lifecycle.onPerform();
} else {
lifecycle.onDisable();
}
}
}
}
}
@Override
public void onMapLoaded() {
if ( mMapLoadedCallback != null ) {
mMapLoadedCallback.run();
mMapLoadedCallback = null;
}
if ( mEnableModuleName != null ) {
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
if ( provider != null ) {
if ( provider != null && provider.getMapListener() != null ) {
provider.getMapListener().onMapLoaded();
}
}
@@ -132,7 +168,7 @@ public class MogoModulesManager implements MogoModulesHandler,
public void onTouch( MotionEvent motionEvent ) {
if ( mEnableModuleName != null ) {
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
if ( provider != null ) {
if ( provider != null && provider.getMapListener() != null ) {
provider.getMapListener().onTouch( motionEvent );
}
}
@@ -142,7 +178,7 @@ public class MogoModulesManager implements MogoModulesHandler,
public void onPOIClick( MogoPoi poi ) {
if ( mEnableModuleName != null ) {
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
if ( provider != null ) {
if ( provider != null && provider.getMapListener() != null ) {
provider.getMapListener().onPOIClick( poi );
}
}
@@ -152,7 +188,7 @@ public class MogoModulesManager implements MogoModulesHandler,
public void onMapClick( MogoLatLng latLng ) {
if ( mEnableModuleName != null ) {
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
if ( provider != null ) {
if ( provider != null && provider.getMapListener() != null ) {
provider.getMapListener().onMapClick( latLng );
}
}
@@ -162,7 +198,7 @@ public class MogoModulesManager implements MogoModulesHandler,
public void onLockMap( boolean isLock ) {
if ( mEnableModuleName != null ) {
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
if ( provider != null ) {
if ( provider != null && provider.getMapListener() != null ) {
provider.getMapListener().onLockMap( isLock );
}
}
@@ -172,7 +208,7 @@ public class MogoModulesManager implements MogoModulesHandler,
public void onMapModeChanged( EnumMapUI ui ) {
if ( mEnableModuleName != null ) {
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
if ( provider != null ) {
if ( provider != null && provider.getMapListener() != null ) {
provider.getMapListener().onMapModeChanged( ui );
}
}
@@ -229,4 +265,19 @@ public class MogoModulesManager implements MogoModulesHandler,
}
}
}
@Override
public void onLocationChanged( MogoLocation location ) {
if ( mEnableModuleName != null ) {
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
if ( provider != null && provider.getLocationListener() != null ) {
provider.getLocationListener().onLocationChanged( location );
}
}
}
@Override
public void destroy() {
}
}

View File

@@ -0,0 +1,26 @@
package com.mogo.module.main.cards;
import android.os.Bundle;
import androidx.annotation.Nullable;
import com.mogo.module.main.R;
/**
* @author congtaowang
* @since 2019-12-31
* <p>
* 描述
*/
public class PlaceholderFragment extends UnDestroyedViewFragment {
@Override
protected int getLayoutId() {
return R.layout.module_main_fragement_placeholder;
}
@Override
public void onCreate( @Nullable Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
}
}

View File

@@ -0,0 +1,100 @@
package com.mogo.module.main.cards;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.mogo.commons.mvp.IView;
import com.mogo.commons.mvp.MvpFragment;
import com.mogo.commons.mvp.Presenter;
import com.mogo.map.listener.IMogoMapListener;
import com.mogo.map.location.IMogoLocationListener;
import com.mogo.map.navi.IMogoNaviListener;
import com.mogo.module.main.R;
import com.mogo.service.module.IMogoModuleLifecycle;
import com.mogo.service.module.IMogoModuleProvider;
/**
* @author congtaowang
* @since 2019-12-31
* <p>
* 描述
*/
public class PlaceholderFragmentProvider implements IMogoModuleProvider {
private Fragment mCopyTarget;
private PlaceholderFragment mUi;
public void setCopyTarget( Fragment mUICopyTarget ) {
this.mCopyTarget = mUICopyTarget;
}
public void renderTargetUI() {
if ( mCopyTarget == null ) {
return;
}
final View target = mCopyTarget.getView();
if ( target == null ) {
return;
}
target.setDrawingCacheEnabled( true );
Bitmap result = target.getDrawingCache();
result = target.getDrawingCache() != null ? result.copy( Bitmap.Config.ARGB_8888, false ) : null;
if ( mUi.getView() != null ) {
mUi.getView().setBackgroundDrawable( new BitmapDrawable( result ) );
}
}
@Override
public Fragment createFragment( Context context, Bundle data ) {
mUi = new PlaceholderFragment();
return mUi;
}
@Override
public View createView( Context context ) {
return null;
}
@NonNull
@Override
public String getModuleName() {
return "placeholder";
}
@Override
public IMogoModuleLifecycle getCardLifecycle() {
return null;
}
@Override
public IMogoMapListener getMapListener() {
return null;
}
@Override
public int getType() {
return TYPE_FRAGMENT;
}
@Override
public IMogoNaviListener getNaviListener() {
return null;
}
@Override
public IMogoLocationListener getLocationListener() {
return null;
}
@Override
public void init( Context context ) {
}
}

View File

@@ -0,0 +1,44 @@
package com.mogo.module.main.cards;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mogo.commons.mvp.IView;
import com.mogo.commons.mvp.MvpFragment;
import com.mogo.commons.mvp.Presenter;
import com.mogo.module.main.R;
/**
* @author congtaowang
* @since 2019-12-31
* <p>
* 描述
*/
public abstract class UnDestroyedViewFragment extends MvpFragment< IView, Presenter< IView > > implements IView {
@Nullable
@Override
public View onCreateView( @NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState ) {
if ( mRootView == null ) {
return super.onCreateView( inflater, container, savedInstanceState );
}
return mRootView;
}
@Override
protected void initViews() {
}
@NonNull
@Override
protected Presenter< IView > createPresenter() {
return new Presenter< IView >( this ) {
};
}
}

View File

@@ -0,0 +1,108 @@
package com.mogo.module.main.cards;
import android.view.View;
import androidx.viewpager.widget.ViewPager;
public abstract class VerticalBaseTransformer implements ViewPager.PageTransformer {
/**
* Called each {@link #transformPage(View, float)}.
*
* @param page Apply the transformation to this page
* @param position Position of page relative to the current front-and-center position of the pager. 0 is front and
* center. 1 is one full page position to the right, and -1 is one page position to the left.
*/
protected abstract void onTransform( View page, float position );
/**
* Apply a property transformation to the given page. For most use cases, this method should not be overridden.
* Instead use {@link #transformPage(View, float)} to perform typical transformations.
*
* @param page Apply the transformation to this page
* @param position Position of page relative to the current front-and-center position of the pager. 0 is front and
* center. 1 is one full page position to the right, and -1 is one page position to the left.
*/
@Override
public void transformPage( View page, float position ) {
onPreTransform( page, position );
onTransform( page, position );
onPostTransform( page, position );
}
/**
* If the position offset of a fragment is less than negative one or greater than one, returning true will set the
* fragment alpha to 0f. Otherwise fragment alpha is always defaulted to 1f.
*
* @return
*/
protected boolean hideOffscreenPages() {
return true;
}
/**
* Indicates if the default animations of the view pager should be used.
*
* @return
*/
protected boolean isPagingEnabled() {
return false;
}
/**
* Called each {@link #transformPage(View, float)} before {{@link #onTransform(View, float)}.
* <p/>
* The default implementation attempts to reset all view properties. This is useful when toggling transforms that do
* not modify the same page properties. For instance changing from a transformation that applies rotation to a
* transformation that fades can inadvertently leave a fragment stuck with a rotation or with some degree of applied
* alpha.
*
* @param page Apply the transformation to this page
* @param position Position of page relative to the current front-and-center position of the pager. 0 is front and
* center. 1 is one full page position to the right, and -1 is one page position to the left.
*/
protected void onPreTransform( View page, float position ) {
final float width = page.getWidth();
final float height = page.getHeight();
page.setRotationX( 0 );
page.setRotationY( 0 );
page.setRotation( 0 );
page.setScaleX( 1 );
page.setScaleY( 1 );
page.setPivotX( 0 );
page.setPivotY( 0 );
page.setTranslationX( 0 );
page.setTranslationY( isPagingEnabled() ? 0f : -height * position );
if ( hideOffscreenPages() ) {
page.setAlpha( position <= -1f || position >= 1f ? 0f : 1f );
} else {
page.setAlpha( 1f );
}
/*final float normalizedposition = Math.abs(Math.abs(position) - 1);
page.setAlpha(normalizedposition);*/
}
/**
* Called each {@link #transformPage(View, float)} after {@link #onTransform(View, float)}.
*
* @param page Apply the transformation to this page
* @param position Position of page relative to the current front-and-center position of the pager. 0 is front and
* center. 1 is one full page position to the right, and -1 is one page position to the left.
*/
protected void onPostTransform( View page, float position ) {
}
/**
* Same as {@link Math#min(double, double)} without double casting, zero closest to infinity handling, or NaN support.
*
* @param val
* @param min
* @return
*/
protected static final float min( float val, float min ) {
return val < min ? min : val;
}
}

View File

@@ -0,0 +1,45 @@
package com.mogo.module.main.cards;
import android.content.Context;
import android.util.Log;
import android.view.View;
import com.mogo.utils.WindowUtils;
public class VerticalStackTransformer extends VerticalBaseTransformer {
private Context context;
private int spaceBetweenFirAndSecWith = 10 * 2;//第一张卡片和第二张卡片宽度差 dp单位
private int spaceBetweenFirAndSecHeight = 10;//第一张卡片和第二张卡片高度差 dp单位
public VerticalStackTransformer( Context context ) {
this.context = context;
}
public VerticalStackTransformer( Context context, int spaceBetweenFirAndSecWith, int spaceBetweenFirAndSecHeight ) {
this.context = context;
this.spaceBetweenFirAndSecWith = spaceBetweenFirAndSecWith;
this.spaceBetweenFirAndSecHeight = spaceBetweenFirAndSecHeight;
}
@Override
protected void onTransform( View page, float position ) {
if ( position <= 0.0f ) {
page.setAlpha( 1.0f );
page.setTranslationY( 0f );
//控制停止滑动切换的时候,只有最上面的一张卡片可以点击
page.setClickable( true );
} else if ( position <= 3.0f ) {
float scale = ( float ) ( page.getWidth() - WindowUtils.dip2px( context, spaceBetweenFirAndSecWith * position ) ) / ( float ) ( page.getWidth() );
//控制下面卡片的可见度
page.setAlpha( 1.0f );
//控制停止滑动切换的时候,只有最上面的一张卡片可以点击
page.setClickable( false );
page.setPivotX( page.getWidth() / 2f );
page.setPivotY( page.getHeight() / 2f );
page.setScaleX( scale );
page.setScaleY( scale );
page.setTranslationY( -page.getHeight() * position + ( page.getHeight() * 0.5f ) * ( 1 - scale ) + WindowUtils.dip2px( context, spaceBetweenFirAndSecHeight ) * position );
}
}
}

View File

@@ -0,0 +1,38 @@
package com.mogo.module.main.cards;
import android.view.View;
import androidx.viewpager.widget.ViewPager;
public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
private static final float MAX_SCALE = 1.0f;
private static final float MIN_SCALE = 0.85f;//0.85f
@Override
public void transformPage( View view, float position ) {
// //setScaleY只支持api11以上
if ( position < -1 ) {
view.setScaleX( MIN_SCALE );
view.setScaleY( MIN_SCALE );
} else if ( position <= 1 ) //a页滑动至b页 a页从 0.0 -1 b页从1 ~ 0.0
{ // [-1,1]
// Log.e("TAG", view + " , " + position + "");
float scaleFactor = MIN_SCALE + ( 1 - Math.abs( position ) ) * ( MAX_SCALE - MIN_SCALE );
view.setScaleX( scaleFactor );
//每次滑动后进行微小的移动目的是为了防止在三星的某些手机上出现两边的页面为显示的情况
if ( position > 0 ) {
view.setTranslationX( -scaleFactor * 2 );
} else if ( position < 0 ) {
view.setTranslationX( scaleFactor * 2 );
}
view.setScaleY( scaleFactor );
} else { // (1,+Infinity]
view.setScaleX( MIN_SCALE );
view.setScaleY( MIN_SCALE );
}
}
}

View File

@@ -0,0 +1,8 @@
{
"cards": [
{
"name": "",
"path": ""
}
]
}

View File

@@ -4,13 +4,40 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 小智语音-->
<FrameLayout
android:id="@+id/module_main_id_ai_fragment_container"
android:layout_width="match_parent"
android:layout_height="100dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- 卡片-->
<FrameLayout
android:id="@+id/module_main_id_fragment_container"
android:layout_width="300dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="parent">
<com.mogo.module.main.cards.OrientedViewPager
android:id="@+id/module_main_id_cards_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="30dp"
android:layout_marginBottom="50dp"
android:padding="10dp" />
<!-- <androidx.viewpager2.widget.ViewPager2-->
<!-- android:id="@+id/module_main_id_cards_container"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:clipChildren="false" />-->
</FrameLayout>
<!-- 地图-->
<FrameLayout
android:id="@+id/module_main_id_map_fragment_container"
android:layout_width="0dp"

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f00">
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -2,15 +2,13 @@ apply plugin: 'com.android.library'
apply plugin: 'com.alibaba.arouter'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
compileSdkVersion rootProject.ext.android.compileSdkVersion
buildToolsVersion rootProject.ext.android.buildToolsVersion
defaultConfig {
minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
versionCode Integer.valueOf(VERSION_CODE)
versionName getValueFromRootProperties("${project.name.replace("-", "_").toUpperCase()}_VERSION")
javaCompileOptions {
annotationProcessorOptions {
@@ -33,14 +31,25 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(":libraries:mogo-map")
implementation project(":libraries:mogo-map-api")
implementation project(":foudations:mogo-utils")
api project(":foudations:mogo-commons")
api project(':services:mogo-service-api')
implementation project(':modules:mogo-module-common')
implementation rootProject.ext.dependencies.androidxappcompat
implementation rootProject.ext.dependencies.androidxconstraintlayout
implementation rootProject.ext.dependencies.arouter
annotationProcessor rootProject.ext.dependencies.aroutercompiler
if (Boolean.valueOf(RELEASE)) {
implementation rootProject.ext.dependencies.mogomap
implementation rootProject.ext.dependencies.mogomapapi
implementation rootProject.ext.dependencies.mogoutils
api rootProject.ext.dependencies.mogocommons
api rootProject.ext.dependencies.mogoserviceapi
implementation rootProject.ext.dependencies.modulecommon
} else {
implementation project(":libraries:mogo-map")
implementation project(":libraries:mogo-map-api")
implementation project(":foudations:mogo-utils")
api project(":foudations:mogo-commons")
api project(':services:mogo-service-api')
implementation project(':modules:mogo-module-common')
}
}
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()

View File

@@ -0,0 +1,3 @@
GROUP=com.mogo.module
POM_ARTIFACT_ID=module-map
VERSION_CODE=1

View File

@@ -9,6 +9,7 @@ import com.mogo.commons.mvp.MvpFragment;
import com.mogo.map.IMogoMap;
import com.mogo.map.IMogoUiSettings;
import com.mogo.map.MogoMapView;
import com.mogo.service.map.IMogoMapService;
/**
* @author congtaowang
@@ -18,6 +19,8 @@ import com.mogo.map.MogoMapView;
*/
public class MapFragment extends MvpFragment< MapView, MapPresenter > implements MapView {
private static final String TAG = "MapFragment";
private MogoMapView mMogoMapView;
private IMogoMap mMogoMap;
@@ -30,6 +33,7 @@ public class MapFragment extends MvpFragment< MapView, MapPresenter > implements
protected void initViews() {
mMogoMapView = findViewById( R.id.module_map_id_map );
mMogoMap = mMogoMapView.getMap();
mMogoMap.getUIController().showMyLocation( true );
}
@NonNull
@@ -94,7 +98,7 @@ public class MapFragment extends MvpFragment< MapView, MapPresenter > implements
//设置旋转手势是否可用。
uiSettings.setRotateGesturesEnabled( false );
//设置比例尺控件是否可见
uiSettings.setScaleControlsEnabled( false );
uiSettings.setScaleControlsEnabled( true );
//设置拖拽手势是否可用。
uiSettings.setScrollGesturesEnabled( true );
//设置倾斜手势是否可用。

View File

@@ -9,6 +9,7 @@ import androidx.fragment.app.Fragment;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.mogo.map.listener.IMogoMapListener;
import com.mogo.map.location.IMogoLocationListener;
import com.mogo.map.navi.IMogoNaviListener;
import com.mogo.module.common.MogoModulePaths;
import com.mogo.service.module.IMogoModuleLifecycle;
@@ -68,4 +69,9 @@ public class MapFragmentProvider implements IMogoModuleProvider {
public IMogoNaviListener getNaviListener() {
return null;
}
@Override
public IMogoLocationListener getLocationListener() {
return null;
}
}