Merge branch 'feature/v1.0.2' of http://gitlab.zhidaoauto.com/ecos/yycp-service/Launcher into feature/v1.0.2
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="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="JDK" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -20,12 +20,12 @@ android {
|
||||
}
|
||||
|
||||
multiDexEnabled true
|
||||
externalNativeBuild {
|
||||
ndk {
|
||||
// 设置支持的SO库架构
|
||||
abiFilters 'armeabi-v7a'
|
||||
}
|
||||
}
|
||||
// externalNativeBuild {
|
||||
// ndk {
|
||||
// // 设置支持的SO库架构
|
||||
// abiFilters 'armeabi-v7a'
|
||||
// }
|
||||
// }
|
||||
}
|
||||
signingConfigs {
|
||||
release {
|
||||
|
||||
@@ -46,12 +46,13 @@ public class MogoApplication extends AbsMogoApplication {
|
||||
|
||||
//运营位卡片,需要默认显示,放在第一个加载
|
||||
MogoModulePaths.addModule(new MogoModule(AdCardConstants.TAG, AdCardConstants.MODULE_NAME));
|
||||
MogoModulePaths.addModule(new MogoModule(OnLineCarConstants.TAG, OnLineCarConstants.MODULE_NAME));
|
||||
MogoModulePaths.addModule(new MogoModule(V2XConst.PATH_V2X_UI, V2XConst.PATH_V2X_UI));
|
||||
MogoModulePaths.addModule(new MogoModule(TanluConstants.TAG, TanluConstants.MODEL_NAME));
|
||||
MogoModulePaths.addModule(new MogoModule(CallChatConstant.PROVIDER, CallChatConstant.MODULE_NAME));
|
||||
MogoModulePaths.addModule(new MogoModule(MediaConstants.TAG, MediaConstants.MODULE_TYPE));
|
||||
MogoModulePaths.addModule(new MogoModule(CallChatConstant.PROVIDER, CallChatConstant.MODULE_NAME));
|
||||
MogoModulePaths.addModule(new MogoModule(TanluConstants.TAG, TanluConstants.MODEL_NAME));
|
||||
MogoModulePaths.addModule(new MogoModule(OnLineCarConstants.TAG, OnLineCarConstants.MODULE_NAME));
|
||||
MogoModulePaths.addModule(new MogoModule( FreshNewsConstants.TAG, FreshNewsConstants.MODULE_NAME));
|
||||
|
||||
MogoModulePaths.addModule(new MogoModule(V2XConst.PATH_V2X_UI, V2XConst.PATH_V2X_UI));
|
||||
MogoModulePaths.addModule(new MogoModule(PushUIConstants.TAG, PushUIConstants.TAG));
|
||||
MogoModulePaths.addModule(new MogoModule( BackToLauncherConst.MODULE_PATH, BackToLauncherConst.MODULE_NAME));
|
||||
Log.i("timer", "cost " + (System.currentTimeMillis() - start) + "ms");
|
||||
|
||||
@@ -21,6 +21,8 @@ buildscript {
|
||||
classpath 'com.android.tools.build:gradle:3.5.2'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "com.alibaba:arouter-register:1.0.2"
|
||||
classpath 'com.novoda:bintray-release:0.8.0'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
|
||||
@@ -89,7 +89,8 @@ ext {
|
||||
modulecommon : "com.mogo.module:module-common:${MOGO_MODULE_COMMON_VERSION}",
|
||||
modulemain : "com.mogo.module:module-main:${MOGO_MODULE_MAIN_VERSION}",
|
||||
modulemap : "com.mogo.module:module-map:${MOGO_MODULE_MAP_VERSION}",
|
||||
moduleservice : "com.mogo.module:module-service:${MOGO_MODULE_SERVICE_VERSION}",
|
||||
moduleservice : "com.mogo.module:module-service:${CARD_LIBRARY_VERSION}",
|
||||
uicard : "com.mogo.ui:card-libaray:${MOGO_MODULE_SERVICE_VERSION}",
|
||||
mogoservice : "com.mogo.service:mogo-service:${MOGO_SERVICE_VERSION}",
|
||||
mogoserviceapi : "com.mogo.service:mogo-service-api:${MOGO_SERVICE_API_VERSION}",
|
||||
moduleapps : "com.mogo.module:module-apps:${MOGO_MODULE_APPS_VERSION}",
|
||||
|
||||
@@ -107,7 +107,7 @@ public class SocketManager implements IMogoSocketManager, OnSocketReceiveCallbac
|
||||
object = GsonUtil.objectFromJson( payload.getPayload().toStringUtf8(), listener.target() );
|
||||
}
|
||||
if ( listener != null ) {
|
||||
Logger.d( TAG, "received msgId = %s", msgId );
|
||||
Logger.d( TAG, "received msgId = %s, content = %s", msgId, payload.getPayload().toStringUtf8() );
|
||||
listener.onMsgReceived( object );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import java.util.concurrent.Executors;
|
||||
|
||||
public class ThreadPoolService {
|
||||
|
||||
private static final ExecutorService SERVICE = Executors.newScheduledThreadPool( 3 );
|
||||
private static final ExecutorService SERVICE = Executors.newFixedThreadPool( 3 );
|
||||
|
||||
private ThreadPoolService() {
|
||||
}
|
||||
|
||||
@@ -66,3 +66,5 @@ MOGO_MODULE_AD_CARD_VERSION=1.0.0-SNAPSHOT
|
||||
# 新鲜水
|
||||
MOGO_MODULE_FRESH_NEWS_VERSION=1.0.0-SNAPSHOT
|
||||
|
||||
# 卡片效果
|
||||
CARD_LIBRARY_VERSION=1.0.0-SNAPSHOT
|
||||
1
libraries/card-library/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
36
libraries/card-library/build.gradle
Normal file
@@ -0,0 +1,36 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'com.novoda.bintray-release'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
||||
|
||||
defaultConfig {
|
||||
targetSdkVersion rootProject.ext.android.targetSdkVersion
|
||||
minSdkVersion rootProject.ext.android.minSdkVersion
|
||||
versionCode Integer.valueOf(VERSION_CODE)
|
||||
versionName getValueFromRootProperties("${project.name.replace("-", "_").toUpperCase()}_VERSION")
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation rootProject.ext.dependencies.androidxappcompat
|
||||
implementation rootProject.ext.dependencies.androidxrecyclerview
|
||||
testImplementation 'org.robolectric:robolectric:3.0'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
testImplementation 'org.mockito:mockito-core:2.13.0'
|
||||
testImplementation 'org.hamcrest:hamcrest-library:1.3'
|
||||
androidTestImplementation 'org.hamcrest:hamcrest-library:1.3'
|
||||
}
|
||||
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
|
||||
|
||||
//publish {
|
||||
// artifactId = 'discrete-scrollview'
|
||||
// userOrg = rootProject.userOrg
|
||||
// groupId = rootProject.groupId
|
||||
// uploadName = rootProject.uploadName
|
||||
// publishVersion = rootProject.publishVersion
|
||||
// description = rootProject.description
|
||||
// licences = rootProject.licences
|
||||
//}
|
||||
3
libraries/card-library/gradle.properties
Normal file
@@ -0,0 +1,3 @@
|
||||
GROUP=com.mogo.ui
|
||||
POM_ARTIFACT_ID=card-libaray
|
||||
VERSION_CODE=1
|
||||
17
libraries/card-library/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in C:\Users\yarolegovich\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
1
libraries/card-library/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1 @@
|
||||
<manifest package="com.yarolegovich.discretescrollview" />
|
||||
@@ -0,0 +1,219 @@
|
||||
package com.yarolegovich.discretescrollview;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* Created by yarolegovich on 16.03.2017.
|
||||
*/
|
||||
public enum DSVOrientation {
|
||||
|
||||
HORIZONTAL {
|
||||
@Override
|
||||
Helper createHelper() {
|
||||
return new HorizontalHelper();
|
||||
}
|
||||
},
|
||||
VERTICAL {
|
||||
@Override
|
||||
Helper createHelper() {
|
||||
return new VerticalHelper();
|
||||
}
|
||||
};
|
||||
|
||||
//Package private
|
||||
abstract Helper createHelper();
|
||||
|
||||
interface Helper {
|
||||
|
||||
int getViewEnd(int recyclerWidth, int recyclerHeight);
|
||||
|
||||
int getDistanceToChangeCurrent(int childWidth, int childHeight);
|
||||
|
||||
void setCurrentViewCenter(Point recyclerCenter, int scrolled, Point outPoint);
|
||||
|
||||
void shiftViewCenter(Direction direction, int shiftAmount, Point outCenter);
|
||||
|
||||
int getFlingVelocity(int velocityX, int velocityY);
|
||||
|
||||
int getPendingDx(int pendingScroll);
|
||||
|
||||
int getPendingDy(int pendingScroll);
|
||||
|
||||
void offsetChildren(int amount, RecyclerViewProxy lm);
|
||||
|
||||
float getDistanceFromCenter(Point center, int viewCenterX, int viewCenterY);
|
||||
|
||||
boolean isViewVisible(Point center, int halfWidth, int halfHeight, int endBound, int extraSpace);
|
||||
|
||||
boolean hasNewBecomeVisible(DiscreteScrollLayoutManager lm);
|
||||
|
||||
boolean canScrollVertically();
|
||||
|
||||
boolean canScrollHorizontally();
|
||||
}
|
||||
|
||||
protected static class HorizontalHelper implements Helper {
|
||||
|
||||
@Override
|
||||
public int getViewEnd(int recyclerWidth, int recyclerHeight) {
|
||||
return recyclerWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDistanceToChangeCurrent(int childWidth, int childHeight) {
|
||||
return childWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentViewCenter(Point recyclerCenter, int scrolled, Point outPoint) {
|
||||
int newX = recyclerCenter.x - scrolled;
|
||||
outPoint.set(newX, recyclerCenter.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shiftViewCenter(Direction direction, int shiftAmount, Point outCenter) {
|
||||
int newX = outCenter.x + direction.applyTo(shiftAmount);
|
||||
outCenter.set(newX, outCenter.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewVisible(
|
||||
Point viewCenter, int halfWidth, int halfHeight, int endBound,
|
||||
int extraSpace) {
|
||||
int viewLeft = viewCenter.x - halfWidth;
|
||||
int viewRight = viewCenter.x + halfWidth;
|
||||
return viewLeft < (endBound + extraSpace) && viewRight > -extraSpace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNewBecomeVisible(DiscreteScrollLayoutManager lm) {
|
||||
View firstChild = lm.getFirstChild(), lastChild = lm.getLastChild();
|
||||
int leftBound = -lm.getExtraLayoutSpace();
|
||||
int rightBound = lm.getWidth() + lm.getExtraLayoutSpace();
|
||||
boolean isNewVisibleFromLeft = lm.getDecoratedLeft(firstChild) > leftBound
|
||||
&& lm.getPosition(firstChild) > 0;
|
||||
boolean isNewVisibleFromRight = lm.getDecoratedRight(lastChild) < rightBound
|
||||
&& lm.getPosition(lastChild) < lm.getItemCount() - 1;
|
||||
return isNewVisibleFromLeft || isNewVisibleFromRight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void offsetChildren(int amount, RecyclerViewProxy helper) {
|
||||
helper.offsetChildrenHorizontal(amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getDistanceFromCenter(Point center, int viewCenterX, int viewCenterY) {
|
||||
return viewCenterX - center.x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFlingVelocity(int velocityX, int velocityY) {
|
||||
return velocityX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canScrollHorizontally() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canScrollVertically() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPendingDx(int pendingScroll) {
|
||||
return pendingScroll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPendingDy(int pendingScroll) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected static class VerticalHelper implements Helper {
|
||||
|
||||
@Override
|
||||
public int getViewEnd(int recyclerWidth, int recyclerHeight) {
|
||||
return recyclerHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDistanceToChangeCurrent(int childWidth, int childHeight) {
|
||||
return childHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentViewCenter(Point recyclerCenter, int scrolled, Point outPoint) {
|
||||
int newY = recyclerCenter.y - scrolled;
|
||||
outPoint.set(recyclerCenter.x, newY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shiftViewCenter(Direction direction, int shiftAmount, Point outCenter) {
|
||||
int newY = outCenter.y + direction.applyTo(shiftAmount);
|
||||
outCenter.set(outCenter.x, newY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void offsetChildren(int amount, RecyclerViewProxy helper) {
|
||||
helper.offsetChildrenVertical(amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getDistanceFromCenter(Point center, int viewCenterX, int viewCenterY) {
|
||||
return viewCenterY - center.y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewVisible(
|
||||
Point viewCenter, int halfWidth, int halfHeight, int endBound,
|
||||
int extraSpace) {
|
||||
int viewTop = viewCenter.y - halfHeight;
|
||||
int viewBottom = viewCenter.y + halfHeight;
|
||||
return viewTop < (endBound + extraSpace) && viewBottom > -extraSpace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNewBecomeVisible(DiscreteScrollLayoutManager lm) {
|
||||
View firstChild = lm.getFirstChild(), lastChild = lm.getLastChild();
|
||||
int topBound = -lm.getExtraLayoutSpace();
|
||||
int bottomBound = lm.getHeight() + lm.getExtraLayoutSpace();
|
||||
boolean isNewVisibleFromTop = lm.getDecoratedTop(firstChild) > topBound
|
||||
&& lm.getPosition(firstChild) > 0;
|
||||
boolean isNewVisibleFromBottom = lm.getDecoratedBottom(lastChild) < bottomBound
|
||||
&& lm.getPosition(lastChild) < lm.getItemCount() - 1;
|
||||
return isNewVisibleFromTop || isNewVisibleFromBottom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFlingVelocity(int velocityX, int velocityY) {
|
||||
return velocityY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canScrollHorizontally() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canScrollVertically() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPendingDx(int pendingScroll) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPendingDy(int pendingScroll) {
|
||||
return pendingScroll;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.yarolegovich.discretescrollview;
|
||||
|
||||
/**
|
||||
* Created by yarolegovich on 16.03.2017.
|
||||
*/
|
||||
enum Direction {
|
||||
|
||||
START {
|
||||
@Override
|
||||
public int applyTo(int delta) {
|
||||
return delta * -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sameAs(int direction) {
|
||||
return direction < 0;
|
||||
}
|
||||
},
|
||||
END {
|
||||
@Override
|
||||
public int applyTo(int delta) {
|
||||
return delta;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sameAs(int direction) {
|
||||
return direction > 0;
|
||||
}
|
||||
};
|
||||
|
||||
public abstract int applyTo(int delta);
|
||||
|
||||
public abstract boolean sameAs(int direction);
|
||||
|
||||
public static Direction fromDelta(int delta) {
|
||||
return delta > 0 ? END : START;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,786 @@
|
||||
package com.yarolegovich.discretescrollview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.view.accessibility.AccessibilityEventCompat;
|
||||
import androidx.core.view.accessibility.AccessibilityRecordCompat;
|
||||
import androidx.recyclerview.widget.LinearSmoothScroller;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.yarolegovich.discretescrollview.transform.DiscreteScrollItemTransformer;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Created by yarolegovich on 17.02.2017.
|
||||
*/
|
||||
class DiscreteScrollLayoutManager extends RecyclerView.LayoutManager {
|
||||
|
||||
static final int NO_POSITION = -1;
|
||||
|
||||
private static final String EXTRA_POSITION = "extra_position";
|
||||
private static final int DEFAULT_TIME_FOR_ITEM_SETTLE = 300;
|
||||
private static final int DEFAULT_FLING_THRESHOLD = 2100; //Decrease to increase sensitivity.
|
||||
private static final int DEFAULT_TRANSFORM_CLAMP_ITEM_COUNT = 1;
|
||||
|
||||
protected static final float SCROLL_TO_SNAP_TO_ANOTHER_ITEM = 0.6f;
|
||||
|
||||
//This field will take value of all visible view's center points during the fill phase
|
||||
protected Point viewCenterIterator;
|
||||
protected Point recyclerCenter;
|
||||
protected Point currentViewCenter;
|
||||
protected int childHalfWidth, childHalfHeight;
|
||||
protected int extraLayoutSpace;
|
||||
|
||||
//Max possible distance a view can travel during one scroll phase
|
||||
protected int scrollToChangeCurrent;
|
||||
protected int currentScrollState;
|
||||
|
||||
protected int scrolled;
|
||||
protected int pendingScroll;
|
||||
protected int currentPosition;
|
||||
protected int pendingPosition;
|
||||
|
||||
protected SparseArray<View> detachedCache;
|
||||
|
||||
private DSVOrientation.Helper orientationHelper;
|
||||
|
||||
protected boolean isFirstOrEmptyLayout;
|
||||
|
||||
private Context context;
|
||||
|
||||
private int timeForItemSettle;
|
||||
private int offscreenItems;
|
||||
private int transformClampItemCount;
|
||||
|
||||
private boolean dataSetChangeShiftedPosition;
|
||||
|
||||
private int flingThreshold;
|
||||
private boolean shouldSlideOnFling;
|
||||
|
||||
private int viewWidth, viewHeight;
|
||||
|
||||
@NonNull
|
||||
private final ScrollStateListener scrollStateListener;
|
||||
private DiscreteScrollItemTransformer itemTransformer;
|
||||
|
||||
private RecyclerViewProxy recyclerViewProxy;
|
||||
|
||||
public DiscreteScrollLayoutManager(
|
||||
@NonNull Context c,
|
||||
@NonNull ScrollStateListener scrollStateListener,
|
||||
@NonNull DSVOrientation orientation) {
|
||||
this.context = c;
|
||||
this.timeForItemSettle = DEFAULT_TIME_FOR_ITEM_SETTLE;
|
||||
this.pendingPosition = NO_POSITION;
|
||||
this.currentPosition = NO_POSITION;
|
||||
this.flingThreshold = DEFAULT_FLING_THRESHOLD;
|
||||
this.shouldSlideOnFling = false;
|
||||
this.recyclerCenter = new Point();
|
||||
this.currentViewCenter = new Point();
|
||||
this.viewCenterIterator = new Point();
|
||||
this.detachedCache = new SparseArray<>();
|
||||
this.scrollStateListener = scrollStateListener;
|
||||
this.orientationHelper = orientation.createHelper();
|
||||
this.recyclerViewProxy = new RecyclerViewProxy(this);
|
||||
this.transformClampItemCount = DEFAULT_TRANSFORM_CLAMP_ITEM_COUNT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||
if (state.getItemCount() == 0) {
|
||||
recyclerViewProxy.removeAndRecycleAllViews(recycler);
|
||||
currentPosition = pendingPosition = NO_POSITION;
|
||||
scrolled = pendingScroll = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ensureValidPosition(state);
|
||||
|
||||
updateRecyclerDimensions(state);
|
||||
|
||||
//onLayoutChildren may be called multiple times and this check is required so that the flag
|
||||
//won't be cleared until onLayoutCompleted
|
||||
if (!isFirstOrEmptyLayout) {
|
||||
isFirstOrEmptyLayout = recyclerViewProxy.getChildCount() == 0;
|
||||
if (isFirstOrEmptyLayout) {
|
||||
initChildDimensions(recycler);
|
||||
}
|
||||
}
|
||||
|
||||
recyclerViewProxy.detachAndScrapAttachedViews(recycler);
|
||||
|
||||
fill(recycler);
|
||||
|
||||
applyItemTransformToChildren();
|
||||
}
|
||||
|
||||
private void ensureValidPosition(RecyclerView.State state) {
|
||||
if (currentPosition == NO_POSITION || currentPosition >= state.getItemCount()) {
|
||||
//currentPosition might have been assigned in onRestoreInstanceState()
|
||||
//which can lead to a crash (position out of bounds) when data set
|
||||
//is not persisted across rotations
|
||||
currentPosition = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLayoutCompleted(RecyclerView.State state) {
|
||||
if (isFirstOrEmptyLayout) {
|
||||
scrollStateListener.onCurrentViewFirstLayout();
|
||||
isFirstOrEmptyLayout = false;
|
||||
} else if (dataSetChangeShiftedPosition) {
|
||||
scrollStateListener.onDataSetChangeChangedPosition();
|
||||
dataSetChangeShiftedPosition = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected void initChildDimensions(RecyclerView.Recycler recycler) {
|
||||
View viewToMeasure = recyclerViewProxy.getMeasuredChildForAdapterPosition(0, recycler);
|
||||
|
||||
int childViewWidth = recyclerViewProxy.getMeasuredWidthWithMargin(viewToMeasure);
|
||||
int childViewHeight = recyclerViewProxy.getMeasuredHeightWithMargin(viewToMeasure);
|
||||
|
||||
childHalfWidth = childViewWidth / 2;
|
||||
childHalfHeight = childViewHeight / 2;
|
||||
|
||||
scrollToChangeCurrent = orientationHelper.getDistanceToChangeCurrent(
|
||||
childViewWidth,
|
||||
childViewHeight);
|
||||
|
||||
extraLayoutSpace = scrollToChangeCurrent * offscreenItems;
|
||||
|
||||
recyclerViewProxy.detachAndScrapView(viewToMeasure, recycler);
|
||||
}
|
||||
|
||||
protected void updateRecyclerDimensions(RecyclerView.State state) {
|
||||
boolean dimensionsChanged = !state.isMeasuring()
|
||||
&& (recyclerViewProxy.getWidth() != viewWidth
|
||||
|| recyclerViewProxy.getHeight() != viewHeight);
|
||||
if (dimensionsChanged) {
|
||||
viewWidth = recyclerViewProxy.getWidth();
|
||||
viewHeight = recyclerViewProxy.getHeight();
|
||||
recyclerViewProxy.removeAllViews();
|
||||
}
|
||||
recyclerCenter.set(
|
||||
recyclerViewProxy.getWidth() / 523*330,
|
||||
recyclerViewProxy.getHeight() / 2);
|
||||
}
|
||||
|
||||
protected void fill(RecyclerView.Recycler recycler) {
|
||||
cacheAndDetachAttachedViews();
|
||||
|
||||
orientationHelper.setCurrentViewCenter(recyclerCenter, scrolled, currentViewCenter);
|
||||
|
||||
final int endBound = orientationHelper.getViewEnd(
|
||||
recyclerViewProxy.getWidth(),
|
||||
recyclerViewProxy.getHeight());
|
||||
|
||||
//Layout current
|
||||
if (isViewVisible(currentViewCenter, endBound)) {
|
||||
layoutView(recycler, currentPosition, currentViewCenter);
|
||||
}
|
||||
|
||||
//Layout items before the current item
|
||||
layoutViews(recycler, Direction.START, endBound);
|
||||
|
||||
//Layout items after the current item
|
||||
layoutViews(recycler, Direction.END, endBound);
|
||||
|
||||
recycleDetachedViewsAndClearCache(recycler);
|
||||
}
|
||||
|
||||
private void layoutViews(RecyclerView.Recycler recycler, Direction direction, int endBound) {
|
||||
final int positionStep = direction.applyTo(1);
|
||||
|
||||
//Predictive layout is required when we are doing smooth fast scroll towards pendingPosition
|
||||
boolean noPredictiveLayoutRequired = pendingPosition == NO_POSITION
|
||||
|| !direction.sameAs(pendingPosition - currentPosition);
|
||||
|
||||
viewCenterIterator.set(currentViewCenter.x, currentViewCenter.y);
|
||||
for (int pos = currentPosition + positionStep; isInBounds(pos); pos += positionStep) {
|
||||
if (pos == pendingPosition) {
|
||||
noPredictiveLayoutRequired = true;
|
||||
}
|
||||
orientationHelper.shiftViewCenter(direction, scrollToChangeCurrent, viewCenterIterator);
|
||||
if (isViewVisible(viewCenterIterator, endBound)) {
|
||||
layoutView(recycler, pos, viewCenterIterator);
|
||||
} else if (noPredictiveLayoutRequired) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void layoutView(RecyclerView.Recycler recycler, int position, Point viewCenter) {
|
||||
if (position < 0) return;
|
||||
View v = detachedCache.get(position);
|
||||
if (v == null) {
|
||||
v = recyclerViewProxy.getMeasuredChildForAdapterPosition(position, recycler);
|
||||
recyclerViewProxy.layoutDecoratedWithMargins(v,
|
||||
viewCenter.x - childHalfWidth, viewCenter.y - childHalfHeight,
|
||||
viewCenter.x + childHalfWidth, viewCenter.y + childHalfHeight);
|
||||
} else {
|
||||
recyclerViewProxy.attachView(v);
|
||||
detachedCache.remove(position);
|
||||
}
|
||||
}
|
||||
|
||||
protected void cacheAndDetachAttachedViews() {
|
||||
detachedCache.clear();
|
||||
for (int i = 0; i < recyclerViewProxy.getChildCount(); i++) {
|
||||
View child = recyclerViewProxy.getChildAt(i);
|
||||
detachedCache.put(recyclerViewProxy.getPosition(child), child);
|
||||
}
|
||||
|
||||
for (int i = 0; i < detachedCache.size(); i++) {
|
||||
recyclerViewProxy.detachView(detachedCache.valueAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
protected void recycleDetachedViewsAndClearCache(RecyclerView.Recycler recycler) {
|
||||
for (int i = 0; i < detachedCache.size(); i++) {
|
||||
View viewToRemove = detachedCache.valueAt(i);
|
||||
recyclerViewProxy.recycleView(viewToRemove, recycler);
|
||||
}
|
||||
detachedCache.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemsAdded(RecyclerView recyclerView, int positionStart, int itemCount) {
|
||||
int newPosition = currentPosition;
|
||||
if (currentPosition == NO_POSITION) {
|
||||
newPosition = 0;
|
||||
} else if (currentPosition >= positionStart) {
|
||||
newPosition = Math.min(currentPosition + itemCount, recyclerViewProxy.getItemCount() - 1);
|
||||
}
|
||||
onNewPosition(newPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemsRemoved(RecyclerView recyclerView, int positionStart, int itemCount) {
|
||||
int newPosition = currentPosition;
|
||||
if (recyclerViewProxy.getItemCount() == 0) {
|
||||
newPosition = NO_POSITION;
|
||||
} else if (currentPosition >= positionStart) {
|
||||
if (currentPosition < positionStart + itemCount) {
|
||||
//If currentPosition is in the removed items, then the new item became current
|
||||
currentPosition = NO_POSITION;
|
||||
}
|
||||
newPosition = Math.max(0, currentPosition - itemCount);
|
||||
}
|
||||
onNewPosition(newPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemsChanged(RecyclerView recyclerView) {
|
||||
//notifyDataSetChanged() was called. We need to ensure that currentPosition is not out of bounds
|
||||
currentPosition = Math.min(Math.max(0, currentPosition), recyclerViewProxy.getItemCount() - 1);
|
||||
dataSetChangeShiftedPosition = true;
|
||||
}
|
||||
|
||||
private void onNewPosition(int position) {
|
||||
if (currentPosition != position) {
|
||||
currentPosition = position;
|
||||
dataSetChangeShiftedPosition = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||
return scrollBy(dx, recycler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||
return scrollBy(dy, recycler);
|
||||
}
|
||||
|
||||
protected int scrollBy(int amount, RecyclerView.Recycler recycler) {
|
||||
if (recyclerViewProxy.getChildCount() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Direction direction = Direction.fromDelta(amount);
|
||||
int leftToScroll = calculateAllowedScrollIn(direction);
|
||||
if (leftToScroll <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int delta = direction.applyTo(Math.min(leftToScroll, Math.abs(amount)));
|
||||
scrolled += delta;
|
||||
if (pendingScroll != 0) {
|
||||
pendingScroll -= delta;
|
||||
}
|
||||
|
||||
orientationHelper.offsetChildren(-delta, recyclerViewProxy);
|
||||
|
||||
if (orientationHelper.hasNewBecomeVisible(this)) {
|
||||
fill(recycler);
|
||||
}
|
||||
|
||||
notifyScroll();
|
||||
|
||||
applyItemTransformToChildren();
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
protected void applyItemTransformToChildren() {
|
||||
if (itemTransformer != null) {
|
||||
int clampAfterDistance = scrollToChangeCurrent * transformClampItemCount;
|
||||
for (int i = 0; i < recyclerViewProxy.getChildCount(); i++) {
|
||||
View child = recyclerViewProxy.getChildAt(i);
|
||||
float position = getCenterRelativePositionOf(child, clampAfterDistance);
|
||||
itemTransformer.transformItem(child, position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scrollToPosition(int position) {
|
||||
if (currentPosition == position) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentPosition = position;
|
||||
recyclerViewProxy.requestLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
|
||||
if (currentPosition == position || pendingPosition != NO_POSITION) {
|
||||
return;
|
||||
}
|
||||
checkTargetPosition(state, position);
|
||||
if (currentPosition == NO_POSITION) {
|
||||
//Layout not happened yet
|
||||
currentPosition = position;
|
||||
} else {
|
||||
startSmoothPendingScroll(position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canScrollHorizontally() {
|
||||
return orientationHelper.canScrollHorizontally();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canScrollVertically() {
|
||||
return orientationHelper.canScrollVertically();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrollStateChanged(int state) {
|
||||
if (currentScrollState == RecyclerView.SCROLL_STATE_IDLE && currentScrollState != state) {
|
||||
scrollStateListener.onScrollStart();
|
||||
}
|
||||
|
||||
if (state == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
//Scroll is not finished until current view is centered
|
||||
boolean isScrollEnded = onScrollEnd();
|
||||
if (isScrollEnded) {
|
||||
scrollStateListener.onScrollEnd();
|
||||
} else {
|
||||
//Scroll continues and we don't want to set currentScrollState to STATE_IDLE,
|
||||
//because this will then trigger .scrollStateListener.onScrollStart()
|
||||
return;
|
||||
}
|
||||
} else if (state == RecyclerView.SCROLL_STATE_DRAGGING) {
|
||||
onDragStart();
|
||||
}
|
||||
currentScrollState = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if scroll is ended and we don't need to settle items
|
||||
*/
|
||||
private boolean onScrollEnd() {
|
||||
if (pendingPosition != NO_POSITION) {
|
||||
currentPosition = pendingPosition;
|
||||
pendingPosition = NO_POSITION;
|
||||
scrolled = 0;
|
||||
}
|
||||
|
||||
Direction scrollDirection = Direction.fromDelta(scrolled);
|
||||
if (Math.abs(scrolled) == scrollToChangeCurrent) {
|
||||
currentPosition += scrollDirection.applyTo(1);
|
||||
scrolled = 0;
|
||||
}
|
||||
|
||||
if (isAnotherItemCloserThanCurrent()) {
|
||||
pendingScroll = getHowMuchIsLeftToScroll(scrolled);
|
||||
} else {
|
||||
pendingScroll = -scrolled;
|
||||
}
|
||||
|
||||
if (pendingScroll == 0) {
|
||||
return true;
|
||||
} else {
|
||||
startSmoothPendingScroll();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void onDragStart() {
|
||||
//Here we need to:
|
||||
//1. Stop any pending scroll
|
||||
//2. Set currentPosition to position of the item that is closest to the center
|
||||
boolean isScrollingThroughMultiplePositions = Math.abs(scrolled) > scrollToChangeCurrent;
|
||||
if (isScrollingThroughMultiplePositions) {
|
||||
int scrolledPositions = scrolled / scrollToChangeCurrent;
|
||||
currentPosition += scrolledPositions;
|
||||
scrolled -= scrolledPositions * scrollToChangeCurrent;
|
||||
}
|
||||
if (isAnotherItemCloserThanCurrent()) {
|
||||
Direction direction = Direction.fromDelta(scrolled);
|
||||
currentPosition += direction.applyTo(1);
|
||||
scrolled = -getHowMuchIsLeftToScroll(scrolled);
|
||||
}
|
||||
pendingPosition = NO_POSITION;
|
||||
pendingScroll = 0;
|
||||
}
|
||||
|
||||
public void onFling(int velocityX, int velocityY) {
|
||||
int velocity = orientationHelper.getFlingVelocity(velocityX, velocityY);
|
||||
int throttleValue = shouldSlideOnFling ? Math.abs(velocity / flingThreshold) : 1;
|
||||
int newPosition = currentPosition + Direction.fromDelta(velocity).applyTo(throttleValue);
|
||||
newPosition = checkNewOnFlingPositionIsInBounds(newPosition);
|
||||
boolean isInScrollDirection = velocity * scrolled >= 0;
|
||||
boolean canFling = isInScrollDirection && isInBounds(newPosition);
|
||||
if (canFling) {
|
||||
startSmoothPendingScroll(newPosition);
|
||||
} else {
|
||||
returnToCurrentPosition();
|
||||
}
|
||||
}
|
||||
|
||||
public void returnToCurrentPosition() {
|
||||
pendingScroll = -scrolled;
|
||||
if (pendingScroll != 0) {
|
||||
startSmoothPendingScroll();
|
||||
}
|
||||
}
|
||||
|
||||
protected int calculateAllowedScrollIn(Direction direction) {
|
||||
if (pendingScroll != 0) {
|
||||
return Math.abs(pendingScroll);
|
||||
}
|
||||
int allowedScroll;
|
||||
boolean isBoundReached;
|
||||
boolean isScrollDirectionAsBefore = direction.applyTo(scrolled) > 0;
|
||||
if (direction == Direction.START && currentPosition == 0) {
|
||||
//We can scroll to the left when currentPosition == 0 only if we scrolled to the right before
|
||||
isBoundReached = scrolled == 0;
|
||||
allowedScroll = isBoundReached ? 0 : Math.abs(scrolled);
|
||||
} else if (direction == Direction.END && currentPosition == recyclerViewProxy.getItemCount() - 1) {
|
||||
//We can scroll to the right when currentPosition == last only if we scrolled to the left before
|
||||
isBoundReached = scrolled == 0;
|
||||
allowedScroll = isBoundReached ? 0 : Math.abs(scrolled);
|
||||
} else {
|
||||
isBoundReached = false;
|
||||
allowedScroll = isScrollDirectionAsBefore ?
|
||||
scrollToChangeCurrent - Math.abs(scrolled) :
|
||||
scrollToChangeCurrent + Math.abs(scrolled);
|
||||
}
|
||||
scrollStateListener.onIsBoundReachedFlagChange(isBoundReached);
|
||||
return allowedScroll;
|
||||
}
|
||||
|
||||
private void startSmoothPendingScroll() {
|
||||
LinearSmoothScroller scroller = new DiscreteLinearSmoothScroller(context);
|
||||
scroller.setTargetPosition(currentPosition);
|
||||
recyclerViewProxy.startSmoothScroll(scroller);
|
||||
}
|
||||
|
||||
private void startSmoothPendingScroll(int position) {
|
||||
if (currentPosition == position) return;
|
||||
pendingScroll = -scrolled;
|
||||
Direction direction = Direction.fromDelta(position - currentPosition);
|
||||
int distanceToScroll = Math.abs(position - currentPosition) * scrollToChangeCurrent;
|
||||
pendingScroll += direction.applyTo(distanceToScroll);
|
||||
pendingPosition = position;
|
||||
startSmoothPendingScroll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutoMeasureEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int computeVerticalScrollRange(RecyclerView.State state) {
|
||||
return computeScrollRange(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int computeVerticalScrollOffset(RecyclerView.State state) {
|
||||
return computeScrollOffset(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int computeVerticalScrollExtent(RecyclerView.State state) {
|
||||
return computeScrollExtent(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int computeHorizontalScrollRange(RecyclerView.State state) {
|
||||
return computeScrollRange(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int computeHorizontalScrollOffset(RecyclerView.State state) {
|
||||
return computeScrollOffset(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int computeHorizontalScrollExtent(RecyclerView.State state) {
|
||||
return computeScrollExtent(state);
|
||||
}
|
||||
|
||||
private int computeScrollOffset(RecyclerView.State state) {
|
||||
int scrollbarSize = computeScrollExtent(state);
|
||||
int offset = (int) ((scrolled / (float) scrollToChangeCurrent) * scrollbarSize);
|
||||
return (currentPosition * scrollbarSize) + offset;
|
||||
}
|
||||
|
||||
private int computeScrollExtent(RecyclerView.State state) {
|
||||
if (getItemCount() == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return (int) (computeScrollRange(state) / (float) getItemCount());
|
||||
}
|
||||
}
|
||||
|
||||
private int computeScrollRange(RecyclerView.State state) {
|
||||
if (getItemCount() == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return scrollToChangeCurrent * (getItemCount() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdapterChanged(RecyclerView.Adapter oldAdapter, RecyclerView.Adapter newAdapter) {
|
||||
pendingPosition = NO_POSITION;
|
||||
scrolled = pendingScroll = 0;
|
||||
if (newAdapter instanceof InitialPositionProvider) {
|
||||
currentPosition = ((InitialPositionProvider) newAdapter).getInitialPosition();
|
||||
} else {
|
||||
currentPosition = 0;
|
||||
}
|
||||
recyclerViewProxy.removeAllViews();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parcelable onSaveInstanceState() {
|
||||
Bundle bundle = new Bundle();
|
||||
if (pendingPosition != NO_POSITION) {
|
||||
currentPosition = pendingPosition;
|
||||
}
|
||||
bundle.putInt(EXTRA_POSITION, currentPosition);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreInstanceState(Parcelable state) {
|
||||
Bundle bundle = (Bundle) state;
|
||||
currentPosition = bundle.getInt(EXTRA_POSITION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
|
||||
return new RecyclerView.LayoutParams(
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
}
|
||||
|
||||
public int getNextPosition() {
|
||||
if (scrolled == 0) {
|
||||
return currentPosition;
|
||||
} else if (pendingPosition != NO_POSITION) {
|
||||
return pendingPosition;
|
||||
} else {
|
||||
return currentPosition + Direction.fromDelta(scrolled).applyTo(1);
|
||||
}
|
||||
}
|
||||
|
||||
public void setItemTransformer(DiscreteScrollItemTransformer itemTransformer) {
|
||||
this.itemTransformer = itemTransformer;
|
||||
}
|
||||
|
||||
public void setTimeForItemSettle(int timeForItemSettle) {
|
||||
this.timeForItemSettle = timeForItemSettle;
|
||||
}
|
||||
|
||||
public void setOffscreenItems(int offscreenItems) {
|
||||
this.offscreenItems = offscreenItems;
|
||||
extraLayoutSpace = scrollToChangeCurrent * offscreenItems;
|
||||
recyclerViewProxy.requestLayout();
|
||||
}
|
||||
|
||||
public void setTransformClampItemCount(int transformClampItemCount) {
|
||||
this.transformClampItemCount = transformClampItemCount;
|
||||
applyItemTransformToChildren();
|
||||
}
|
||||
|
||||
public void setOrientation(DSVOrientation orientation) {
|
||||
orientationHelper = orientation.createHelper();
|
||||
recyclerViewProxy.removeAllViews();
|
||||
recyclerViewProxy.requestLayout();
|
||||
}
|
||||
|
||||
public void setShouldSlideOnFling(boolean result) {
|
||||
shouldSlideOnFling = result;
|
||||
}
|
||||
|
||||
public void setSlideOnFlingThreshold(int threshold) {
|
||||
flingThreshold = threshold;
|
||||
}
|
||||
|
||||
public int getCurrentPosition() {
|
||||
return currentPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
|
||||
super.onInitializeAccessibilityEvent(event);
|
||||
if (recyclerViewProxy.getChildCount() > 0) {
|
||||
final AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event);
|
||||
record.setFromIndex(getPosition(getFirstChild()));
|
||||
record.setToIndex(getPosition(getLastChild()));
|
||||
}
|
||||
}
|
||||
|
||||
private float getCenterRelativePositionOf(View v, int maxDistance) {
|
||||
float distanceFromCenter = orientationHelper.getDistanceFromCenter(recyclerCenter,
|
||||
getDecoratedLeft(v) + childHalfWidth,
|
||||
getDecoratedTop(v) + childHalfHeight);
|
||||
return Math.min(Math.max(-1f, distanceFromCenter / maxDistance), 1f);
|
||||
}
|
||||
|
||||
private int checkNewOnFlingPositionIsInBounds(int position) {
|
||||
final int itemCount = recyclerViewProxy.getItemCount();
|
||||
//The check is required in case slide through multiple items is turned on
|
||||
if (currentPosition != 0 && position < 0) {
|
||||
//If currentPosition == 0 && position < 0 we forbid scroll to the left,
|
||||
//but if currentPosition != 0 we can slide to the first item
|
||||
return 0;
|
||||
} else if (currentPosition != itemCount - 1 && position >= itemCount) {
|
||||
return itemCount - 1;
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
private int getHowMuchIsLeftToScroll(int dx) {
|
||||
return Direction.fromDelta(dx).applyTo(scrollToChangeCurrent - Math.abs(scrolled));
|
||||
}
|
||||
|
||||
private boolean isAnotherItemCloserThanCurrent() {
|
||||
return Math.abs(scrolled) >= scrollToChangeCurrent * SCROLL_TO_SNAP_TO_ANOTHER_ITEM;
|
||||
}
|
||||
|
||||
public View getFirstChild() {
|
||||
return recyclerViewProxy.getChildAt(0);
|
||||
}
|
||||
|
||||
public View getLastChild() {
|
||||
return recyclerViewProxy.getChildAt(recyclerViewProxy.getChildCount() - 1);
|
||||
}
|
||||
|
||||
public int getExtraLayoutSpace() {
|
||||
return extraLayoutSpace;
|
||||
}
|
||||
|
||||
private void notifyScroll() {
|
||||
float amountToScroll = pendingPosition != NO_POSITION ?
|
||||
Math.abs(scrolled + pendingScroll) :
|
||||
scrollToChangeCurrent;
|
||||
float position = -Math.min(Math.max(-1f, scrolled / amountToScroll), 1f);
|
||||
scrollStateListener.onScroll(position);
|
||||
}
|
||||
|
||||
private boolean isInBounds(int itemPosition) {
|
||||
return itemPosition >= 0 && itemPosition < recyclerViewProxy.getItemCount();
|
||||
}
|
||||
|
||||
private boolean isViewVisible(Point viewCenter, int endBound) {
|
||||
return orientationHelper.isViewVisible(
|
||||
viewCenter, childHalfWidth, childHalfHeight,
|
||||
endBound, extraLayoutSpace);
|
||||
}
|
||||
|
||||
private void checkTargetPosition(RecyclerView.State state, int targetPosition) {
|
||||
if (targetPosition < 0 || targetPosition >= state.getItemCount()) {
|
||||
throw new IllegalArgumentException(String.format(Locale.US,
|
||||
"target position out of bounds: position=%d, itemCount=%d",
|
||||
targetPosition, state.getItemCount()));
|
||||
}
|
||||
}
|
||||
|
||||
protected void setRecyclerViewProxy(RecyclerViewProxy recyclerViewProxy) {
|
||||
this.recyclerViewProxy = recyclerViewProxy;
|
||||
}
|
||||
|
||||
protected void setOrientationHelper(DSVOrientation.Helper orientationHelper) {
|
||||
this.orientationHelper = orientationHelper;
|
||||
}
|
||||
|
||||
private class DiscreteLinearSmoothScroller extends LinearSmoothScroller {
|
||||
|
||||
public DiscreteLinearSmoothScroller(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int calculateDxToMakeVisible(View view, int snapPreference) {
|
||||
return orientationHelper.getPendingDx(-pendingScroll);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int calculateDyToMakeVisible(View view, int snapPreference) {
|
||||
return orientationHelper.getPendingDy(-pendingScroll);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int calculateTimeForScrolling(int dx) {
|
||||
float dist = Math.min(Math.abs(dx), scrollToChangeCurrent);
|
||||
return (int) (Math.max(0.01f, dist / scrollToChangeCurrent) * timeForItemSettle);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PointF computeScrollVectorForPosition(int targetPosition) {
|
||||
return new PointF(
|
||||
orientationHelper.getPendingDx(pendingScroll),
|
||||
orientationHelper.getPendingDy(pendingScroll));
|
||||
}
|
||||
}
|
||||
|
||||
public interface ScrollStateListener {
|
||||
void onIsBoundReachedFlagChange(boolean isBoundReached);
|
||||
|
||||
void onScrollStart();
|
||||
|
||||
void onScrollEnd();
|
||||
|
||||
void onScroll(float currentViewPosition);
|
||||
|
||||
void onCurrentViewFirstLayout();
|
||||
|
||||
void onDataSetChangeChangedPosition();
|
||||
}
|
||||
|
||||
public interface InitialPositionProvider {
|
||||
int getInitialPosition();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
package com.yarolegovich.discretescrollview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.IntRange;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.yarolegovich.discretescrollview.transform.DiscreteScrollItemTransformer;
|
||||
import com.yarolegovich.discretescrollview.util.ScrollListenerAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by yarolegovich on 18.02.2017.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class DiscreteScrollView extends RecyclerView {
|
||||
|
||||
public static final int NO_POSITION = DiscreteScrollLayoutManager.NO_POSITION;
|
||||
|
||||
private static final int DEFAULT_ORIENTATION = DSVOrientation.HORIZONTAL.ordinal();
|
||||
|
||||
private DiscreteScrollLayoutManager layoutManager;
|
||||
|
||||
private List<ScrollStateChangeListener> scrollStateChangeListeners;
|
||||
private List<OnItemChangedListener> onItemChangedListeners;
|
||||
|
||||
private boolean isOverScrollEnabled;
|
||||
|
||||
public DiscreteScrollView(Context context) {
|
||||
super(context);
|
||||
init(null);
|
||||
}
|
||||
|
||||
public DiscreteScrollView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(attrs);
|
||||
}
|
||||
|
||||
public DiscreteScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(attrs);
|
||||
}
|
||||
|
||||
private void init(AttributeSet attrs) {
|
||||
scrollStateChangeListeners = new ArrayList<>();
|
||||
onItemChangedListeners = new ArrayList<>();
|
||||
|
||||
int orientation = DEFAULT_ORIENTATION;
|
||||
if (attrs != null) {
|
||||
TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.DiscreteScrollView);
|
||||
orientation = ta.getInt(R.styleable.DiscreteScrollView_dsv_orientation, DEFAULT_ORIENTATION);
|
||||
ta.recycle();
|
||||
}
|
||||
|
||||
isOverScrollEnabled = getOverScrollMode() != OVER_SCROLL_NEVER;
|
||||
|
||||
layoutManager = new DiscreteScrollLayoutManager(
|
||||
getContext(), new ScrollStateListener(),
|
||||
DSVOrientation.values()[orientation]);
|
||||
setLayoutManager(layoutManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayoutManager(LayoutManager layout) {
|
||||
if (layout instanceof DiscreteScrollLayoutManager) {
|
||||
super.setLayoutManager(layout);
|
||||
} else {
|
||||
throw new IllegalArgumentException(getContext().getString(R.string.dsv_ex_msg_dont_set_lm));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean fling(int velocityX, int velocityY) {
|
||||
boolean isFling = super.fling(velocityX, velocityY);
|
||||
if (isFling) {
|
||||
layoutManager.onFling(velocityX, velocityY);
|
||||
} else {
|
||||
layoutManager.returnToCurrentPosition();
|
||||
}
|
||||
return isFling;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ViewHolder getViewHolder(int position) {
|
||||
View view = layoutManager.findViewByPosition(position);
|
||||
return view != null ? getChildViewHolder(view) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return adapter position of the current item or -1 if nothing is selected
|
||||
*/
|
||||
public int getCurrentItem() {
|
||||
return layoutManager.getCurrentPosition();
|
||||
}
|
||||
|
||||
public void setItemTransformer(DiscreteScrollItemTransformer transformer) {
|
||||
layoutManager.setItemTransformer(transformer);
|
||||
}
|
||||
|
||||
public void setItemTransitionTimeMillis(@IntRange(from = 10) int millis) {
|
||||
layoutManager.setTimeForItemSettle(millis);
|
||||
}
|
||||
|
||||
public void setSlideOnFling(boolean result){
|
||||
layoutManager.setShouldSlideOnFling(result);
|
||||
}
|
||||
|
||||
public void setSlideOnFlingThreshold(int threshold){
|
||||
layoutManager.setSlideOnFlingThreshold(threshold);
|
||||
}
|
||||
|
||||
public void setOrientation(DSVOrientation orientation) {
|
||||
layoutManager.setOrientation(orientation);
|
||||
}
|
||||
|
||||
public void setOffscreenItems(int items) {
|
||||
layoutManager.setOffscreenItems(items);
|
||||
}
|
||||
|
||||
public void setClampTransformProgressAfter(@IntRange(from = 1) int itemCount) {
|
||||
if (itemCount <= 1) {
|
||||
throw new IllegalArgumentException("must be >= 1");
|
||||
}
|
||||
layoutManager.setTransformClampItemCount(itemCount);
|
||||
}
|
||||
|
||||
public void setOverScrollEnabled(boolean overScrollEnabled) {
|
||||
isOverScrollEnabled = overScrollEnabled;
|
||||
setOverScrollMode(OVER_SCROLL_NEVER);
|
||||
}
|
||||
|
||||
public void addScrollStateChangeListener(@NonNull ScrollStateChangeListener<?> scrollStateChangeListener) {
|
||||
scrollStateChangeListeners.add(scrollStateChangeListener);
|
||||
}
|
||||
|
||||
public void addScrollListener(@NonNull ScrollListener<?> scrollListener) {
|
||||
addScrollStateChangeListener(new ScrollListenerAdapter(scrollListener));
|
||||
}
|
||||
|
||||
public void addOnItemChangedListener(@NonNull OnItemChangedListener<?> onItemChangedListener) {
|
||||
onItemChangedListeners.add(onItemChangedListener);
|
||||
}
|
||||
|
||||
public void removeScrollStateChangeListener(@NonNull ScrollStateChangeListener<?> scrollStateChangeListener) {
|
||||
scrollStateChangeListeners.remove(scrollStateChangeListener);
|
||||
}
|
||||
|
||||
public void removeScrollListener(@NonNull ScrollListener<?> scrollListener) {
|
||||
removeScrollStateChangeListener(new ScrollListenerAdapter<>(scrollListener));
|
||||
}
|
||||
|
||||
public void removeItemChangedListener(@NonNull OnItemChangedListener<?> onItemChangedListener) {
|
||||
onItemChangedListeners.remove(onItemChangedListener);
|
||||
}
|
||||
|
||||
private void notifyScrollStart(ViewHolder holder, int current) {
|
||||
for (ScrollStateChangeListener listener : scrollStateChangeListeners) {
|
||||
listener.onScrollStart(holder, current);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyScrollEnd(ViewHolder holder, int current) {
|
||||
for (ScrollStateChangeListener listener : scrollStateChangeListeners) {
|
||||
listener.onScrollEnd(holder, current);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyScroll(float position,
|
||||
int currentIndex, int newIndex,
|
||||
ViewHolder currentHolder, ViewHolder newHolder) {
|
||||
for (ScrollStateChangeListener listener : scrollStateChangeListeners) {
|
||||
listener.onScroll(position, currentIndex, newIndex,
|
||||
currentHolder,
|
||||
newHolder);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyCurrentItemChanged(ViewHolder holder, int current) {
|
||||
for (OnItemChangedListener listener : onItemChangedListeners) {
|
||||
listener.onCurrentItemChanged(holder, current);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyCurrentItemChanged() {
|
||||
if (onItemChangedListeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
int current = layoutManager.getCurrentPosition();
|
||||
ViewHolder currentHolder = getViewHolder(current);
|
||||
notifyCurrentItemChanged(currentHolder, current);
|
||||
}
|
||||
|
||||
private class ScrollStateListener implements DiscreteScrollLayoutManager.ScrollStateListener {
|
||||
|
||||
@Override
|
||||
public void onIsBoundReachedFlagChange(boolean isBoundReached) {
|
||||
if (isOverScrollEnabled) {
|
||||
setOverScrollMode(isBoundReached ? OVER_SCROLL_ALWAYS : OVER_SCROLL_NEVER);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrollStart() {
|
||||
if (scrollStateChangeListeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
int current = layoutManager.getCurrentPosition();
|
||||
ViewHolder holder = getViewHolder(current);
|
||||
if (holder != null) {
|
||||
notifyScrollStart(holder, current);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrollEnd() {
|
||||
if (onItemChangedListeners.isEmpty() && scrollStateChangeListeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
int current = layoutManager.getCurrentPosition();
|
||||
ViewHolder holder = getViewHolder(current);
|
||||
if (holder != null) {
|
||||
notifyScrollEnd(holder, current);
|
||||
notifyCurrentItemChanged(holder, current);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScroll(float currentViewPosition) {
|
||||
if (scrollStateChangeListeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
int currentIndex = getCurrentItem();
|
||||
int newIndex = layoutManager.getNextPosition();
|
||||
if (currentIndex != newIndex) {
|
||||
notifyScroll(currentViewPosition,
|
||||
currentIndex, newIndex,
|
||||
getViewHolder(currentIndex),
|
||||
getViewHolder(newIndex));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentViewFirstLayout() {
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
notifyCurrentItemChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataSetChangeChangedPosition() {
|
||||
notifyCurrentItemChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public interface ScrollStateChangeListener<T extends ViewHolder> {
|
||||
|
||||
void onScrollStart(@NonNull T currentItemHolder, int adapterPosition);
|
||||
|
||||
void onScrollEnd(@NonNull T currentItemHolder, int adapterPosition);
|
||||
|
||||
void onScroll(float scrollPosition,
|
||||
int currentPosition,
|
||||
int newPosition,
|
||||
@Nullable T currentHolder,
|
||||
@Nullable T newCurrent);
|
||||
}
|
||||
|
||||
public interface ScrollListener<T extends ViewHolder> {
|
||||
|
||||
void onScroll(float scrollPosition,
|
||||
int currentPosition, int newPosition,
|
||||
@Nullable T currentHolder,
|
||||
@Nullable T newCurrent);
|
||||
}
|
||||
|
||||
public interface OnItemChangedListener<T extends ViewHolder> {
|
||||
/*
|
||||
* This method will be also triggered when view appears on the screen for the first time.
|
||||
* If data set is empty, viewHolder will be null and adapterPosition will be NO_POSITION
|
||||
*/
|
||||
void onCurrentItemChanged(@Nullable T viewHolder, int adapterPosition);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package com.yarolegovich.discretescrollview;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Created by yarolegovich on 28-Apr-17.
|
||||
*/
|
||||
|
||||
public class InfiniteScrollAdapter<T extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<T>
|
||||
implements DiscreteScrollLayoutManager.InitialPositionProvider {
|
||||
|
||||
private static final int CENTER = Integer.MAX_VALUE / 2;
|
||||
private static final int RESET_BOUND = 100;
|
||||
|
||||
public static <T extends RecyclerView.ViewHolder> InfiniteScrollAdapter<T> wrap(
|
||||
@NonNull RecyclerView.Adapter<T> adapter) {
|
||||
return new InfiniteScrollAdapter<>(adapter);
|
||||
}
|
||||
|
||||
private RecyclerView.Adapter<T> wrapped;
|
||||
private DiscreteScrollLayoutManager layoutManager;
|
||||
|
||||
public InfiniteScrollAdapter(@NonNull RecyclerView.Adapter<T> wrapped) {
|
||||
this.wrapped = wrapped;
|
||||
this.wrapped.registerAdapterDataObserver(new DataSetChangeDelegate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
|
||||
wrapped.onAttachedToRecyclerView(recyclerView);
|
||||
if (recyclerView instanceof DiscreteScrollView) {
|
||||
layoutManager = (DiscreteScrollLayoutManager) recyclerView.getLayoutManager();
|
||||
} else {
|
||||
String msg = recyclerView.getContext().getString(R.string.dsv_ex_msg_adapter_wrong_recycler);
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
|
||||
wrapped.onDetachedFromRecyclerView(recyclerView);
|
||||
layoutManager = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull T onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return wrapped.onCreateViewHolder(parent, viewType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull T holder, int position) {
|
||||
if (isResetRequired(position)) {
|
||||
int resetPosition = CENTER + mapPositionToReal(layoutManager.getCurrentPosition());
|
||||
setPosition(resetPosition);
|
||||
return;
|
||||
}
|
||||
wrapped.onBindViewHolder(holder, mapPositionToReal(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return wrapped.getItemViewType(mapPositionToReal(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return isInfinite() ? Integer.MAX_VALUE : wrapped.getItemCount();
|
||||
}
|
||||
|
||||
public int getRealItemCount() {
|
||||
return wrapped.getItemCount();
|
||||
}
|
||||
|
||||
public int getRealCurrentPosition() {
|
||||
return getRealPosition(layoutManager.getCurrentPosition());
|
||||
}
|
||||
|
||||
public int getRealPosition(int position) {
|
||||
return mapPositionToReal(position);
|
||||
}
|
||||
|
||||
public int getClosestPosition(int position) {
|
||||
ensureValidPosition(position);
|
||||
int adapterCurrent = layoutManager.getCurrentPosition();
|
||||
int current = mapPositionToReal(adapterCurrent);
|
||||
if (position == current) {
|
||||
return adapterCurrent;
|
||||
}
|
||||
int delta = position - current;
|
||||
int target = adapterCurrent + delta;
|
||||
int wraparoundTarget = adapterCurrent + (position > current ?
|
||||
delta - wrapped.getItemCount() :
|
||||
wrapped.getItemCount() + delta);
|
||||
int distance = Math.abs(adapterCurrent - target);
|
||||
int wraparoundDistance = Math.abs(adapterCurrent - wraparoundTarget);
|
||||
if (distance == wraparoundDistance) {
|
||||
//Scroll to the right feels more natural, so prefer it
|
||||
return target > adapterCurrent ? target : wraparoundTarget;
|
||||
} else {
|
||||
return distance < wraparoundDistance ? target : wraparoundTarget;
|
||||
}
|
||||
}
|
||||
|
||||
private int mapPositionToReal(int position) {
|
||||
if (position < CENTER) {
|
||||
int rem = (CENTER - position) % wrapped.getItemCount();
|
||||
return rem == 0 ? 0 : wrapped.getItemCount() - rem;
|
||||
} else {
|
||||
return (position - CENTER) % wrapped.getItemCount();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isResetRequired(int requestedPosition) {
|
||||
return isInfinite()
|
||||
&& (requestedPosition <= RESET_BOUND
|
||||
|| requestedPosition >= (Integer.MAX_VALUE - RESET_BOUND));
|
||||
}
|
||||
|
||||
private void ensureValidPosition(int position) {
|
||||
if (position >= wrapped.getItemCount()) {
|
||||
throw new IndexOutOfBoundsException(String.format(Locale.US,
|
||||
"requested position is outside adapter's bounds: position=%d, size=%d",
|
||||
position, wrapped.getItemCount()));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInfinite() {
|
||||
return wrapped.getItemCount() > 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInitialPosition() {
|
||||
return isInfinite() ? CENTER : 0;
|
||||
}
|
||||
|
||||
private void setPosition(int position) {
|
||||
layoutManager.scrollToPosition(position);
|
||||
}
|
||||
|
||||
//TODO: handle proper data set change notifications
|
||||
private class DataSetChangeDelegate extends RecyclerView.AdapterDataObserver {
|
||||
|
||||
@Override
|
||||
public void onChanged() {
|
||||
setPosition(getInitialPosition());
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemRangeRemoved(int positionStart, int itemCount) {
|
||||
onChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemRangeInserted(int positionStart, int itemCount) {
|
||||
onChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
|
||||
onChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemRangeChanged(int positionStart, int itemCount) {
|
||||
notifyItemRangeChanged(0, getItemCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
|
||||
notifyItemRangeChanged(0, getItemCount(), payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package com.yarolegovich.discretescrollview;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
/**
|
||||
* Created by yarolegovich on 10/25/17.
|
||||
*/
|
||||
public class RecyclerViewProxy {
|
||||
|
||||
private RecyclerView.LayoutManager layoutManager;
|
||||
|
||||
public RecyclerViewProxy(@NonNull RecyclerView.LayoutManager layoutManager) {
|
||||
this.layoutManager = layoutManager;
|
||||
}
|
||||
|
||||
public void attachView(View view) {
|
||||
layoutManager.attachView(view);
|
||||
}
|
||||
|
||||
public void detachView(View view) {
|
||||
layoutManager.detachView(view);
|
||||
}
|
||||
|
||||
public void detachAndScrapView(View view, RecyclerView.Recycler recycler) {
|
||||
layoutManager.detachAndScrapView(view, recycler);
|
||||
}
|
||||
|
||||
public void detachAndScrapAttachedViews(RecyclerView.Recycler recycler) {
|
||||
layoutManager.detachAndScrapAttachedViews(recycler);
|
||||
}
|
||||
|
||||
public void recycleView(View view, RecyclerView.Recycler recycler) {
|
||||
recycler.recycleView(view);
|
||||
}
|
||||
|
||||
public void removeAndRecycleAllViews(RecyclerView.Recycler recycler) {
|
||||
layoutManager.removeAndRecycleAllViews(recycler);
|
||||
}
|
||||
|
||||
public int getChildCount() {
|
||||
return layoutManager.getChildCount();
|
||||
}
|
||||
|
||||
public int getItemCount() {
|
||||
return layoutManager.getItemCount();
|
||||
}
|
||||
|
||||
public View getMeasuredChildForAdapterPosition(int position, RecyclerView.Recycler recycler) {
|
||||
View view = recycler.getViewForPosition(position);
|
||||
layoutManager.addView(view);
|
||||
layoutManager.measureChildWithMargins(view, 0, 0);
|
||||
return view;
|
||||
}
|
||||
|
||||
public void layoutDecoratedWithMargins(View v, int left, int top, int right, int bottom) {
|
||||
layoutManager.layoutDecoratedWithMargins(v, left, top, right, bottom);
|
||||
}
|
||||
|
||||
public View getChildAt(int index) {
|
||||
return layoutManager.getChildAt(index);
|
||||
}
|
||||
|
||||
public int getPosition(View view) {
|
||||
return layoutManager.getPosition(view);
|
||||
}
|
||||
|
||||
public int getMeasuredWidthWithMargin(View child) {
|
||||
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) child.getLayoutParams();
|
||||
return layoutManager.getDecoratedMeasuredWidth(child) + lp.leftMargin + lp.rightMargin;
|
||||
}
|
||||
|
||||
public int getMeasuredHeightWithMargin(View child) {
|
||||
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) child.getLayoutParams();
|
||||
return layoutManager.getDecoratedMeasuredHeight(child) + lp.topMargin + lp.bottomMargin;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return layoutManager.getWidth();
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return layoutManager.getHeight();
|
||||
}
|
||||
|
||||
public void offsetChildrenHorizontal(int amount) {
|
||||
layoutManager.offsetChildrenHorizontal(amount);
|
||||
}
|
||||
|
||||
public void offsetChildrenVertical(int amount) {
|
||||
layoutManager.offsetChildrenVertical(amount);
|
||||
}
|
||||
|
||||
public void requestLayout() {
|
||||
layoutManager.requestLayout();
|
||||
}
|
||||
|
||||
public void startSmoothScroll(RecyclerView.SmoothScroller smoothScroller) {
|
||||
layoutManager.startSmoothScroll(smoothScroller);
|
||||
}
|
||||
|
||||
public void removeAllViews() {
|
||||
layoutManager.removeAllViews();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.yarolegovich.discretescrollview.transform;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* Created by yarolegovich on 02.03.2017.
|
||||
*/
|
||||
|
||||
public interface DiscreteScrollItemTransformer {
|
||||
void transformItem(View item, float position);
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.yarolegovich.discretescrollview.transform;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Created by yarolegovich on 03.03.2017.
|
||||
*/
|
||||
|
||||
public class Pivot {
|
||||
|
||||
public static final int AXIS_X = 0;
|
||||
public static final int AXIS_Y = 1;
|
||||
|
||||
private static final int PIVOT_CENTER = -1;
|
||||
private static final int PIVOT_MAX = -2;
|
||||
|
||||
private int axis;
|
||||
private int pivotPoint;
|
||||
|
||||
public Pivot(@Axis int axis, int pivotPoint) {
|
||||
this.axis = axis;
|
||||
this.pivotPoint = pivotPoint;
|
||||
}
|
||||
|
||||
public void setOn(View view) {
|
||||
if (axis == AXIS_X) {
|
||||
switch (pivotPoint) {
|
||||
case PIVOT_CENTER:
|
||||
view.setPivotX(view.getWidth() * 0.5f);
|
||||
break;
|
||||
case PIVOT_MAX:
|
||||
view.setPivotX(view.getWidth());
|
||||
break;
|
||||
default:
|
||||
view.setPivotX(pivotPoint);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (axis == AXIS_Y) {
|
||||
switch (pivotPoint) {
|
||||
case PIVOT_CENTER:
|
||||
view.setPivotY(view.getHeight() * 0.5f);
|
||||
break;
|
||||
case PIVOT_MAX:
|
||||
view.setPivotY(view.getHeight());
|
||||
break;
|
||||
default:
|
||||
view.setPivotY(pivotPoint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Axis
|
||||
public int getAxis() {
|
||||
return axis;
|
||||
}
|
||||
|
||||
public enum X {
|
||||
LEFT {
|
||||
@Override
|
||||
public Pivot create() {
|
||||
return new Pivot(AXIS_X, 0);
|
||||
}
|
||||
},
|
||||
CENTER {
|
||||
@Override
|
||||
public Pivot create() {
|
||||
return new Pivot(AXIS_X, PIVOT_CENTER);
|
||||
}
|
||||
},
|
||||
RIGHT {
|
||||
@Override
|
||||
public Pivot create() {
|
||||
return new Pivot(AXIS_X, PIVOT_MAX);
|
||||
}
|
||||
};
|
||||
|
||||
public abstract Pivot create();
|
||||
}
|
||||
|
||||
public enum Y {
|
||||
TOP {
|
||||
@Override
|
||||
public Pivot create() {
|
||||
return new Pivot(AXIS_Y, 0);
|
||||
}
|
||||
},
|
||||
CENTER {
|
||||
@Override
|
||||
public Pivot create() {
|
||||
return new Pivot(AXIS_Y, PIVOT_CENTER);
|
||||
}
|
||||
},
|
||||
BOTTOM {
|
||||
@Override
|
||||
public Pivot create() {
|
||||
return new Pivot(AXIS_Y, PIVOT_MAX);
|
||||
}
|
||||
};
|
||||
|
||||
public abstract Pivot create();
|
||||
}
|
||||
|
||||
@IntDef({AXIS_X, AXIS_Y})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Axis{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.yarolegovich.discretescrollview.transform;
|
||||
|
||||
import android.view.View;
|
||||
import androidx.annotation.FloatRange;
|
||||
|
||||
/**
|
||||
* Created by yarolegovich on 03.03.2017.
|
||||
*/
|
||||
public class ScaleTransformer implements DiscreteScrollItemTransformer {
|
||||
|
||||
private Pivot pivotX;
|
||||
private Pivot pivotY;
|
||||
private float minScale;
|
||||
private float maxMinDiff;
|
||||
|
||||
public ScaleTransformer() {
|
||||
pivotX = Pivot.X.CENTER.create();
|
||||
pivotY = Pivot.Y.CENTER.create();
|
||||
minScale = 0.8f;
|
||||
maxMinDiff = 0.2f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transformItem(View item, float position) {
|
||||
pivotX.setOn(item);
|
||||
pivotY.setOn(item);
|
||||
float closenessToCenter = 1f - Math.abs(position);
|
||||
float scale = minScale + maxMinDiff * closenessToCenter;
|
||||
item.setScaleX(scale);
|
||||
item.setScaleY(scale);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private ScaleTransformer transformer;
|
||||
private float maxScale;
|
||||
|
||||
public Builder() {
|
||||
transformer = new ScaleTransformer();
|
||||
maxScale = 1f;
|
||||
}
|
||||
|
||||
public Builder setMinScale(@FloatRange(from = 0.01) float scale) {
|
||||
transformer.minScale = scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setMaxScale(@FloatRange(from = 0.01) float scale) {
|
||||
maxScale = scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPivotX(Pivot.X pivotX) {
|
||||
return setPivotX(pivotX.create());
|
||||
}
|
||||
|
||||
public Builder setPivotX(Pivot pivot) {
|
||||
assertAxis(pivot, Pivot.AXIS_X);
|
||||
transformer.pivotX = pivot;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPivotY(Pivot.Y pivotY) {
|
||||
return setPivotY(pivotY.create());
|
||||
}
|
||||
|
||||
public Builder setPivotY(Pivot pivot) {
|
||||
assertAxis(pivot, Pivot.AXIS_Y);
|
||||
transformer.pivotY = pivot;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ScaleTransformer build() {
|
||||
transformer.maxMinDiff = maxScale - transformer.minScale;
|
||||
return transformer;
|
||||
}
|
||||
|
||||
private void assertAxis(Pivot pivot, @Pivot.Axis int axis) {
|
||||
if (pivot.getAxis() != axis) {
|
||||
throw new IllegalArgumentException("You passed a Pivot for wrong axis.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.yarolegovich.discretescrollview.util;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.yarolegovich.discretescrollview.DiscreteScrollView;
|
||||
|
||||
/**
|
||||
* Created by yarolegovich on 16.03.2017.
|
||||
*/
|
||||
public class ScrollListenerAdapter<T extends RecyclerView.ViewHolder> implements DiscreteScrollView.ScrollStateChangeListener<T> {
|
||||
|
||||
private DiscreteScrollView.ScrollListener<T> adaptee;
|
||||
|
||||
public ScrollListenerAdapter(@NonNull DiscreteScrollView.ScrollListener<T> adaptee) {
|
||||
this.adaptee = adaptee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrollStart(@NonNull T currentItemHolder, int adapterPosition) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrollEnd(@NonNull T currentItemHolder, int adapterPosition) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScroll(float scrollPosition,
|
||||
int currentIndex, int newIndex,
|
||||
@Nullable T currentHolder, @Nullable T newCurrentHolder) {
|
||||
adaptee.onScroll(scrollPosition, currentIndex, newIndex, currentHolder, newCurrentHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof ScrollListenerAdapter) {
|
||||
return adaptee.equals(((ScrollListenerAdapter) obj).adaptee);
|
||||
} else {
|
||||
return super.equals(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
9
libraries/card-library/src/main/res/values/attr.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="DiscreteScrollView">
|
||||
<attr name="dsv_orientation" format="enum">
|
||||
<enum name="horizontal" value="0" />
|
||||
<enum name="vertical" value="1" />
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
4
libraries/card-library/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<resources>
|
||||
<string name="dsv_ex_msg_dont_set_lm">You should not set LayoutManager on DiscreteScrollView.class instance. Library uses a special one. Just don\'t call the method.</string>
|
||||
<string name="dsv_ex_msg_adapter_wrong_recycler">InfiniteScrollAdapter is supposed to work only with DiscreteScrollView</string>
|
||||
</resources>
|
||||
@@ -7,6 +7,7 @@ import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.os.Trace;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.animation.Interpolator;
|
||||
@@ -319,7 +320,9 @@ public class AMapNaviViewWrapper implements IMogoMapView,
|
||||
@Override
|
||||
public void onLockMap( boolean isLock ) {
|
||||
Logger.d( TAG, "lock status = %s", isLock );
|
||||
Trace.beginSection( "timer.onCameraChangeFinish" );
|
||||
MogoMapListenerHandler.getInstance().onLockMap( isLock );
|
||||
Trace.endSection();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -418,7 +421,6 @@ public class AMapNaviViewWrapper implements IMogoMapView,
|
||||
}
|
||||
|
||||
|
||||
|
||||
private boolean checkAMapView() {
|
||||
if ( mMapView == null ) {
|
||||
Logger.e( TAG, "高德mapView实例为空,请检查" );
|
||||
@@ -549,17 +551,19 @@ public class AMapNaviViewWrapper implements IMogoMapView,
|
||||
@Override
|
||||
public void onCameraChangeFinish( CameraPosition cameraPosition ) {
|
||||
if ( cameraPosition != null ) {
|
||||
MogoMapListenerHandler.getInstance()
|
||||
.onMapChanged( ObjectUtils.fromAMap( cameraPosition.target ), cameraPosition.zoom,
|
||||
cameraPosition.tilt, cameraPosition.bearing );
|
||||
Trace.beginSection( "timer.onCameraChangeFinish" );
|
||||
MogoMapListenerHandler.getInstance().onMapChanged( ObjectUtils.fromAMap( cameraPosition.target ),
|
||||
cameraPosition.zoom,
|
||||
cameraPosition.tilt,
|
||||
cameraPosition.bearing );
|
||||
Trace.endSection();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MogoLatLng getCameraNorthEastPosition() {
|
||||
try {
|
||||
return ObjectUtils.fromAMap(
|
||||
mMapView.getMap().getProjection().getVisibleRegion().latLngBounds.northeast );
|
||||
return ObjectUtils.fromAMap( mMapView.getMap().getProjection().getVisibleRegion().latLngBounds.northeast );
|
||||
} catch ( Exception e ) {
|
||||
|
||||
}
|
||||
@@ -569,8 +573,7 @@ public class AMapNaviViewWrapper implements IMogoMapView,
|
||||
@Override
|
||||
public MogoLatLng getCameraSouthWestPosition() {
|
||||
try {
|
||||
return ObjectUtils.fromAMap(
|
||||
mMapView.getMap().getProjection().getVisibleRegion().latLngBounds.southwest );
|
||||
return ObjectUtils.fromAMap( mMapView.getMap().getProjection().getVisibleRegion().latLngBounds.southwest );
|
||||
} catch ( Exception e ) {
|
||||
|
||||
}
|
||||
|
||||
@@ -6,16 +6,21 @@ import com.amap.api.maps.AMap;
|
||||
import com.amap.api.maps.CameraUpdateFactory;
|
||||
import com.amap.api.maps.model.Marker;
|
||||
import com.amap.api.maps.model.MarkerOptions;
|
||||
import com.amap.api.maps.model.Polyline;
|
||||
import com.amap.api.maps.model.PolylineOptions;
|
||||
import com.amap.api.navi.AMapNaviView;
|
||||
import com.mogo.map.IMogoMap;
|
||||
import com.mogo.map.IMogoUiSettings;
|
||||
import com.mogo.map.impl.amap.marker.AMapInfoWindowAdapter;
|
||||
import com.mogo.map.impl.amap.marker.AMapMarkerWrapper;
|
||||
import com.mogo.map.impl.amap.overlay.AMapPolylineWrapper;
|
||||
import com.mogo.map.impl.amap.uicontroller.AMapUIController;
|
||||
import com.mogo.map.impl.amap.utils.ObjectUtils;
|
||||
import com.mogo.map.marker.IMogoMarker;
|
||||
import com.mogo.map.marker.MogoMarkerOptions;
|
||||
import com.mogo.map.marker.MogoMarkersHandler;
|
||||
import com.mogo.map.overlay.IMogoPolyline;
|
||||
import com.mogo.map.overlay.MogoPolylineOptions;
|
||||
import com.mogo.map.uicontroller.IMogoMapUIController;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
|
||||
@@ -219,6 +224,19 @@ public class AMapWrapper implements IMogoMap {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMogoPolyline addPolyline( MogoPolylineOptions options ) {
|
||||
if ( checkAMap() ) {
|
||||
PolylineOptions polylineOptions = ObjectUtils.fromMogo( options );
|
||||
if ( polylineOptions == null ) {
|
||||
return null;
|
||||
}
|
||||
Polyline polyline = mAMap.addPolyline( polylineOptions );
|
||||
return new AMapPolylineWrapper( polyline, options );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean checkAMap() {
|
||||
if ( mAMap == null ) {
|
||||
Logger.e( TAG, "高德map实例为空,请检查" );
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.mogo.map.impl.amap.location;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Trace;
|
||||
|
||||
import com.amap.api.location.AMapLocation;
|
||||
import com.amap.api.location.AMapLocationClient;
|
||||
@@ -139,6 +140,7 @@ public class ALocationClient implements IMogoLocationClient {
|
||||
aMapLocation.getLongitude() == 0.0D ) {
|
||||
return;
|
||||
}
|
||||
Trace.beginSection("timer.onLocationChanged");
|
||||
mLastLocation = ObjectUtils.fromAMap( aMapLocation );
|
||||
synchronized ( sListeners ) {
|
||||
Iterator< IMogoLocationListener > listenerIterator = sListeners.iterator();
|
||||
@@ -146,6 +148,7 @@ public class ALocationClient implements IMogoLocationClient {
|
||||
listenerIterator.next().onLocationChanged( mLastLocation.clone() );
|
||||
}
|
||||
}
|
||||
Trace.endSection();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -294,7 +294,13 @@ public class AMapMarkerWrapper implements IMogoMarker, Observer {
|
||||
|
||||
@Override
|
||||
public String getOwner() {
|
||||
return this.mOwner == null ? mMogoMarkerOptions.getOwner() : mOwner;
|
||||
if ( mOwner != null ) {
|
||||
return mOwner;
|
||||
}
|
||||
if ( mMogoMarkerOptions != null ) {
|
||||
return mMogoMarkerOptions.getOwner();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.mogo.map.impl.amap.navi;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Trace;
|
||||
|
||||
import com.amap.api.maps.model.Polyline;
|
||||
import com.amap.api.navi.AMapNavi;
|
||||
@@ -178,8 +179,10 @@ public class NaviListenerAdapter extends AMapNaviListenerAdapter {
|
||||
|
||||
@Override
|
||||
public void onNaviInfoUpdate( NaviInfo naviInfo ) {
|
||||
Trace.beginSection( "NaviListenerAdapter.onNaviInfoUpdate" );
|
||||
MogoNaviListenerHandler.getInstance().onNaviInfoUpdate( ObjectUtils.fromAMap( mContext, naviInfo ) );
|
||||
mNaviOverlayHelper.handleNaviInfoUpdate( naviInfo );
|
||||
Trace.endSection();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -201,8 +204,10 @@ public class NaviListenerAdapter extends AMapNaviListenerAdapter {
|
||||
|
||||
@Override
|
||||
public void onLocationChange( AMapNaviLocation aMapNaviLocation ) {
|
||||
Trace.beginSection( "NaviListenerAdapter.onLocationChange" );
|
||||
super.onLocationChange( aMapNaviLocation );
|
||||
mNaviOverlayHelper.handlePassedLocation( aMapNaviLocation );
|
||||
Trace.endSection();
|
||||
}
|
||||
|
||||
public void stopNavi() {
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
package com.mogo.map.impl.amap.overlay;
|
||||
|
||||
import com.amap.api.maps.model.LatLng;
|
||||
import com.amap.api.maps.model.Polyline;
|
||||
import com.amap.api.maps.model.PolylineOptions;
|
||||
import com.mogo.map.MogoLatLng;
|
||||
import com.mogo.map.impl.amap.utils.ObjectUtils;
|
||||
import com.mogo.map.overlay.IMogoPolyline;
|
||||
import com.mogo.map.overlay.MogoPolylineOptions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-03-10
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class AMapPolylineWrapper implements IMogoPolyline {
|
||||
|
||||
private Polyline mPolyline;
|
||||
private MogoPolylineOptions mOptions;
|
||||
private boolean mIsDestroyed = false;
|
||||
|
||||
public AMapPolylineWrapper( Polyline mPolyline,
|
||||
MogoPolylineOptions mOptions ) {
|
||||
this.mPolyline = mPolyline;
|
||||
this.mOptions = mOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if ( mPolyline != null ) {
|
||||
mPolyline.remove();
|
||||
}
|
||||
mIsDestroyed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
if ( mPolyline != null ) {
|
||||
return mPolyline.getId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPoints( List< MogoLatLng > lonLats ) {
|
||||
if ( lonLats == null || lonLats.isEmpty() ) {
|
||||
mPolyline.setPoints( new ArrayList< LatLng >() );
|
||||
return;
|
||||
}
|
||||
ArrayList< LatLng > points = new ArrayList<>();
|
||||
for ( MogoLatLng lonLat : lonLats ) {
|
||||
LatLng latLng = ObjectUtils.fromMogo2( lonLat );
|
||||
if ( latLng == null ) {
|
||||
continue;
|
||||
}
|
||||
points.add( latLng );
|
||||
}
|
||||
mPolyline.setPoints( points );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List< MogoLatLng > getPoints() {
|
||||
if ( mPolyline == null ) {
|
||||
return null;
|
||||
}
|
||||
ArrayList< MogoLatLng > lonLats = new ArrayList<>();
|
||||
List< LatLng > points = mPolyline.getPoints();
|
||||
if ( points != null ) {
|
||||
for ( LatLng latLng : points ) {
|
||||
MogoLatLng lonLat = ObjectUtils.fromAMap( latLng );
|
||||
if ( lonLat == null ) {
|
||||
continue;
|
||||
}
|
||||
lonLats.add( lonLat );
|
||||
}
|
||||
}
|
||||
return lonLats;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGeodesic( boolean draw ) {
|
||||
if ( mPolyline != null ) {
|
||||
mPolyline.setGeodesic( draw );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGeodesic() {
|
||||
return mPolyline == null ? false : mPolyline.isGeodesic();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDottedLine( boolean dottedLine ) {
|
||||
if ( mPolyline != null ) {
|
||||
mPolyline.setDottedLine( dottedLine );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDottedLine() {
|
||||
return mPolyline == null ? false : mPolyline.isDottedLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWidth( float width ) {
|
||||
if ( mPolyline != null ) {
|
||||
mPolyline.setWidth( width );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getWidth() {
|
||||
if ( mPolyline != null ) {
|
||||
return mPolyline.getWidth();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColor( int color ) {
|
||||
if ( mPolyline != null ) {
|
||||
mPolyline.setColor( color );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColor() {
|
||||
if ( mPolyline != null ) {
|
||||
return mPolyline.getColor();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZIndex( float zIndex ) {
|
||||
if ( mPolyline != null ) {
|
||||
mPolyline.setZIndex( zIndex );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getZIndex() {
|
||||
if ( mPolyline != null ) {
|
||||
return mPolyline.getZIndex();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible( boolean visible ) {
|
||||
if ( mPolyline != null ) {
|
||||
mPolyline.setVisible( visible );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
if ( mPolyline != null ) {
|
||||
return mPolyline.isVisible();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransparency( float transparency ) {
|
||||
if ( mPolyline != null ) {
|
||||
mPolyline.setTransparency( transparency );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOption( MogoPolylineOptions option ) {
|
||||
PolylineOptions target = ObjectUtils.fromMogo( option );
|
||||
if ( target == null ) {
|
||||
return;
|
||||
}
|
||||
mOptions = option;
|
||||
if ( mPolyline != null ) {
|
||||
mPolyline.setOptions( target );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDestroyed() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import com.amap.api.maps.model.BitmapDescriptorFactory;
|
||||
import com.amap.api.maps.model.LatLng;
|
||||
import com.amap.api.maps.model.MarkerOptions;
|
||||
import com.amap.api.maps.model.Poi;
|
||||
import com.amap.api.maps.model.PolylineOptions;
|
||||
import com.amap.api.navi.model.AMapCongestionLink;
|
||||
import com.amap.api.navi.model.AMapNaviTrafficFacilityInfo;
|
||||
import com.amap.api.navi.model.AimLessModeCongestionInfo;
|
||||
@@ -46,6 +47,7 @@ import com.mogo.map.navi.MogoCongestionLink;
|
||||
import com.mogo.map.navi.MogoNaviInfo;
|
||||
import com.mogo.map.navi.MogoNaviListenerHandler;
|
||||
import com.mogo.map.navi.MogoTraffic;
|
||||
import com.mogo.map.overlay.MogoPolylineOptions;
|
||||
import com.mogo.map.search.geo.MogoAoiItem;
|
||||
import com.mogo.map.search.geo.MogoBusinessArea;
|
||||
import com.mogo.map.search.geo.MogoCrossroad;
|
||||
@@ -704,4 +706,31 @@ public class ObjectUtils {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PolylineOptions fromMogo( MogoPolylineOptions options ) {
|
||||
if ( options == null ) {
|
||||
return null;
|
||||
}
|
||||
PolylineOptions target = new PolylineOptions();
|
||||
if ( options.getPoints() != null ) {
|
||||
List< LatLng > points = new ArrayList<>();
|
||||
for ( MogoLatLng point : options.getPoints() ) {
|
||||
points.add( fromMogo2( point ) );
|
||||
}
|
||||
target.addAll( points );
|
||||
}
|
||||
target.width( options.getWidth() );
|
||||
target.color( options.getColor() );
|
||||
target.zIndex( options.getWidth() );
|
||||
target.visible( options.isVisible() );
|
||||
target.geodesic( options.isGeodesic() );
|
||||
target.setDottedLine( options.isDottedLine() );
|
||||
target.useGradient( options.isGradient() );
|
||||
target.transparency( options.getTransparency() );
|
||||
target.aboveMaskLayer( options.isAboveMaskLayer() );
|
||||
target.lineCapType( PolylineOptions.LineCapType.LineCapRound );
|
||||
target.lineJoinType( PolylineOptions.LineJoinType.LineJoinRound );
|
||||
target.setDottedLineType( PolylineOptions.DOTTEDLINE_TYPE_CIRCLE );
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.mogo.map;
|
||||
|
||||
import com.mogo.map.marker.IMogoMarker;
|
||||
import com.mogo.map.marker.MogoMarkerOptions;
|
||||
import com.mogo.map.overlay.IMogoPolyline;
|
||||
import com.mogo.map.overlay.MogoPolylineOptions;
|
||||
import com.mogo.map.uicontroller.IMogoMapUIController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -127,4 +129,12 @@ public interface IMogoMap {
|
||||
* @return
|
||||
*/
|
||||
float getZoomLevel();
|
||||
|
||||
/**
|
||||
* 添加线段
|
||||
*
|
||||
* @param options
|
||||
* @return
|
||||
*/
|
||||
IMogoPolyline addPolyline( MogoPolylineOptions options );
|
||||
}
|
||||
|
||||
@@ -54,63 +54,49 @@ public class MogoMapListenerHandler implements IMogoMapListener, IMogoMapListene
|
||||
@Override
|
||||
public void onMapLoaded() {
|
||||
if ( mDelegateListener != null ) {
|
||||
synchronized ( mDelegateListener ) {
|
||||
mDelegateListener.onMapLoaded();
|
||||
}
|
||||
mDelegateListener.onMapLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTouch( MotionEvent motionEvent ) {
|
||||
if ( mDelegateListener != null ) {
|
||||
synchronized ( mDelegateListener ) {
|
||||
mDelegateListener.onTouch( motionEvent );
|
||||
}
|
||||
mDelegateListener.onTouch( motionEvent );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPOIClick( MogoPoi poi ) {
|
||||
if ( mDelegateListener != null ) {
|
||||
synchronized ( mDelegateListener ) {
|
||||
mDelegateListener.onPOIClick( poi );
|
||||
}
|
||||
mDelegateListener.onPOIClick( poi );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapClick( MogoLatLng latLng ) {
|
||||
if ( mDelegateListener != null ) {
|
||||
synchronized ( mDelegateListener ) {
|
||||
mDelegateListener.onMapClick( latLng );
|
||||
}
|
||||
mDelegateListener.onMapClick( latLng );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLockMap( boolean isLock ) {
|
||||
if ( mDelegateListener != null ) {
|
||||
synchronized ( mDelegateListener ) {
|
||||
mDelegateListener.onLockMap( isLock );
|
||||
}
|
||||
mDelegateListener.onLockMap( isLock );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapModeChanged( EnumMapUI ui ) {
|
||||
if ( mDelegateListener != null ) {
|
||||
synchronized ( mDelegateListener ) {
|
||||
mDelegateListener.onMapModeChanged( ui );
|
||||
}
|
||||
mDelegateListener.onMapModeChanged( ui );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapChanged( MogoLatLng location, float zoom, float tilt, float bearing ) {
|
||||
if ( mDelegateListener != null ) {
|
||||
synchronized ( mDelegateListener ) {
|
||||
mDelegateListener.onMapChanged( location, zoom, tilt, bearing );
|
||||
}
|
||||
mDelegateListener.onMapChanged( location, zoom, tilt, bearing );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.mogo.map.overlay;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-03-10
|
||||
* <p>
|
||||
* 覆盖物
|
||||
*/
|
||||
public interface IMogoOverlayManager {
|
||||
|
||||
/**
|
||||
* 绘制线段
|
||||
*
|
||||
* @param options
|
||||
* @return
|
||||
*/
|
||||
IMogoPolyline addPolyline( MogoPolylineOptions options );
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.mogo.map.overlay;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
|
||||
import com.mogo.map.IDestroyable;
|
||||
import com.mogo.map.MogoLatLng;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-03-10
|
||||
* <p>
|
||||
* 线段
|
||||
*/
|
||||
public interface IMogoPolyline extends IDestroyable {
|
||||
|
||||
|
||||
/**
|
||||
* 是否已经销毁
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isDestroyed();
|
||||
|
||||
/**
|
||||
* 移除
|
||||
*/
|
||||
void remove();
|
||||
|
||||
/**
|
||||
* 获取ID
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* 设置绘制点数据
|
||||
*
|
||||
* @param lonLats
|
||||
*/
|
||||
void setPoints( List< MogoLatLng > lonLats );
|
||||
|
||||
/**
|
||||
* 获取点
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List< MogoLatLng > getPoints();
|
||||
|
||||
/**
|
||||
* 测地线
|
||||
*
|
||||
* @param draw
|
||||
*/
|
||||
void setGeodesic( boolean draw );
|
||||
|
||||
/**
|
||||
* 是否设置了测地线
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isGeodesic();
|
||||
|
||||
/**
|
||||
* 虚线
|
||||
*
|
||||
* @param dottedLine
|
||||
*/
|
||||
void setDottedLine( boolean dottedLine );
|
||||
|
||||
/**
|
||||
* 是否是虚线
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isDottedLine();
|
||||
|
||||
/**
|
||||
* 设置线宽
|
||||
*
|
||||
* @param width
|
||||
*/
|
||||
void setWidth( float width );
|
||||
|
||||
/**
|
||||
* 获取线宽
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
float getWidth();
|
||||
|
||||
/**
|
||||
* 设置线条颜色
|
||||
*
|
||||
* @param color
|
||||
*/
|
||||
void setColor( @ColorInt int color );
|
||||
|
||||
/**
|
||||
* 获取线条颜色
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@ColorInt
|
||||
int getColor();
|
||||
|
||||
/**
|
||||
* 设置Z轴
|
||||
*/
|
||||
void setZIndex( float zIndex );
|
||||
|
||||
/**
|
||||
* 获取Z轴
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
float getZIndex();
|
||||
|
||||
/**
|
||||
* 设置显示/隐藏
|
||||
*/
|
||||
void setVisible( boolean visible );
|
||||
|
||||
/**
|
||||
* 是否可见
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isVisible();
|
||||
|
||||
/**
|
||||
* 设置透明度
|
||||
*
|
||||
* @param transparency
|
||||
*/
|
||||
void setTransparency( float transparency );
|
||||
|
||||
/**
|
||||
* 设置配置项
|
||||
*/
|
||||
void setOption( MogoPolylineOptions option );
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
package com.mogo.map.overlay;
|
||||
|
||||
import android.graphics.Color;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
|
||||
import com.mogo.map.MogoLatLng;
|
||||
import com.mogo.map.location.MogoLocation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-03-10
|
||||
* <p>
|
||||
* 线段属性
|
||||
*/
|
||||
public class MogoPolylineOptions {
|
||||
|
||||
private List< MogoLatLng > mPoints;
|
||||
private float mWidth = 10.0F;
|
||||
private int mColor = Color.BLACK;
|
||||
private float mZIndex = 0.0F;
|
||||
private boolean mIsVisible = true;
|
||||
private boolean mIsGeodesic = false;
|
||||
private boolean mIsDottedLine = false;
|
||||
private boolean mIsGradient = false;
|
||||
private float mTransparency = 1.0F;
|
||||
private boolean mIsAboveMaskLayer = false;
|
||||
private boolean mIsPointsUpdated = false;
|
||||
|
||||
public MogoPolylineOptions() {
|
||||
this.mPoints = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置顶点
|
||||
*
|
||||
* @param points
|
||||
* @return
|
||||
*/
|
||||
public MogoPolylineOptions points( List< MogoLatLng > points ) {
|
||||
this.mPoints.clear();
|
||||
this.mPoints.addAll( points );
|
||||
this.mIsPointsUpdated = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加顶点到集合最后
|
||||
*
|
||||
* @param points
|
||||
* @return
|
||||
*/
|
||||
public MogoPolylineOptions add( MogoLatLng... points ) {
|
||||
if ( points != null ) {
|
||||
this.mPoints.addAll( Arrays.asList( points ) );
|
||||
this.mIsPointsUpdated = true;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public MogoPolylineOptions add( double lon, double lat ) {
|
||||
this.mPoints.add( new MogoLatLng( lat, lon ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
public MogoPolylineOptions add( MogoLocation location ) {
|
||||
if ( location != null ) {
|
||||
this.mPoints.add( new MogoLatLng( location.getLatitude(), location.getLongitude() ) );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置线宽
|
||||
*/
|
||||
public MogoPolylineOptions width( float width ) {
|
||||
this.mWidth = width;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置线的颜色
|
||||
*
|
||||
* @param color
|
||||
* @return
|
||||
*/
|
||||
public MogoPolylineOptions color( @ColorInt int color ) {
|
||||
this.mColor = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置Z轴的值
|
||||
*
|
||||
* @param zIndex
|
||||
* @return
|
||||
*/
|
||||
public MogoPolylineOptions zIndex( float zIndex ) {
|
||||
this.mZIndex = zIndex;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否可见
|
||||
*
|
||||
* @param isVisible
|
||||
* @return
|
||||
*/
|
||||
public MogoPolylineOptions visible( boolean isVisible ) {
|
||||
this.mIsVisible = isVisible;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否绘制测地线
|
||||
*
|
||||
* @param isGeodesic
|
||||
* @return
|
||||
*/
|
||||
public MogoPolylineOptions geodesic( boolean isGeodesic ) {
|
||||
this.mIsGeodesic = isGeodesic;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是虚线
|
||||
*
|
||||
* @param isDottedLine
|
||||
* @return
|
||||
*/
|
||||
public MogoPolylineOptions dottedLine( boolean isDottedLine ) {
|
||||
this.mIsDottedLine = isDottedLine;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否使用渐变色
|
||||
*
|
||||
* @param isGradient
|
||||
* @return
|
||||
*/
|
||||
public MogoPolylineOptions useGradient( boolean isGradient ) {
|
||||
this.mIsGradient = isGradient;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置透明度
|
||||
*
|
||||
* @param transparency
|
||||
* @return
|
||||
*/
|
||||
public MogoPolylineOptions transparency( float transparency ) {
|
||||
this.mTransparency = transparency;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isAboveMaskLayer
|
||||
* @return
|
||||
*/
|
||||
public MogoPolylineOptions aboveMaskLayer( boolean isAboveMaskLayer ) {
|
||||
this.mIsAboveMaskLayer = isAboveMaskLayer;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List< MogoLatLng > getPoints() {
|
||||
return mPoints;
|
||||
}
|
||||
|
||||
public float getWidth() {
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return mColor;
|
||||
}
|
||||
|
||||
public float getZIndex() {
|
||||
return mZIndex;
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return mIsVisible;
|
||||
}
|
||||
|
||||
public boolean isGeodesic() {
|
||||
return mIsGeodesic;
|
||||
}
|
||||
|
||||
public boolean isDottedLine() {
|
||||
return mIsDottedLine;
|
||||
}
|
||||
|
||||
public boolean isGradient() {
|
||||
return mIsGradient;
|
||||
}
|
||||
|
||||
public float getTransparency() {
|
||||
return mTransparency;
|
||||
}
|
||||
|
||||
public boolean isAboveMaskLayer() {
|
||||
return mIsAboveMaskLayer;
|
||||
}
|
||||
|
||||
public boolean isPointsUpdated() {
|
||||
return mIsPointsUpdated;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.mogo.map;
|
||||
|
||||
import com.mogo.map.overlay.IMogoOverlayManager;
|
||||
import com.mogo.map.overlay.IMogoPolyline;
|
||||
import com.mogo.map.overlay.MogoPolylineOptions;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-03-10
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class MogoOverlayManager implements IMogoOverlayManager {
|
||||
|
||||
private MogoOverlayManager() {
|
||||
// private constructor
|
||||
}
|
||||
|
||||
private static final class InstanceHolder {
|
||||
private static final MogoOverlayManager INSTANCE = new MogoOverlayManager();
|
||||
}
|
||||
|
||||
public static MogoOverlayManager getInstance() {
|
||||
return InstanceHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private Object readResolve() {
|
||||
// 阻止反序列化,必须实现 Serializable 接口
|
||||
return InstanceHolder.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMogoPolyline addPolyline( MogoPolylineOptions options ) {
|
||||
try {
|
||||
return MogoMap.getInstance().getMogoMap().addPolyline( options );
|
||||
} catch ( Exception e ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,10 +43,10 @@ dependencies {
|
||||
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.mogomapapi
|
||||
implementation rootProject.ext.dependencies.mogoutils
|
||||
api rootProject.ext.dependencies.mogocommons
|
||||
api rootProject.ext.dependencies.mogoserviceapi
|
||||
@@ -58,6 +58,8 @@ dependencies {
|
||||
api project(":foudations:mogo-commons")
|
||||
api project(':services:mogo-service-api')
|
||||
implementation project(':modules:mogo-module-common')
|
||||
implementation project(":libraries:card-library")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,18 @@ package com.mogo.module.apps;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
import android.widget.HorizontalScrollView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.LinearSnapHelper;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.alibaba.android.arouter.launcher.ARouter;
|
||||
import com.mogo.commons.mvp.MvpFragment;
|
||||
import com.mogo.module.apps.adapter.AppIndicatorAdapter;
|
||||
import com.mogo.module.apps.utils.CardScaleTransformer;
|
||||
import com.mogo.module.apps.utils.LaunchUtils;
|
||||
import com.mogo.module.common.MogoModulePaths;
|
||||
import com.mogo.service.MogoServicePaths;
|
||||
@@ -18,6 +24,9 @@ import com.mogo.service.fragmentmanager.IMogoFragmentManager;
|
||||
import com.mogo.service.module.IMogoModuleProvider;
|
||||
import com.mogo.utils.TipToast;
|
||||
|
||||
import com.yarolegovich.discretescrollview.DiscreteScrollView;
|
||||
import com.yarolegovich.discretescrollview.transform.ScaleTransformer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -27,11 +36,10 @@ import java.util.Map;
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class AppNavigatorFragment extends MvpFragment< AppNavigatorView, AppNavigatorPresenter > implements AppNavigatorView {
|
||||
public class AppNavigatorFragment extends MvpFragment<AppNavigatorView, AppNavigatorPresenter>
|
||||
implements AppNavigatorView, DiscreteScrollView.OnItemChangedListener<RecyclerView.ViewHolder>,
|
||||
DiscreteScrollView.ScrollStateChangeListener<RecyclerView.ViewHolder> {
|
||||
|
||||
private View mNavigation;
|
||||
private View mMediaCenter;
|
||||
private View mCarSettings;
|
||||
private View mApps;
|
||||
|
||||
private IMogoFragmentManager mMogoFragmentManager;
|
||||
@@ -42,6 +50,7 @@ public class AppNavigatorFragment extends MvpFragment< AppNavigatorView, AppNavi
|
||||
private IMogoModuleProvider mSearchProvider;
|
||||
|
||||
private IMogoAnalytics mMogoAnalytics;
|
||||
private DiscreteScrollView scroller;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
@@ -51,66 +60,105 @@ public class AppNavigatorFragment extends MvpFragment< AppNavigatorView, AppNavi
|
||||
@Override
|
||||
protected void initViews() {
|
||||
|
||||
mMogoFragmentManager = ( IMogoFragmentManager ) ARouter.getInstance().build( MogoServicePaths.PATH_FRAGMENT_MANAGER ).navigation();
|
||||
mMogoFragmentManager = (IMogoFragmentManager) ARouter.getInstance()
|
||||
.build(MogoServicePaths.PATH_FRAGMENT_MANAGER)
|
||||
.navigation();
|
||||
|
||||
mNavigation = findViewById( R.id.module_apps_id_navigation );
|
||||
mMediaCenter = findViewById( R.id.module_apps_ic_media_center );
|
||||
mCarSettings = findViewById( R.id.module_apps_ic_car_settings );
|
||||
mApps = findViewById( R.id.module_apps_id_apps );
|
||||
mNavigation.setOnClickListener( view -> {
|
||||
openSearchPanel();
|
||||
trackNavigatorClickEvent( 1 );
|
||||
} );
|
||||
mMediaCenter.setOnClickListener( view -> {
|
||||
try {
|
||||
LaunchUtils.launchByPkg( getContext(), AppsConst.APP_PKG_MUSIC );
|
||||
trackNavigatorClickEvent( 2 );
|
||||
} catch ( Exception e ) {
|
||||
TipToast.shortTip( R.string.module_apps_str_no_app );
|
||||
}
|
||||
} );
|
||||
mCarSettings.setOnClickListener( view -> {
|
||||
try {
|
||||
LaunchUtils.launchByPkg( getContext(), AppsConst.APP_PKG_CAR_SETTINGS );
|
||||
trackNavigatorClickEvent( 3 );
|
||||
} catch ( Exception e ) {
|
||||
TipToast.shortTip( R.string.module_apps_str_no_app );
|
||||
}
|
||||
} );
|
||||
mApps.setOnClickListener( view -> {
|
||||
mApps = findViewById(R.id.module_apps_id_apps);
|
||||
|
||||
scroller = findViewById(R.id.module_apps_id_scroller);
|
||||
scroller.setSlideOnFling(true);
|
||||
scroller.addOnItemChangedListener(this);
|
||||
scroller.addScrollStateChangeListener(this);
|
||||
//scroller.setItemTransitionTimeMillis(DiscreteScrollViewOptions.getTransitionTime());
|
||||
scroller.setItemTransformer(new CardScaleTransformer.Builder()
|
||||
.setMinScale(0.84f)
|
||||
.build());
|
||||
//
|
||||
//
|
||||
//LinearLayoutManager linearLayoutManager =
|
||||
// new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
|
||||
//
|
||||
//scroller.setLayoutManager(linearLayoutManager);
|
||||
|
||||
ArrayList<Integer> integers = new ArrayList<>(10);
|
||||
|
||||
integers.add(R.drawable.module_apps_ic_interest);
|
||||
integers.add(R.drawable.module_apps_ic_online_car);
|
||||
integers.add(R.drawable.module_apps_ic_news);
|
||||
integers.add(R.drawable.module_apps_ic_tanlu);
|
||||
integers.add(R.drawable.module_apps_ic_media_center);
|
||||
|
||||
AppIndicatorAdapter appIndicatorAdapter = new AppIndicatorAdapter(getContext(), integers);
|
||||
scroller.setAdapter(appIndicatorAdapter);
|
||||
scroller.scrollToPosition(Integer.MAX_VALUE / 2-1);
|
||||
//mNavigation.setOnClickListener( view -> {
|
||||
// openSearchPanel();
|
||||
// trackNavigatorClickEvent( 1 );
|
||||
//} );
|
||||
//mMediaCenter.setOnClickListener( view -> {
|
||||
// try {
|
||||
// LaunchUtils.launchByPkg( getContext(), AppsConst.APP_PKG_MUSIC );
|
||||
// trackNavigatorClickEvent( 2 );
|
||||
// } catch ( Exception e ) {
|
||||
// TipToast.shortTip( R.string.module_apps_str_no_app );
|
||||
// }
|
||||
//} );
|
||||
//mCarSettings.setOnClickListener( view -> {
|
||||
// try {
|
||||
// LaunchUtils.launchByPkg( getContext(), AppsConst.APP_PKG_CAR_SETTINGS );
|
||||
// trackNavigatorClickEvent( 3 );
|
||||
// } catch ( Exception e ) {
|
||||
// TipToast.shortTip( R.string.module_apps_str_no_app );
|
||||
// }
|
||||
//} );
|
||||
mApps.setOnClickListener(view -> {
|
||||
openAppsPanel();
|
||||
trackNavigatorClickEvent( 4 );
|
||||
} );
|
||||
trackNavigatorClickEvent(4);
|
||||
});
|
||||
}
|
||||
|
||||
private void scrollToCenter(int index) {
|
||||
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected AppNavigatorPresenter createPresenter() {
|
||||
return new AppNavigatorPresenter( this );
|
||||
return new AppNavigatorPresenter(this);
|
||||
}
|
||||
|
||||
private void openSearchPanel() {
|
||||
mSearchProvider = ( IMogoModuleProvider ) ARouter.getInstance().build( MogoModulePaths.PATH_MODULE_SEARCH ).navigation();
|
||||
final Fragment fragment = mSearchProvider.createFragment( getContext(), null );
|
||||
mMogoFragmentManager.push( new FragmentDescriptor.Builder().fragment( fragment ).tag( MogoModulePaths.PATH_FRAGMENT_SEARCH ).notifyMainModule( true ).build() );
|
||||
mSearchProvider = (IMogoModuleProvider) ARouter.getInstance()
|
||||
.build(MogoModulePaths.PATH_MODULE_SEARCH)
|
||||
.navigation();
|
||||
final Fragment fragment = mSearchProvider.createFragment(getContext(), null);
|
||||
mMogoFragmentManager.push(new FragmentDescriptor.Builder().fragment(fragment)
|
||||
.tag(MogoModulePaths.PATH_FRAGMENT_SEARCH)
|
||||
.notifyMainModule(true)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated( @Nullable Bundle savedInstanceState ) {
|
||||
super.onActivityCreated( savedInstanceState );
|
||||
mMogoFragmentManager = ( IMogoFragmentManager ) ARouter.getInstance().build( MogoServicePaths.PATH_FRAGMENT_MANAGER ).navigation( getContext() );
|
||||
mMogoAnalytics = ( IMogoAnalytics ) ARouter.getInstance().build( MogoServicePaths.PATH_UTILS_ANALYTICS ).navigation( getContext() );
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
mMogoFragmentManager = (IMogoFragmentManager) ARouter.getInstance()
|
||||
.build(MogoServicePaths.PATH_FRAGMENT_MANAGER)
|
||||
.navigation(getContext());
|
||||
mMogoAnalytics = (IMogoAnalytics) ARouter.getInstance()
|
||||
.build(MogoServicePaths.PATH_UTILS_ANALYTICS)
|
||||
.navigation(getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openAppsPanel() {
|
||||
AppsListActivity.start( getActivity() );
|
||||
AppsListActivity.start(getActivity());
|
||||
}
|
||||
|
||||
private void trackNavigatorClickEvent( int type ) {
|
||||
final Map< String, Object > properties = new HashMap<>();
|
||||
properties.put( "type", type );
|
||||
mMogoAnalytics.track( "Launcher_APP_Icon", properties );
|
||||
private void trackNavigatorClickEvent(int type) {
|
||||
final Map<String, Object> properties = new HashMap<>();
|
||||
properties.put("type", type);
|
||||
mMogoAnalytics.track("Launcher_APP_Icon", properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -120,8 +168,27 @@ public class AppNavigatorFragment extends MvpFragment< AppNavigatorView, AppNavi
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
if ( mPresenter != null ) {
|
||||
mPresenter.onDestroy( getViewLifecycleOwner() );
|
||||
if (mPresenter != null) {
|
||||
mPresenter.onDestroy(getViewLifecycleOwner());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentItemChanged(@Nullable RecyclerView.ViewHolder viewHolder, int i) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onScrollStart(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onScrollEnd(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScroll(float v, int i, int i1, @Nullable RecyclerView.ViewHolder viewHolder,
|
||||
@Nullable RecyclerView.ViewHolder t1) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.mogo.module.apps.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import com.mogo.module.apps.R;
|
||||
import com.mogo.module.apps.adapter.base.RecycleBaseAdapter;
|
||||
import com.mogo.module.apps.adapter.base.RecycleViewHolder;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author zyz
|
||||
* 2020-03-09.
|
||||
*/
|
||||
public class AppIndicatorAdapter extends RecycleBaseAdapter<Integer> {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public AppIndicatorAdapter(Context context, List<Integer> list
|
||||
) {
|
||||
super(context, list, R.layout.module_apps_item_app_indicator);
|
||||
}
|
||||
|
||||
@Override public int getItemCount() {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override public void onBindViewHolder(RecycleViewHolder holder, Integer integer) {
|
||||
ImageView ivIndicator = holder.getView(R.id.module_apps_id_app_icon);
|
||||
ivIndicator.setImageResource(integer);
|
||||
holder.setText(R.id.module_apps_id_app_name,names[holder.getLayoutPosition()%5] );
|
||||
}
|
||||
private String[] names=new String[]{"新鲜事","在线车辆","首页","探路","车聊聊"};
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package com.mogo.module.apps.adapter.base;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Title: adapter
|
||||
* </p>
|
||||
* <p>
|
||||
* Description:
|
||||
* </p>
|
||||
* <p>
|
||||
* Copyright: Copyright (c) 2015
|
||||
* </p>
|
||||
* <p>
|
||||
* </p>
|
||||
*/
|
||||
public abstract class RecycleBaseAdapter<T> extends
|
||||
RecyclerView.Adapter<RecycleViewHolder>
|
||||
{
|
||||
|
||||
protected Context context;
|
||||
protected List<T> list;
|
||||
private int resourceID;
|
||||
private Toast toast;
|
||||
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
public RecycleBaseAdapter(Context context, List<T> list, int resourceID)
|
||||
{
|
||||
super();
|
||||
this.context = context;
|
||||
this.list = list;
|
||||
this.resourceID = resourceID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecycleViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType)
|
||||
{
|
||||
View v = LayoutInflater.from(context).inflate(resourceID, viewGroup,
|
||||
false);
|
||||
|
||||
RecycleViewHolder holder = RecycleViewHolder
|
||||
.get(v);
|
||||
|
||||
initHolder(holder);
|
||||
|
||||
return holder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(
|
||||
RecycleViewHolder viewHolder, int position)
|
||||
{
|
||||
onBindViewHolder(viewHolder, list.get(position % list.size()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount()
|
||||
{
|
||||
return list == null ? 0 : list.size();
|
||||
}
|
||||
|
||||
public abstract void onBindViewHolder(
|
||||
RecycleViewHolder holder, T t);
|
||||
|
||||
public void initHolder(RecycleViewHolder holder)
|
||||
{
|
||||
|
||||
}
|
||||
public void setDatas(List<T> list)
|
||||
{
|
||||
setDatas(list, false);
|
||||
}
|
||||
|
||||
public void setDatas(List<T> list, boolean add)
|
||||
{
|
||||
if (add)
|
||||
{
|
||||
this.list.addAll(list);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.list = list;
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
public void clear(){
|
||||
if (list != null) {
|
||||
list.clear();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
public void messageShow(String mes)
|
||||
{
|
||||
if (toast==null){
|
||||
toast= Toast.makeText(context,mes, Toast.LENGTH_LONG);
|
||||
}
|
||||
else{
|
||||
toast.setText(mes);
|
||||
}
|
||||
toast.show();
|
||||
}
|
||||
|
||||
public T getItem(int position){
|
||||
if (list==null||list.size()==0){
|
||||
return null;
|
||||
}
|
||||
return list.get(position);
|
||||
}
|
||||
|
||||
public List<T> getList() {
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package com.mogo.module.apps.adapter.base;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.text.SpannableString;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class RecycleViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private SparseArray<View> mViews;
|
||||
|
||||
private View mConvertView;
|
||||
|
||||
public RecycleViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
this.mConvertView = itemView;
|
||||
mViews = new SparseArray<View>();
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public static RecycleViewHolder get(View itemView) {
|
||||
return new RecycleViewHolder(itemView);
|
||||
}
|
||||
|
||||
public View getConvertView() {
|
||||
return mConvertView;
|
||||
}
|
||||
|
||||
public <T extends View> T getView(int viewId) {
|
||||
View view = mViews.get(viewId);
|
||||
if (view == null) {
|
||||
view = mConvertView.findViewById(viewId);
|
||||
mViews.put(viewId, view);
|
||||
}
|
||||
return (T) view;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param viewId
|
||||
* @param text
|
||||
* @return
|
||||
*/
|
||||
public RecycleViewHolder setText(int viewId, String text) {
|
||||
TextView tv = getView(viewId);
|
||||
if (tv==null)return this;
|
||||
tv.setText(text);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param viewId
|
||||
* @param text
|
||||
* @return
|
||||
*/
|
||||
public RecycleViewHolder setText(int viewId, SpannableString text) {
|
||||
TextView tv = getView(viewId);
|
||||
tv.setText(text);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param viewId
|
||||
* @param resId
|
||||
* @return
|
||||
*/
|
||||
public RecycleViewHolder setImageResource(int viewId, int resId) {
|
||||
ImageView view = getView(viewId);
|
||||
view.setImageResource(resId);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param viewId
|
||||
* @return
|
||||
*/
|
||||
public RecycleViewHolder setImageBitmap(int viewId, Bitmap bitmap) {
|
||||
ImageView view = getView(viewId);
|
||||
view.setImageBitmap(bitmap);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param viewId
|
||||
* @param resId
|
||||
* @return
|
||||
*/
|
||||
// public ViewHolder setImageURI(int viewId, String url) {
|
||||
// ImageView view = getView(viewId);
|
||||
// // ImageLoader.getInstance.loadImg(view,url);
|
||||
// return this;
|
||||
// }
|
||||
|
||||
/**
|
||||
*
|
||||
* @param viewId
|
||||
* @param resId
|
||||
* @return
|
||||
*/
|
||||
public RecycleViewHolder setBackgroundImage(int viewId, int resId) {
|
||||
View view = getView(viewId);
|
||||
view.setBackgroundResource(resId);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param viewId
|
||||
* @param resId
|
||||
* @return
|
||||
*/
|
||||
public RecycleViewHolder setTextColor(int viewId, int resId) {
|
||||
TextView view = getView(viewId);
|
||||
view.setTextColor(resId);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param viewId
|
||||
* @return
|
||||
*/
|
||||
public RecycleViewHolder setOnClickListener(int viewId,
|
||||
OnClickListener listener) {
|
||||
getView(viewId).setOnClickListener(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.mogo.module.apps.utils;
|
||||
|
||||
import android.view.View;
|
||||
import androidx.annotation.FloatRange;
|
||||
import com.mogo.module.apps.R;
|
||||
import com.yarolegovich.discretescrollview.transform.DiscreteScrollItemTransformer;
|
||||
import com.yarolegovich.discretescrollview.transform.Pivot;
|
||||
import com.yarolegovich.discretescrollview.transform.ScaleTransformer;
|
||||
|
||||
/**
|
||||
* @author zyz
|
||||
* 2020-03-11.
|
||||
*/
|
||||
public class CardScaleTransformer implements DiscreteScrollItemTransformer {
|
||||
|
||||
private Pivot pivotX;
|
||||
private Pivot pivotY;
|
||||
private float minScale;
|
||||
private float maxMinDiff;
|
||||
|
||||
public CardScaleTransformer() {
|
||||
pivotX = Pivot.X.CENTER.create();
|
||||
pivotY = Pivot.Y.BOTTOM.create();
|
||||
minScale = 0.8f;
|
||||
maxMinDiff = 0.2f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transformItem(View item, float position) {
|
||||
|
||||
item= item.findViewById(R.id.module_apps_id_app_icon);
|
||||
pivotX.setOn(item);
|
||||
pivotY.setOn(item);
|
||||
float closenessToCenter = 1f - Math.abs(position);
|
||||
float scale = minScale + maxMinDiff * closenessToCenter;
|
||||
item.setScaleX(scale);
|
||||
item.setScaleY(scale);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private CardScaleTransformer transformer;
|
||||
private float maxScale;
|
||||
|
||||
public Builder() {
|
||||
transformer = new CardScaleTransformer();
|
||||
maxScale = 1f;
|
||||
}
|
||||
|
||||
public Builder setMinScale(@FloatRange(from = 0.01) float scale) {
|
||||
transformer.minScale = scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setMaxScale(@FloatRange(from = 0.01) float scale) {
|
||||
maxScale = scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPivotX(Pivot.X pivotX) {
|
||||
return setPivotX(pivotX.create());
|
||||
}
|
||||
|
||||
public Builder setPivotX(Pivot pivot) {
|
||||
assertAxis(pivot, Pivot.AXIS_X);
|
||||
transformer.pivotX = pivot;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPivotY(Pivot.Y pivotY) {
|
||||
return setPivotY(pivotY.create());
|
||||
}
|
||||
|
||||
public Builder setPivotY(Pivot pivot) {
|
||||
assertAxis(pivot, Pivot.AXIS_Y);
|
||||
transformer.pivotY = pivot;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CardScaleTransformer build() {
|
||||
transformer.maxMinDiff = maxScale - transformer.minScale;
|
||||
return transformer;
|
||||
}
|
||||
|
||||
private void assertAxis(Pivot pivot, @Pivot.Axis int axis) {
|
||||
if (pivot.getAxis() != axis) {
|
||||
throw new IllegalArgumentException("You passed a Pivot for wrong axis.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
BIN
modules/mogo-module-apps/src/main/res/drawable-xhdpi/module_apps_ic_interest.png
Executable file
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
BIN
modules/mogo-module-apps/src/main/res/drawable-xhdpi/module_apps_ic_media_center.png
Normal file → Executable file
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
BIN
modules/mogo-module-apps/src/main/res/drawable-xhdpi/module_apps_ic_news.png
Executable file
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
BIN
modules/mogo-module-apps/src/main/res/drawable-xhdpi/module_apps_ic_tanlu.png
Executable file
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
@@ -1,35 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<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:gravity="bottom"
|
||||
android:paddingBottom="@dimen/module_apps_navigation_icon_paddingBottom">
|
||||
android:paddingBottom="@dimen/module_apps_navigation_icon_paddingBottom"
|
||||
>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/module_apps_id_navigation"
|
||||
android:layout_width="@dimen/module_apps_navigation_icon_width"
|
||||
android:layout_height="@dimen/module_apps_navigation_icon_height"
|
||||
android:src="@drawable/module_apps_ic_navigation" />
|
||||
<com.yarolegovich.discretescrollview.DiscreteScrollView
|
||||
android:id="@+id/module_apps_id_scroller"
|
||||
android:layout_width="@dimen/dp_523"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
android:layout_height="@dimen/module_apps_navigation_icon_container_height"
|
||||
>
|
||||
</com.yarolegovich.discretescrollview.DiscreteScrollView>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/module_apps_ic_media_center"
|
||||
android:layout_width="@dimen/module_apps_navigation_icon_width"
|
||||
android:layout_height="@dimen/module_apps_navigation_icon_height"
|
||||
android:layout_marginLeft="@dimen/module_apps_navigation_icon_marginLeft"
|
||||
android:src="@drawable/module_apps_ic_media_center" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/module_apps_ic_car_settings"
|
||||
android:layout_width="@dimen/module_apps_navigation_icon_width"
|
||||
android:layout_height="@dimen/module_apps_navigation_icon_height"
|
||||
android:layout_marginLeft="@dimen/module_apps_navigation_icon_marginLeft"
|
||||
android:src="@drawable/module_apps_ic_car_settings" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/module_apps_id_apps"
|
||||
android:layout_width="@dimen/module_apps_navigation_icon_width"
|
||||
android:layout_height="@dimen/module_apps_navigation_icon_height"
|
||||
android:layout_marginLeft="@dimen/module_apps_navigation_icon_marginLeft"
|
||||
android:src="@drawable/module_apps_ic_apps" />
|
||||
</LinearLayout>
|
||||
<ImageView
|
||||
android:id="@+id/module_apps_id_apps"
|
||||
android:layout_width="@dimen/module_apps_navigation_icon_width"
|
||||
android:layout_marginTop="@dimen/dp_18"
|
||||
android:layout_height="@dimen/module_apps_navigation_icon_height"
|
||||
app:layout_constraintLeft_toRightOf="@id/module_apps_id_scroller"
|
||||
app:layout_constraintTop_toTopOf="@id/module_apps_id_scroller"
|
||||
android:layout_marginLeft="@dimen/module_apps_navigation_icon_marginLeft"
|
||||
android:src="@drawable/module_apps_ic_apps"
|
||||
/>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_marginLeft="@dimen/dp_37"
|
||||
app:layout_constraintLeft_toRightOf="@id/module_apps_id_scroller"
|
||||
app:layout_constraintTop_toBottomOf="@id/module_apps_id_apps"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="全部应用"
|
||||
android:maxLines="1"
|
||||
android:layout_marginTop="24px"
|
||||
android:textColor="#FFFFFFFF"
|
||||
android:textSize="26.25px"
|
||||
/>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,24 @@
|
||||
<?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="@dimen/dp_137"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center|bottom"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/module_apps_id_app_icon"
|
||||
android:layout_width="@dimen/dp_112"
|
||||
android:scaleType="fitXY"
|
||||
android:layout_height="@dimen/dp_112" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/module_apps_id_app_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dp_24"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="@dimen/dp_26" />
|
||||
</LinearLayout>
|
||||
@@ -5,9 +5,9 @@
|
||||
<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>
|
||||
<dimen name="module_apps_navigation_icon_marginLeft">60px</dimen>
|
||||
<dimen name="module_apps_navigation_icon_width">94px</dimen>
|
||||
<dimen name="module_apps_navigation_icon_height">94px</dimen>
|
||||
<dimen name="module_apps_navigation_icon_marginLeft">43px</dimen>
|
||||
<dimen name="module_apps_navigation_icon_paddingBottom">60px</dimen>
|
||||
<dimen name="module_apps_app_name_marginTop">32px</dimen>
|
||||
<dimen name="module_apps_app_name_textSize">32px</dimen>
|
||||
|
||||
@@ -14,4 +14,5 @@
|
||||
<dimen name="module_apps_page_paddingLeft">220px</dimen>
|
||||
<dimen name="module_apps_page_paddingRight">220px</dimen>
|
||||
<dimen name="module_apps_page_item_verticalSpacing">154px</dimen>
|
||||
<dimen name="module_apps_navigation_icon_container_height">174px</dimen>
|
||||
</resources>
|
||||
@@ -47,13 +47,21 @@ dependencies {
|
||||
implementation rootProject.ext.dependencies.rxandroid
|
||||
|
||||
if (Boolean.valueOf(RELEASE)) {
|
||||
implementation rootProject.ext.dependencies.mogomap
|
||||
implementation rootProject.ext.dependencies.mogomapapi
|
||||
implementation rootProject.ext.dependencies.mogoutils
|
||||
implementation rootProject.ext.dependencies.mogocommons
|
||||
implementation rootProject.ext.dependencies.mogoserviceapi
|
||||
implementation rootProject.ext.dependencies.modulecommon
|
||||
implementation rootProject.ext.dependencies.moduleshare
|
||||
} else {
|
||||
implementation project(":libraries:mogo-map")
|
||||
implementation project(":libraries:mogo-map-api")
|
||||
implementation project(":foudations:mogo-utils")
|
||||
api project(":foudations:mogo-commons")
|
||||
implementation project(":foudations:mogo-commons")
|
||||
implementation project(':services:mogo-service-api')
|
||||
implementation project(':modules:mogo-module-common')
|
||||
implementation project(':modules:mogo-module-share')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,33 +1,31 @@
|
||||
package com.mogo.module.back;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.alibaba.android.arouter.facade.annotation.Route;
|
||||
import com.alibaba.android.arouter.launcher.ARouter;
|
||||
import com.alibaba.idst.nls.internal.utils.L;
|
||||
import com.mogo.commons.AbsMogoApplication;
|
||||
import com.mogo.map.listener.IMogoMapListener;
|
||||
import com.mogo.map.location.IMogoLocationListener;
|
||||
import com.mogo.map.marker.IMogoMarkerClickListener;
|
||||
import com.mogo.map.navi.IMogoNaviListener;
|
||||
import com.mogo.service.IMogoServiceApis;
|
||||
import com.mogo.service.MogoServicePaths;
|
||||
import com.mogo.service.fragmentmanager.IMogoFragmentManager;
|
||||
import com.mogo.service.intent.IMogoIntentListener;
|
||||
import com.mogo.service.intent.IMogoIntentManager;
|
||||
import com.mogo.service.module.IMogoModuleLifecycle;
|
||||
import com.mogo.service.module.IMogoModuleProvider;
|
||||
import com.mogo.service.module.ModuleType;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-02-26
|
||||
@@ -35,7 +33,12 @@ import java.util.Map;
|
||||
* 描述
|
||||
*/
|
||||
@Route( path = BackToLauncherConst.MODULE_PATH )
|
||||
public class BackToLauncherModuleProvider implements IMogoModuleProvider {
|
||||
public class BackToLauncherModuleProvider implements IMogoModuleProvider, IMogoIntentListener {
|
||||
|
||||
private IMogoServiceApis mServiceApis;
|
||||
private IMogoIntentManager mIntentManager;
|
||||
|
||||
public static final String COMMAND_BACK = "com.ileja.launcher.back";
|
||||
|
||||
private static final String TAG = "BackToLauncherModuleProvider";
|
||||
|
||||
@@ -98,54 +101,17 @@ public class BackToLauncherModuleProvider implements IMogoModuleProvider {
|
||||
@Override
|
||||
public void init( Context context ) {
|
||||
BackToMainHomeManager.addMainHomeView();
|
||||
// final Activity activity = getTopActivity(context.getPackageName());
|
||||
// if ( activity instanceof FragmentActivity ) {
|
||||
// Logger.d( TAG, "init." );
|
||||
// FragmentManager fragmentManager = ( ( FragmentActivity ) activity ).getSupportFragmentManager();
|
||||
// fragmentManager.beginTransaction()
|
||||
// .add( new Back2LauncherFragment(), BackToLauncherConst.MODULE_NAME )
|
||||
// .commitAllowingStateLoss();
|
||||
// fragmentManager.executePendingTransactions();
|
||||
// }
|
||||
mServiceApis = ( IMogoServiceApis ) ARouter.getInstance().build( MogoServicePaths.PATH_SERVICE_APIS ).navigation();
|
||||
mIntentManager = mServiceApis.getIntentManagerApi();
|
||||
mIntentManager.registerIntentListener( COMMAND_BACK, this );
|
||||
BackToMainHomeManager.init( mServiceApis.getFragmentManagerApi() );
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 获取当前运行的activity
|
||||
// */
|
||||
// private Activity getTopActivity(String process) {
|
||||
// Log.i("activity", "[getTopActivity]");
|
||||
// try {
|
||||
// Class activityThreadClass = Class.forName("android.app.ActivityThread");
|
||||
// Object activityThread = activityThreadClass.getMethod("currentActivityThread").invoke(null);
|
||||
// Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
|
||||
// activitiesField.setAccessible(true);
|
||||
// //16~18 HashMap
|
||||
// //19~27 ArrayMap
|
||||
// Map<Object, Object> activities;
|
||||
// if ( Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||
// activities = ( HashMap<Object, Object> ) activitiesField.get(activityThread);
|
||||
// } else {
|
||||
// activities = ( ArrayMap<Object, Object> ) activitiesField.get(activityThread);
|
||||
// }
|
||||
// if (activities.size() < 1) {
|
||||
// return null;
|
||||
// }
|
||||
// for (Object activityRecord : activities.values()) {
|
||||
// Class activityRecordClass = activityRecord.getClass();
|
||||
// Field pausedField = activityRecordClass.getDeclaredField("paused");
|
||||
// pausedField.setAccessible(true);
|
||||
// if (!pausedField.getBoolean(activityRecord)) {
|
||||
// Field activityField = activityRecordClass.getDeclaredField("activity");
|
||||
// activityField.setAccessible(true);
|
||||
// Activity activity = (Activity) activityField.get(activityRecord);
|
||||
// if ( TextUtils.equals( process, activity.getPackageName() ) ) {
|
||||
// return activity;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
@Override
|
||||
public void onIntentReceived( String intentStr, Intent intent ) {
|
||||
if ( COMMAND_BACK.equals( intentStr ) ) {
|
||||
Logger.d( TAG, "received back to home command." );
|
||||
BackToMainHomeManager.backToLauncher();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,15 +14,35 @@ import android.view.WindowManager;
|
||||
import com.mogo.commons.AbsMogoApplication;
|
||||
import com.mogo.module.back.utils.Utils;
|
||||
import com.mogo.module.back.utils.WindowManagerViewHelper;
|
||||
import com.mogo.service.fragmentmanager.IMogoFragmentManager;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
|
||||
public class BackToMainHomeManager {
|
||||
|
||||
private static View mBackView;
|
||||
public static void addMainHomeView(){
|
||||
Logger.d("BackToMainHomeManager","addMainHomeView");
|
||||
if (mBackView != null)WindowManagerViewHelper.removeView(mBackView);
|
||||
mBackView = LayoutInflater.from(AbsMogoApplication.getApp()).inflate(R.layout.mogo_module_back_home_back_layout, null);
|
||||
|
||||
private static IMogoFragmentManager mFragmentManager;
|
||||
|
||||
public static void init( IMogoFragmentManager manager ) {
|
||||
mFragmentManager = manager;
|
||||
}
|
||||
|
||||
public static void backToLauncher(){
|
||||
Intent intent = new Intent();
|
||||
intent.setAction( Intent.ACTION_MAIN );
|
||||
intent.addCategory( Intent.CATEGORY_HOME );
|
||||
intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
|
||||
AbsMogoApplication.getApp().startActivity( intent );
|
||||
|
||||
if ( mFragmentManager != null ) {
|
||||
mFragmentManager.clearAll();
|
||||
}
|
||||
}
|
||||
|
||||
public static void addMainHomeView() {
|
||||
Logger.d( "BackToMainHomeManager", "addMainHomeView" );
|
||||
if ( mBackView != null ) WindowManagerViewHelper.removeView( mBackView );
|
||||
mBackView = LayoutInflater.from( AbsMogoApplication.getApp() ).inflate( R.layout.mogo_module_back_home_back_layout, null );
|
||||
final Context context = mBackView.getContext();
|
||||
if ( context == null || context.getApplicationContext() == null ) {
|
||||
return;
|
||||
@@ -31,32 +51,24 @@ public class BackToMainHomeManager {
|
||||
if ( windowManager == null ) {
|
||||
return;
|
||||
}
|
||||
mBackView.setOnClickListener(view -> {
|
||||
if (Utils.isActivityExits("com.mogo.launcher","com.mogo.module.main.MainActivity")){
|
||||
ComponentName cn = new ComponentName("com.mogo.launcher", "com.mogo.module.main.MainActivity") ;
|
||||
Intent intent = new Intent() ;
|
||||
intent.setComponent(cn) ;
|
||||
if (!(AbsMogoApplication.getApp().getApplicationContext() instanceof Activity)) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
}
|
||||
AbsMogoApplication.getApp().startActivity(intent);
|
||||
}
|
||||
});
|
||||
mBackView.setOnClickListener( view -> {
|
||||
backToLauncher();
|
||||
} );
|
||||
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
|
||||
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||
params.x = AbsMogoApplication.getApp().getResources().getDimensionPixelOffset(R.dimen.module_back_main_home_icon_left);
|
||||
params.y = AbsMogoApplication.getApp().getResources().getDimensionPixelOffset(R.dimen.module_back_main_home_icon_top);
|
||||
params.x = AbsMogoApplication.getApp().getResources().getDimensionPixelOffset( R.dimen.module_back_main_home_icon_left );
|
||||
params.y = AbsMogoApplication.getApp().getResources().getDimensionPixelOffset( R.dimen.module_back_main_home_icon_top );
|
||||
params.gravity = Gravity.LEFT | Gravity.CENTER;
|
||||
params.type = getFitWindowParamsType();
|
||||
params.format = PixelFormat.RGBA_8888;
|
||||
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
|
||||
windowManager.addView( mBackView, params );
|
||||
WindowManagerViewHelper.attachMovementEvent(mBackView,params);
|
||||
WindowManagerViewHelper.attachMovementEvent( mBackView, params );
|
||||
}
|
||||
|
||||
public static void removeMainHomeView(){
|
||||
WindowManagerViewHelper.removeView(mBackView);
|
||||
public static void removeMainHomeView() {
|
||||
WindowManagerViewHelper.removeView( mBackView );
|
||||
}
|
||||
|
||||
private static int getFitWindowParamsType() {
|
||||
|
||||
@@ -7,13 +7,13 @@ import android.content.pm.ResolveInfo;
|
||||
import com.mogo.commons.AbsMogoApplication;
|
||||
|
||||
public class Utils {
|
||||
public static boolean isActivityExits(String packageName,String classStr){
|
||||
public static boolean isActivityExits( String packageName, String classStr ) {
|
||||
Intent intent = new Intent();
|
||||
intent.setClassName(packageName, classStr);
|
||||
ResolveInfo resolveInfo = AbsMogoApplication.getApp().getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
if(resolveInfo != null) {
|
||||
intent.setClassName( packageName, classStr );
|
||||
ResolveInfo resolveInfo = AbsMogoApplication.getApp().getPackageManager().resolveActivity( intent, PackageManager.MATCH_DEFAULT_ONLY );
|
||||
if ( resolveInfo != null ) {
|
||||
return true;
|
||||
}else{
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ public class MarkerCarInfo implements Serializable {
|
||||
|
||||
private String carBrandLogoUrl;
|
||||
private String carTypeName;
|
||||
private int carType;
|
||||
private CarLive carLive;
|
||||
|
||||
public String getCarBrandLogoUrl() {
|
||||
if (TextUtils.isEmpty(carBrandLogoUrl)) {
|
||||
@@ -34,11 +36,61 @@ public class MarkerCarInfo implements Serializable {
|
||||
this.carTypeName = carTypeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MarkerCarInfo{" +
|
||||
"carBrandLogoUrl='" + carBrandLogoUrl + '\'' +
|
||||
", carTypeName='" + carTypeName + '\'' +
|
||||
'}';
|
||||
public int getCarType() {
|
||||
return carType;
|
||||
}
|
||||
|
||||
public void setCarType(int carType) {
|
||||
this.carType = carType;
|
||||
}
|
||||
|
||||
public CarLive getCarLive() {
|
||||
return carLive;
|
||||
}
|
||||
|
||||
public void setCarLive(CarLive carLive) {
|
||||
this.carLive = carLive;
|
||||
}
|
||||
|
||||
class CarLive implements Serializable {
|
||||
//rtmp视频直播地址rtmp://
|
||||
private String videoUrl;
|
||||
//直播频道【直播心跳接口参数】C_1
|
||||
private String videoChannel;
|
||||
//直播源sn【直播心跳接口参数】XTCBA90740400625
|
||||
private String videoSn;
|
||||
|
||||
public String getVideoUrl() {
|
||||
return videoUrl;
|
||||
}
|
||||
|
||||
public void setVideoUrl(String videoUrl) {
|
||||
this.videoUrl = videoUrl;
|
||||
}
|
||||
|
||||
public String getVideoChannel() {
|
||||
return videoChannel;
|
||||
}
|
||||
|
||||
public void setVideoChannel(String videoChannel) {
|
||||
this.videoChannel = videoChannel;
|
||||
}
|
||||
|
||||
public String getVideoSn() {
|
||||
return videoSn;
|
||||
}
|
||||
|
||||
public void setVideoSn(String videoSn) {
|
||||
this.videoSn = videoSn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CarLive{" +
|
||||
"videoUrl='" + videoUrl + '\'' +
|
||||
", videoChannel='" + videoChannel + '\'' +
|
||||
", videoSn='" + videoSn + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,4 +26,10 @@ public interface MarkerPoiTypeEnum {
|
||||
public String FOURS_PONDING = "10008";
|
||||
//超市打折
|
||||
public String FOURS_SHOP_FREE = "10009";
|
||||
//浓雾
|
||||
public String FOURS_FOG = "10010";
|
||||
//结冰
|
||||
public String FOURS_ICE = "10011";
|
||||
//停车场
|
||||
public String FOURS_PARKING = "10012";
|
||||
}
|
||||
@@ -16,6 +16,11 @@ public class MarkerUserInfo implements Serializable {
|
||||
private String gender;//gender": "男|女|无(也可以0|1|2根据实际库存返回即可)
|
||||
private Integer age;// 年龄段,可以为空,与车聊聊一致
|
||||
|
||||
// TODO V2X临时字段,接口出好后进行修改
|
||||
private String lastActiveweekAvgscore;//末次活跃周驾驶行为平均得分
|
||||
private String safeLabel;//车辆安全标签
|
||||
private int safeLabelType;//1老司机 2安全驾驶 3危险驾驶
|
||||
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
@@ -150,16 +155,46 @@ public class MarkerUserInfo implements Serializable {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public void setUserId(long userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getLastActiveweekAvgscore() {
|
||||
return lastActiveweekAvgscore;
|
||||
}
|
||||
|
||||
public void setLastActiveweekAvgscore(String lastActiveweekAvgscore) {
|
||||
this.lastActiveweekAvgscore = lastActiveweekAvgscore;
|
||||
}
|
||||
|
||||
public String getSafeLabel() {
|
||||
return safeLabel;
|
||||
}
|
||||
|
||||
public void setSafeLabel(String safeLabel) {
|
||||
this.safeLabel = safeLabel;
|
||||
}
|
||||
|
||||
public int getSafeLabelType() {
|
||||
return safeLabelType;
|
||||
}
|
||||
|
||||
public void setSafeLabelType(int safeLabelType) {
|
||||
this.safeLabelType = safeLabelType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MarkerUserInfo{" +
|
||||
"age=" + age +
|
||||
", gender='" + gender + '\'' +
|
||||
", sn='" + sn + '\'' +
|
||||
", userHead='" + userHead + '\'' +
|
||||
"sn='" + sn + '\'' +
|
||||
", userId=" + userId +
|
||||
", userName='" + userName + '\'' +
|
||||
", userHead='" + userHead + '\'' +
|
||||
", gender='" + gender + '\'' +
|
||||
", age=" + age +
|
||||
", lastActiveweekAvgscore='" + lastActiveweekAvgscore + '\'' +
|
||||
", safeLabel='" + safeLabel + '\'' +
|
||||
", safeLabelType=" + safeLabelType +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,9 +50,9 @@ import java.util.Map;
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class EntranceFragment extends MvpFragment<EntranceView, EntrancePresenter>
|
||||
implements EntranceView,
|
||||
IMogoNaviListener, IMogoMapListener {
|
||||
public class EntranceFragment extends MvpFragment< EntranceView, EntrancePresenter >
|
||||
implements EntranceView,
|
||||
IMogoNaviListener, IMogoMapListener {
|
||||
|
||||
private static final String TAG = "EntranceFragment";
|
||||
|
||||
@@ -100,37 +100,37 @@ public class EntranceFragment extends MvpFragment<EntranceView, EntrancePresente
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
mMogoFragmentManager = (IMogoFragmentManager) ARouter.getInstance()
|
||||
.build(MogoServicePaths.PATH_FRAGMENT_MANAGER)
|
||||
.navigation();
|
||||
mMogoAddressManager = (IMogoAddressManager) ARouter.getInstance()
|
||||
.build(MogoServicePaths.PATH_ADDRESS_MANAGER)
|
||||
.navigation();
|
||||
|
||||
mCommonAddress = findViewById(R.id.module_entrance_id_common_address);
|
||||
|
||||
mSearch = findViewById(R.id.module_entrance_id_search);
|
||||
|
||||
mSearch.setOnClickListener(view -> {
|
||||
mSearchProvider = (IMogoModuleProvider) ARouter.getInstance()
|
||||
.build(MogoModulePaths.PATH_MODULE_SEARCH)
|
||||
mMogoFragmentManager = ( IMogoFragmentManager ) ARouter.getInstance()
|
||||
.build( MogoServicePaths.PATH_FRAGMENT_MANAGER )
|
||||
.navigation();
|
||||
mMogoAddressManager = ( IMogoAddressManager ) ARouter.getInstance()
|
||||
.build( MogoServicePaths.PATH_ADDRESS_MANAGER )
|
||||
.navigation();
|
||||
final Fragment fragment = mSearchProvider.createFragment(getContext(), null);
|
||||
mMogoFragmentManager.push(new FragmentDescriptor.Builder().fragment(fragment)
|
||||
.tag(MogoModulePaths.PATH_FRAGMENT_SEARCH)
|
||||
.notifyMainModule(true)
|
||||
.build());
|
||||
});
|
||||
|
||||
mHome = findViewById(R.id.module_entrance_id_home);
|
||||
mHome.setOnClickListener(view -> {
|
||||
mCommonAddress = findViewById( R.id.module_entrance_id_common_address );
|
||||
|
||||
mSearch = findViewById( R.id.module_entrance_id_search );
|
||||
|
||||
mSearch.setOnClickListener( view -> {
|
||||
mSearchProvider = ( IMogoModuleProvider ) ARouter.getInstance()
|
||||
.build( MogoModulePaths.PATH_MODULE_SEARCH )
|
||||
.navigation();
|
||||
final Fragment fragment = mSearchProvider.createFragment( getContext(), null );
|
||||
mMogoFragmentManager.push( new FragmentDescriptor.Builder().fragment( fragment )
|
||||
.tag( MogoModulePaths.PATH_FRAGMENT_SEARCH )
|
||||
.notifyMainModule( true )
|
||||
.build() );
|
||||
} );
|
||||
|
||||
mHome = findViewById( R.id.module_entrance_id_home );
|
||||
mHome.setOnClickListener( view -> {
|
||||
mMogoAddressManager.goHome();
|
||||
});
|
||||
} );
|
||||
|
||||
mCompany = findViewById(R.id.module_entrance_id_company);
|
||||
mCompany.setOnClickListener(view -> {
|
||||
mCompany = findViewById( R.id.module_entrance_id_company );
|
||||
mCompany.setOnClickListener( view -> {
|
||||
mMogoAddressManager.goCompany();
|
||||
});
|
||||
} );
|
||||
|
||||
mUploadRoadCondition = findViewById( R.id.module_entrance_id_upload_road_condition );
|
||||
mUploadRoadCondition.setOnClickListener( view -> {
|
||||
@@ -141,78 +141,79 @@ public class EntranceFragment extends MvpFragment<EntranceView, EntrancePresente
|
||||
mVRMode.setOnClickListener( view -> {
|
||||
} );
|
||||
|
||||
mMove2CurrentLocation = findViewById(R.id.module_entrance_id_move2_current_location);
|
||||
mMove2CurrentLocation.setOnClickListener(view -> {
|
||||
mMove2CurrentLocation = findViewById( R.id.module_entrance_id_move2_current_location );
|
||||
mMove2CurrentLocation.setOnClickListener( view -> {
|
||||
final MogoLocation location = mMogoLocationClient.getLastKnowLocation();
|
||||
if (location != null) {
|
||||
mMogoStatusManager.setUserInteractionStatus(TAG, true, false);
|
||||
mMApUIController.changeZoom(16.0f);
|
||||
mMogoStatusManager.setUserInteractionStatus(TAG, true, false);
|
||||
if ( location != null ) {
|
||||
mMogoStatusManager.setUserInteractionStatus( TAG, true, false );
|
||||
mMApUIController.changeZoom( 16.0f );
|
||||
mMogoStatusManager.setUserInteractionStatus( TAG, true, false );
|
||||
mMApUIController.recoverLockMode();
|
||||
}
|
||||
});
|
||||
} );
|
||||
|
||||
mNaviInfo = findViewById(R.id.module_entrance_id_navi_info_panel);
|
||||
mExitNavi = findViewById(R.id.module_entrance_id_exit_navi);
|
||||
mExitNavi.setOnClickListener(view -> {
|
||||
if (mMogoNavi != null) {
|
||||
mNaviInfo = findViewById( R.id.module_entrance_id_navi_info_panel );
|
||||
mExitNavi = findViewById( R.id.module_entrance_id_exit_navi );
|
||||
mExitNavi.setOnClickListener( view -> {
|
||||
if ( mMogoNavi != null ) {
|
||||
//if ( mIsLock ) {
|
||||
NaviNoticeDialog naviNoticeDialog = new NaviNoticeDialog(getContext());
|
||||
NaviNoticeDialog naviNoticeDialog = new NaviNoticeDialog( getContext() );
|
||||
naviNoticeDialog.show();
|
||||
//} else {
|
||||
// mMApUIController.recoverLockMode();
|
||||
//}
|
||||
}
|
||||
});
|
||||
} );
|
||||
|
||||
ivMode = findViewById(R.id.module_ext_id_north);
|
||||
ivMode.setOnClickListener(new View.OnClickListener() {
|
||||
@Override public void onClick(View v) {
|
||||
if (ivMode.isSelected()) {
|
||||
mMApUIController.changeMapMode(EnumMapUI.CarUp_2D);
|
||||
ivMode = findViewById( R.id.module_ext_id_north );
|
||||
ivMode.setOnClickListener( new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View v ) {
|
||||
if ( ivMode.isSelected() ) {
|
||||
mMApUIController.changeMapMode( EnumMapUI.CarUp_2D );
|
||||
} else {
|
||||
mMApUIController.changeMapMode(EnumMapUI.NorthUP_2D);
|
||||
mMApUIController.changeMapMode( EnumMapUI.NorthUP_2D );
|
||||
}
|
||||
ivMode.setSelected(!ivMode.isSelected());
|
||||
ivMode.setSelected( !ivMode.isSelected() );
|
||||
ivMode.setText(
|
||||
getString(ivMode.isSelected() ? R.string.mode_car_up : R.string.mode_north_up));
|
||||
getString( ivMode.isSelected() ? R.string.mode_car_up : R.string.mode_north_up ) );
|
||||
}
|
||||
});
|
||||
} );
|
||||
|
||||
mSpeedLimit = findViewById(R.id.module_entrance_id_speed_limit_container);
|
||||
mSpeedLimitValue = findViewById(R.id.module_entrance_id_speed_limit_value);
|
||||
mSpeedLimitUnit = findViewById(R.id.module_entrance_id_speed_limit_unit);
|
||||
mSpeedLimit = findViewById( R.id.module_entrance_id_speed_limit_container );
|
||||
mSpeedLimitValue = findViewById( R.id.module_entrance_id_speed_limit_value );
|
||||
mSpeedLimitUnit = findViewById( R.id.module_entrance_id_speed_limit_unit );
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected EntrancePresenter createPresenter() {
|
||||
return new EntrancePresenter(getContext(), this);
|
||||
return new EntrancePresenter( getContext(), this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
mService = (IMogoMapService) ARouter.getInstance()
|
||||
.build(MogoServicePaths.PATH_SERVICES_MAP)
|
||||
.navigation(getContext());
|
||||
mMogoRegisterCenter = (IMogoRegisterCenter) ARouter.getInstance()
|
||||
.build(MogoServicePaths.PATH_REGISTER_CENTER)
|
||||
.navigation(getContext());
|
||||
public void onActivityCreated( @Nullable Bundle savedInstanceState ) {
|
||||
super.onActivityCreated( savedInstanceState );
|
||||
mService = ( IMogoMapService ) ARouter.getInstance()
|
||||
.build( MogoServicePaths.PATH_SERVICES_MAP )
|
||||
.navigation( getContext() );
|
||||
mMogoRegisterCenter = ( IMogoRegisterCenter ) ARouter.getInstance()
|
||||
.build( MogoServicePaths.PATH_REGISTER_CENTER )
|
||||
.navigation( getContext() );
|
||||
mMApUIController = mService.getMapUIController();
|
||||
mMogoLocationClient = mService.getSingletonLocationClient(getContext());
|
||||
mMogoNavi = mService.getNavi(getContext());
|
||||
mAnalytics = (IMogoAnalytics) ARouter.getInstance()
|
||||
.build(MogoServicePaths.PATH_UTILS_ANALYTICS)
|
||||
.navigation(getContext());
|
||||
mMogoStatusManager = (IMogoStatusManager) ARouter.getInstance()
|
||||
.build(MogoServicePaths.PATH_STATUS_MANAGER)
|
||||
.navigation(getContext());
|
||||
mMogoLocationClient = mService.getSingletonLocationClient( getContext() );
|
||||
mMogoNavi = mService.getNavi( getContext() );
|
||||
mAnalytics = ( IMogoAnalytics ) ARouter.getInstance()
|
||||
.build( MogoServicePaths.PATH_UTILS_ANALYTICS )
|
||||
.navigation( getContext() );
|
||||
mMogoStatusManager = ( IMogoStatusManager ) ARouter.getInstance()
|
||||
.build( MogoServicePaths.PATH_STATUS_MANAGER )
|
||||
.navigation( getContext() );
|
||||
|
||||
mMogoRegisterCenter.registerMogoNaviListener(ExtensionsModuleConst.TYPE_ENTRANCE, this);
|
||||
mMogoRegisterCenter.registerMogoMapListener(ExtensionsModuleConst.TYPE_ENTRANCE, this);
|
||||
mMogoRegisterCenter.registerMogoNaviListener( ExtensionsModuleConst.TYPE_ENTRANCE, this );
|
||||
mMogoRegisterCenter.registerMogoMapListener( ExtensionsModuleConst.TYPE_ENTRANCE, this );
|
||||
|
||||
mMogoMarkerManager = mService.getMarkerManager(getContext());
|
||||
mMogoMarkerManager = mService.getMarkerManager( getContext() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -224,30 +225,30 @@ public class EntranceFragment extends MvpFragment<EntranceView, EntrancePresente
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNaviInfoUpdate(MogoNaviInfo naviinfo) {
|
||||
if (naviinfo == null) {
|
||||
public void onNaviInfoUpdate( MogoNaviInfo naviinfo ) {
|
||||
if ( naviinfo == null ) {
|
||||
return;
|
||||
}
|
||||
mNaviInfo.notifyChanged(naviinfo);
|
||||
mNaviInfo.notifyChanged( naviinfo );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartNavi() {
|
||||
mCommonAddress.setVisibility(View.GONE);
|
||||
mNaviInfo.setVisibility(View.VISIBLE);
|
||||
ivMode.setVisibility(View.VISIBLE);
|
||||
mExitNavi.setVisibility(View.VISIBLE);
|
||||
mMApUIController.setPointToCenter(0.675926, 0.77552);
|
||||
mCommonAddress.setVisibility( View.GONE );
|
||||
mNaviInfo.setVisibility( View.VISIBLE );
|
||||
ivMode.setVisibility( View.VISIBLE );
|
||||
mExitNavi.setVisibility( View.VISIBLE );
|
||||
mMApUIController.setPointToCenter( 0.675926, 0.77552 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopNavi() {
|
||||
mCommonAddress.setVisibility(View.VISIBLE);
|
||||
mNaviInfo.setVisibility(View.GONE);
|
||||
ivMode.setVisibility(View.GONE);
|
||||
mExitNavi.setVisibility(View.GONE);
|
||||
mSpeedLimit.setVisibility(View.GONE);
|
||||
mMApUIController.setPointToCenter(0.66145, 0.590688);
|
||||
mCommonAddress.setVisibility( View.VISIBLE );
|
||||
mNaviInfo.setVisibility( View.GONE );
|
||||
ivMode.setVisibility( View.GONE );
|
||||
mExitNavi.setVisibility( View.GONE );
|
||||
mSpeedLimit.setVisibility( View.GONE );
|
||||
mMApUIController.setPointToCenter( 0.66145, 0.590688 );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -259,16 +260,16 @@ public class EntranceFragment extends MvpFragment<EntranceView, EntrancePresente
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdateTraffic(MogoTraffic traffic) {
|
||||
if (traffic == null) {
|
||||
public void onUpdateTraffic( MogoTraffic traffic ) {
|
||||
if ( traffic == null ) {
|
||||
return;
|
||||
}
|
||||
if (traffic.getSpeedLimit() <= 0) {
|
||||
mSpeedLimit.setVisibility(View.INVISIBLE);
|
||||
mSpeedLimitValue.setText("--");
|
||||
if ( traffic.getSpeedLimit() <= 0 ) {
|
||||
mSpeedLimit.setVisibility( View.INVISIBLE );
|
||||
mSpeedLimitValue.setText( "--" );
|
||||
} else {
|
||||
mSpeedLimit.setVisibility(View.VISIBLE);
|
||||
mSpeedLimitValue.setText(String.valueOf(traffic.getSpeedLimit()));
|
||||
mSpeedLimit.setVisibility( View.VISIBLE );
|
||||
mSpeedLimitValue.setText( String.valueOf( traffic.getSpeedLimit() ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,43 +279,43 @@ public class EntranceFragment extends MvpFragment<EntranceView, EntrancePresente
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTouch(MotionEvent motionEvent) {
|
||||
public void onTouch( MotionEvent motionEvent ) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPOIClick(MogoPoi poi) {
|
||||
public void onPOIClick( MogoPoi poi ) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapClick(MogoLatLng latLng) {
|
||||
public void onMapClick( MogoLatLng latLng ) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLockMap(boolean isLock) {
|
||||
public void onLockMap( boolean isLock ) {
|
||||
mIsLock = isLock;
|
||||
if (isLock) {
|
||||
mExitNavi.setText(R.string.module_ext_str_exit_navi);
|
||||
if ( isLock ) {
|
||||
mExitNavi.setText( R.string.module_ext_str_exit_navi );
|
||||
} else {
|
||||
mExitNavi.setText(R.string.module_ext_str_exit_navi);
|
||||
mExitNavi.setText( R.string.module_ext_str_exit_navi );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapModeChanged(EnumMapUI ui) {
|
||||
public void onMapModeChanged( EnumMapUI ui ) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapChanged(MogoLatLng latLng, float zoom, float tilt, float bearing) {
|
||||
public void onMapChanged( MogoLatLng latLng, float zoom, float tilt, float bearing ) {
|
||||
|
||||
}
|
||||
|
||||
private void traceData(String from) {
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put("from", from);
|
||||
mAnalytics.track("Launcher_Share_Click", properties);
|
||||
private void traceData( String from ) {
|
||||
Map< String, Object > properties = new HashMap<>();
|
||||
properties.put( "from", from );
|
||||
mAnalytics.track( "Launcher_Share_Click", properties );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import com.mogo.service.intent.IMogoIntentListener;
|
||||
import com.mogo.service.intent.IMogoIntentManager;
|
||||
import com.mogo.service.map.IMogoMapService;
|
||||
import com.mogo.service.module.IMogoModuleProvider;
|
||||
import com.mogo.service.statusmanager.IMogoStatusManager;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
|
||||
import org.json.JSONException;
|
||||
@@ -65,9 +66,10 @@ public class MainActivity extends MvpActivity< MainView, MainPresenter > impleme
|
||||
private MogoModulesHandler mMogoModuleHandler;
|
||||
private IMogoCardManager mMogoCardManager;
|
||||
private IMogoFragmentManager mMogoFragmentManager;
|
||||
private IMogoStatusManager mMogoStatusManager;
|
||||
|
||||
private OrientedViewPager mCardsContainer;
|
||||
private VerticalStackTransformer mTransformer;
|
||||
//private VerticalStackTransformer mTransformer;
|
||||
private CardModulesAdapter mCardModulesAdapter;
|
||||
|
||||
private View mHeader;
|
||||
@@ -98,75 +100,68 @@ 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 );
|
||||
mTransformer = new VerticalStackTransformer( this );
|
||||
mCardsContainer.setOnPageChangeListener(
|
||||
mOnPageChangeListener = new OnPageChangeListenerAdapter() {
|
||||
private boolean mIsLast = true;
|
||||
private boolean mCardFlipStatus = false;
|
||||
mCardsContainer.setOrientation( OrientedViewPager.Orientation.HORIZONTAL );
|
||||
//mTransformer = new VerticalStackTransformer( this );
|
||||
mCardsContainer.setOnPageChangeListener( mOnPageChangeListener = new OnPageChangeListenerAdapter() {
|
||||
private boolean mIsLast = true;
|
||||
private boolean mCardFlipStatus = false;
|
||||
|
||||
@Override
|
||||
public void onPageSelected( int position ) {
|
||||
final long start = System.currentTimeMillis();
|
||||
try {
|
||||
IMogoModuleProvider provider =
|
||||
mCardModulesAdapter.getProvider( mCurrentPosition );
|
||||
mPresenter.postTrackLastCardShowEvent( provider );
|
||||
mCurrentPosition = position;
|
||||
provider = mCardModulesAdapter.getProvider( mCurrentPosition );
|
||||
mMogoModuleHandler.setModuleEnable( provider.getModuleName() );
|
||||
mMogoCardManager.invoke( position,
|
||||
mMogoModuleHandler.getCurrentModuleName() );
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Logger.i( TAG,
|
||||
"onPageSelected cost " + ( System.currentTimeMillis() - start ) + "ms" );
|
||||
@Override
|
||||
public void onPageSelected( int position ) {
|
||||
final long start = System.currentTimeMillis();
|
||||
try {
|
||||
IMogoModuleProvider provider = mCardModulesAdapter.getProvider( mCurrentPosition );
|
||||
mPresenter.postTrackLastCardShowEvent( provider );
|
||||
mCurrentPosition = position;
|
||||
provider = mCardModulesAdapter.getProvider( mCurrentPosition );
|
||||
mMogoModuleHandler.setModuleEnable( provider.getModuleName() );
|
||||
mMogoCardManager.invoke( position, mMogoModuleHandler.getCurrentModuleName() );
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Logger.i( TAG, "onPageSelected cost " + ( System.currentTimeMillis() - start ) + "ms" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged( int state ) {
|
||||
final long start = System.currentTimeMillis();
|
||||
super.onPageScrollStateChanged( state );
|
||||
if ( state == ViewPager.SCROLL_STATE_DRAGGING ) {
|
||||
if ( !mCardFlipStatus ) {
|
||||
mCardFlipStatus = true;
|
||||
final IMogoModuleProvider provider = mCardModulesAdapter.getProvider( mCurrentPosition );
|
||||
mPresenter.postTrackCardFlipEvent( provider );
|
||||
}
|
||||
} else if ( state == ViewPager.SCROLL_STATE_IDLE ) {
|
||||
mCardFlipStatus = false;
|
||||
//mTransformer.resetOffsetScroll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged( int state ) {
|
||||
final long start = System.currentTimeMillis();
|
||||
super.onPageScrollStateChanged( state );
|
||||
if ( state == ViewPager.SCROLL_STATE_DRAGGING ) {
|
||||
if ( !mCardFlipStatus ) {
|
||||
mCardFlipStatus = true;
|
||||
final IMogoModuleProvider provider =
|
||||
mCardModulesAdapter.getProvider( mCurrentPosition );
|
||||
mPresenter.postTrackCardFlipEvent( provider );
|
||||
}
|
||||
} else if ( state == ViewPager.SCROLL_STATE_IDLE ) {
|
||||
mCardFlipStatus = false;
|
||||
mTransformer.resetOffsetScroll();
|
||||
}
|
||||
int cardSize = mCardModulesAdapter.getCount();
|
||||
|
||||
int cardSize = mCardModulesAdapter.getCount();
|
||||
|
||||
if ( state == ViewPager.SCROLL_STATE_SETTLING ) {
|
||||
mIsLast = false;
|
||||
} else if ( state == ViewPager.SCROLL_STATE_IDLE && mIsLast ) {
|
||||
//此处为你需要的情况,再加入当前页码判断可知道是第一页还是最后一页
|
||||
if ( cardSize != 1 && mCurrentPosition == ( cardSize - 1 ) ) {
|
||||
mCardsContainer.setCurrentItem( 0, false );
|
||||
} else if ( cardSize != 1 && mCurrentPosition == 0 ) {
|
||||
mCardsContainer.setCurrentItem( cardSize - 1, false );
|
||||
}
|
||||
} else {
|
||||
mIsLast = true;
|
||||
}
|
||||
Logger.i( TAG, "onPageScrollStateChanged cost "
|
||||
+ ( System.currentTimeMillis() - start )
|
||||
+ "ms" );
|
||||
if ( state == ViewPager.SCROLL_STATE_SETTLING ) {
|
||||
mIsLast = false;
|
||||
} else if ( state == ViewPager.SCROLL_STATE_IDLE && mIsLast ) {
|
||||
//此处为你需要的情况,再加入当前页码判断可知道是第一页还是最后一页
|
||||
if ( cardSize != 1 && mCurrentPosition == ( cardSize - 1 ) ) {
|
||||
mCardsContainer.setCurrentItem( 0, false );
|
||||
} else if ( cardSize != 1 && mCurrentPosition == 0 ) {
|
||||
mCardsContainer.setCurrentItem( cardSize - 1, false );
|
||||
}
|
||||
} else {
|
||||
mIsLast = true;
|
||||
}
|
||||
Logger.i( TAG, "onPageScrollStateChanged cost " + ( System.currentTimeMillis() - start ) + "ms" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrolled( int position, float positionOffset,
|
||||
int positionOffsetPixels ) {
|
||||
super.onPageScrolled( position, positionOffset, positionOffsetPixels );
|
||||
Logger.d( TAG, "pageScrolled : offset --- " + positionOffset );
|
||||
mTransformer.offsetScrollChanged( positionOffset );
|
||||
}
|
||||
} );
|
||||
@Override
|
||||
public void onPageScrolled( int position, float positionOffset,
|
||||
int positionOffsetPixels ) {
|
||||
super.onPageScrolled( position, positionOffset, positionOffsetPixels );
|
||||
Logger.d( TAG, "pageScrolled : offset --- " + positionOffset );
|
||||
//mTransformer.offsetScrollChanged( positionOffset );
|
||||
}
|
||||
} );
|
||||
|
||||
mHeader = findViewById( R.id.module_main_id_header_fragment_container );
|
||||
mCards = findViewById( R.id.module_main_id_cards_container );
|
||||
@@ -261,6 +256,7 @@ public class MainActivity extends MvpActivity< MainView, MainPresenter > impleme
|
||||
} );
|
||||
|
||||
mMogoIntentManager = mServiceApis.getIntentManagerApi();
|
||||
mMogoStatusManager = mServiceApis.getStatusManagerApi();
|
||||
registerVoiceCmd();
|
||||
Log.i( "timer", "cost " + ( System.currentTimeMillis() - start ) + "ms" );
|
||||
}
|
||||
@@ -303,7 +299,7 @@ public class MainActivity extends MvpActivity< MainView, MainPresenter > impleme
|
||||
List< IMogoModuleProvider > providers = mMogoModuleHandler.loadCardsModule();
|
||||
mCardModulesAdapter = new CardModulesAdapter( this, providers );
|
||||
mCardsContainer.setOffscreenPageLimit( providers.size() );
|
||||
mCardsContainer.setPageTransformer( true, mTransformer );
|
||||
//mCardsContainer.setPageTransformer( true, mTransformer );
|
||||
mCardsContainer.setAdapter( mCardModulesAdapter );
|
||||
|
||||
mCardCoverUpBottomLayout.setVisibility( View.VISIBLE );
|
||||
@@ -324,7 +320,7 @@ public class MainActivity extends MvpActivity< MainView, MainPresenter > impleme
|
||||
|
||||
@Override
|
||||
public boolean onMarkerClicked( IMogoMarker marker ) {
|
||||
switch2Card( marker.getOwner() );
|
||||
switch2Card( marker.getOwner(), false );
|
||||
if ( mMogoModuleHandler != null ) {
|
||||
mMogoModuleHandler.onMarkerClicked( marker );
|
||||
}
|
||||
@@ -332,17 +328,23 @@ public class MainActivity extends MvpActivity< MainView, MainPresenter > impleme
|
||||
}
|
||||
|
||||
@Override
|
||||
public void switch2Card( String cardType ) {
|
||||
if ( mCardModulesAdapter != null ) {
|
||||
public void switch2Card( String cardType, boolean lockCar ) {
|
||||
if ( mCardModulesAdapter == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
int position = mCardModulesAdapter.getProviderPosition( cardType );
|
||||
if ( position != -1 ) {
|
||||
int lastFactPosition = mCardModulesAdapter.getFactPosition( mCurrentPosition );
|
||||
mCardsContainer.setCurrentItem( mCurrentPosition + position - lastFactPosition,
|
||||
Math.abs( lastFactPosition - position ) == 1 );
|
||||
} else {
|
||||
Logger.e( TAG, "Can't find type of %s's position", cardType );
|
||||
}
|
||||
int position = mCardModulesAdapter.getProviderPosition( cardType );
|
||||
if ( position != -1 ) {
|
||||
int lastFactPosition = mCardModulesAdapter.getFactPosition( mCurrentPosition );
|
||||
mCardsContainer.setCurrentItem( mCurrentPosition + position - lastFactPosition,
|
||||
Math.abs( lastFactPosition - position ) == 1 );
|
||||
} else {
|
||||
Logger.e( TAG, "Can't find type of %s's position", cardType );
|
||||
}
|
||||
|
||||
if ( lockCar ) {
|
||||
mMogoStatusManager.setUserInteractionStatus( TAG, true, false );
|
||||
mMogoMapUIController.recoverLockMode();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,11 +67,11 @@ public class MainPresenter extends Presenter< MainView > {
|
||||
@Override
|
||||
public void onCreate( @NonNull LifecycleOwner owner ) {
|
||||
super.onCreate( owner );
|
||||
CardSwitchLiveData.getInstance().observeForever( to -> {
|
||||
if ( TextUtils.isEmpty( to ) ) {
|
||||
CardSwitchLiveData.getInstance().observeForever( cardInfo -> {
|
||||
if ( TextUtils.isEmpty( cardInfo.mCardName ) ) {
|
||||
return;
|
||||
}
|
||||
mView.switch2Card( to );
|
||||
mView.switch2Card( cardInfo.mCardName, true );
|
||||
} );
|
||||
mAnalytics = ( IMogoAnalytics ) ARouter.getInstance().build( MogoServicePaths.PATH_UTILS_ANALYTICS ).navigation( getContext() );
|
||||
mCardStartShowTime = System.currentTimeMillis();
|
||||
|
||||
@@ -15,7 +15,7 @@ public interface MainView extends IView {
|
||||
*
|
||||
* @param cardType
|
||||
*/
|
||||
void switch2Card( String cardType );
|
||||
void switch2Card( String cardType, boolean lockCar );
|
||||
|
||||
/**
|
||||
* 加载卡片
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.mogo.module.main;
|
||||
import android.content.Context;
|
||||
|
||||
import com.alibaba.android.arouter.facade.annotation.Route;
|
||||
import com.mogo.module.main.livedata.CardInfo;
|
||||
import com.mogo.module.main.livedata.CardSwitchLiveData;
|
||||
import com.mogo.service.MogoServicePaths;
|
||||
import com.mogo.service.cardmanager.IMogoCardChangedListener;
|
||||
@@ -25,7 +26,7 @@ public class MogoCardManager implements IMogoCardManager {
|
||||
|
||||
@Override
|
||||
public void switch2( String cardType ) {
|
||||
CardSwitchLiveData.getInstance().postValue( cardType );
|
||||
CardSwitchLiveData.getInstance().postValue( new CardInfo( cardType, false ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,6 +52,11 @@ public class MogoCardManager implements IMogoCardManager {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void switch2( String cardType, boolean lockCar ) {
|
||||
CardSwitchLiveData.getInstance().postValue( new CardInfo( cardType, lockCar ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init( Context context ) {
|
||||
|
||||
|
||||
@@ -148,7 +148,8 @@ public class MogoModulesManager implements MogoModulesHandler,
|
||||
providers.add( provider );
|
||||
}
|
||||
}
|
||||
return sort( providers );
|
||||
return providers;
|
||||
// return sort( providers ); v2.0.2暂不支持变顺序
|
||||
}
|
||||
|
||||
private List< IMogoModuleProvider > sort( List< IMogoModuleProvider > modules ) {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.mogo.module.main.livedata;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-03-09
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class CardInfo implements Parcelable {
|
||||
|
||||
public String mCardName;
|
||||
public boolean mLockCar;
|
||||
|
||||
public CardInfo( String cardName, boolean lockCar ) {
|
||||
this.mCardName = cardName;
|
||||
this.mLockCar = lockCar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel( Parcel dest, int flags ) {
|
||||
dest.writeString( this.mCardName );
|
||||
dest.writeByte( this.mLockCar ? ( byte ) 1 : ( byte ) 0 );
|
||||
}
|
||||
|
||||
protected CardInfo( Parcel in ) {
|
||||
this.mCardName = in.readString();
|
||||
this.mLockCar = in.readByte() != 0;
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator< CardInfo > CREATOR = new Parcelable.Creator< CardInfo >() {
|
||||
@Override
|
||||
public CardInfo createFromParcel( Parcel source ) {
|
||||
return new CardInfo( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CardInfo[] newArray( int size ) {
|
||||
return new CardInfo[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import androidx.lifecycle.MutableLiveData;
|
||||
* <p>
|
||||
* 切换卡片
|
||||
*/
|
||||
public class CardSwitchLiveData extends MutableLiveData< String > {
|
||||
public class CardSwitchLiveData extends MutableLiveData< CardInfo > {
|
||||
|
||||
private CardSwitchLiveData() {
|
||||
// private constructor
|
||||
|
||||
BIN
modules/mogo-module-main/src/main/res/drawable-xhdpi/module_apps_bg_card.png
Executable file
|
After Width: | Height: | Size: 60 KiB |
@@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
@@ -9,9 +8,7 @@
|
||||
<FrameLayout
|
||||
android:id="@+id/module_main_id_map_fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintLeft_toRightOf="@+id/module_main_id_apps_fragment_container"
|
||||
app:layout_constraintRight_toRightOf="parent" />
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/module_main_id_map_top_shadow_frame"
|
||||
@@ -27,68 +24,60 @@
|
||||
android:background="@drawable/module_main_dw_left_frame_bkg"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<LinearLayout
|
||||
<FrameLayout
|
||||
android:id="@+id/module_main_id_header_fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/module_ext_height" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/module_main_card_container_frame"
|
||||
android:layout_width="@dimen/module_main_card_container_width"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/module_main_id_header_fragment_container"
|
||||
android:layout_marginLeft="@dimen/module_main_card_container_marginLeft"
|
||||
android:layout_marginTop="@dimen/module_main_card_container_marginTop">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:src="@drawable/module_apps_bg_card"
|
||||
android:layout_height="@dimen/dp_797"/>
|
||||
<com.mogo.module.main.cards.OrientedViewPager
|
||||
android:id="@+id/module_main_id_cards_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginLeft="@dimen/dp_30"
|
||||
android:layout_marginRight="@dimen/dp_30"
|
||||
android:layout_height="@dimen/dp_600"
|
||||
android:clipToPadding="false"
|
||||
android:overScrollMode="never" />
|
||||
|
||||
<!-- 应用入口-->
|
||||
<FrameLayout
|
||||
android:id="@+id/module_main_id_apps_fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/module_main_id_card_cover_up_bottom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dp_26"
|
||||
android:layout_marginTop="@dimen/dp_600"
|
||||
android:layout_marginLeft="@dimen/dp_64"
|
||||
android:layout_marginRight="@dimen/dp_64"
|
||||
android:background="@drawable/module_main_card_cover_up_bottom"
|
||||
/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<!--快捷操作浮层-->
|
||||
<FrameLayout
|
||||
android:id="@+id/module_main_id_entrance_fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 小智语音-->
|
||||
<FrameLayout
|
||||
android:id="@+id/module_main_id_header_fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginTop="@dimen/module_main_card_container_marginTop"
|
||||
android:layout_height="match_parent">
|
||||
<!-- 卡片-->
|
||||
<FrameLayout
|
||||
android:layout_width="@dimen/module_main_card_container_width"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="@dimen/module_main_card_container_marginLeft">
|
||||
|
||||
<com.mogo.module.main.cards.OrientedViewPager
|
||||
android:id="@+id/module_main_id_cards_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/module_main_card_container_height"
|
||||
android:layout_marginBottom="@dimen/module_main_card_container_marginBottom"
|
||||
android:clipToPadding="false"
|
||||
android:overScrollMode="never"
|
||||
android:paddingBottom="@dimen/module_main_card_container_paddingBottom" />
|
||||
|
||||
<!-- 应用入口-->
|
||||
<FrameLayout
|
||||
android:id="@+id/module_main_id_apps_fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/module_main_id_card_cover_up_bottom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="20px"
|
||||
android:visibility="gone"
|
||||
android:layout_marginTop="@dimen/module_main_card_cover_up_margin"
|
||||
android:layout_marginLeft="15px"
|
||||
android:layout_marginRight="15px"
|
||||
android:background="@drawable/module_main_card_cover_up_bottom"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<!--快捷操作浮层-->
|
||||
<FrameLayout
|
||||
android:id="@+id/module_main_id_entrance_fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
android:layout_below="@+id/module_main_id_header_fragment_container"
|
||||
android:layout_marginTop="@dimen/module_main_card_container_marginTop"
|
||||
android:layout_toRightOf="@+id/module_main_card_container_frame" />
|
||||
|
||||
<!-- 浮层-->
|
||||
<FrameLayout
|
||||
@@ -104,6 +93,6 @@
|
||||
<FrameLayout
|
||||
android:id="@+id/module_main_id_cover_up"
|
||||
android:layout_width="match_parent"
|
||||
android:background="@drawable/module_main_launcher_bg"
|
||||
android:layout_height="match_parent"/>
|
||||
</FrameLayout>
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/module_main_launcher_bg" />
|
||||
</RelativeLayout>
|
||||
@@ -22,13 +22,12 @@ import com.mogo.service.statusmanager.StatusDescriptor;
|
||||
* <p>
|
||||
* 地图图层,地图操作都在这个图层完成
|
||||
*/
|
||||
public class MapFragment extends MvpFragment< MapView, MapPresenter > implements MapView, IMogoStatusChangedListener {
|
||||
public class MapFragment extends MvpFragment< MapView, MapPresenter > implements MapView {
|
||||
|
||||
private static final String TAG = "MapFragment";
|
||||
|
||||
private MogoMapView mMogoMapView;
|
||||
private IMogoMap mMogoMap;
|
||||
private IMogoStatusManager mMogoStatusManager;
|
||||
|
||||
private boolean mIsControllerByOthersStatus = false;
|
||||
|
||||
@@ -67,8 +66,6 @@ public class MapFragment extends MvpFragment< MapView, MapPresenter > implements
|
||||
// mMogoMapView.onCreate( savedInstanceState );
|
||||
//}
|
||||
initMapView();
|
||||
mMogoStatusManager = ( IMogoStatusManager ) ARouter.getInstance().build( MogoServicePaths.PATH_STATUS_MANAGER ).navigation( getContext() );
|
||||
mMogoStatusManager.registerStatusChangedListener( TAG, StatusDescriptor.APP_LIST_UI, this );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -134,18 +131,6 @@ public class MapFragment extends MvpFragment< MapView, MapPresenter > implements
|
||||
return mMogoMap.getUIController();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged( StatusDescriptor descriptor, boolean isTrue ) {
|
||||
if ( descriptor == StatusDescriptor.APP_LIST_UI ) {
|
||||
mIsControllerByOthersStatus = isTrue;
|
||||
if ( isTrue ) {
|
||||
mMogoMapView.onPause();
|
||||
} else {
|
||||
mMogoMapView.onResume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
|
||||
@@ -29,6 +29,11 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility 1.8
|
||||
targetCompatibility 1.8
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.mogo.map.uicontroller.IMogoMapUIController;
|
||||
import com.mogo.module.common.entity.MarkerResponse;
|
||||
import com.mogo.module.common.entity.MarkerShowEntity;
|
||||
import com.mogo.module.service.marker.MapMarkerManager;
|
||||
import com.mogo.service.IMogoServiceApis;
|
||||
import com.mogo.service.MogoServicePaths;
|
||||
import com.mogo.service.analytics.IMogoAnalytics;
|
||||
import com.mogo.service.cardmanager.IMogoCardManager;
|
||||
@@ -28,6 +29,7 @@ import com.mogo.service.statusmanager.IMogoStatusManager;
|
||||
public class MarkerServiceHandler {
|
||||
private static final String TAG = "MarkerServiceHandler";
|
||||
|
||||
private static IMogoServiceApis mApis;
|
||||
|
||||
private static IMogoMapService mMapService;
|
||||
private static IMogoMarkerManager mMarkerManager;
|
||||
@@ -44,22 +46,22 @@ public class MarkerServiceHandler {
|
||||
|
||||
private static MapMarkerManager mMapMarkerManager;
|
||||
|
||||
public static void init( final Context context ) {
|
||||
mApis = ( IMogoServiceApis ) ARouter.getInstance().build( MogoServicePaths.PATH_SERVICE_APIS ).navigation( context );
|
||||
mMapService = mApis.getMapServiceApi();
|
||||
mImageloader = mApis.getImageLoaderApi();
|
||||
mMogoStatusManager = mApis.getStatusManagerApi();
|
||||
mMogoSocketManager = mApis.getSocketManagerApi( context );
|
||||
mMogoCardManager = mApis.getCardManagerApi();
|
||||
mMogoAnalytics = mApis.getAnalyticsApi();
|
||||
|
||||
public static void init(final Context context) {
|
||||
mMapService = (IMogoMapService) ARouter.getInstance().build(MogoServicePaths.PATH_SERVICES_MAP).navigation(context);
|
||||
mImageloader = (IMogoImageloader) ARouter.getInstance().build(MogoServicePaths.PATH_UTILS_IMAGE_LOADER).navigation(context);
|
||||
mMogoStatusManager = (IMogoStatusManager) ARouter.getInstance().build(MogoServicePaths.PATH_STATUS_MANAGER).navigation(context);
|
||||
mMogoSocketManager = (IMogoSocketManager) ARouter.getInstance().build(MogoServicePaths.PATH_SOCKET_MANAGER).navigation();
|
||||
mMogoCardManager = (IMogoCardManager) ARouter.getInstance().build(MogoServicePaths.PATH_CARD_MANAGER).navigation();
|
||||
mMogoAnalytics = (IMogoAnalytics) ARouter.getInstance().build(MogoServicePaths.PATH_UTILS_ANALYTICS).navigation();
|
||||
|
||||
mMarkerManager = mMapService.getMarkerManager(context);
|
||||
mNavi = mMapService.getNavi(context);
|
||||
mMarkerManager = mMapService.getMarkerManager( context );
|
||||
mNavi = mMapService.getNavi( context );
|
||||
mMapUIController = mMapService.getMapUIController();
|
||||
mLocationClient = mMapService.getSingletonLocationClient(context);
|
||||
mLocationClient = mMapService.getSingletonLocationClient( context );
|
||||
|
||||
mMapMarkerManager = MapMarkerManager.getInstance(context);
|
||||
mMapMarkerManager.init(context);
|
||||
mMapMarkerManager = MapMarkerManager.getInstance();
|
||||
mMapMarkerManager.init( context );
|
||||
}
|
||||
|
||||
public static IMogoMapService getMapService() {
|
||||
@@ -112,30 +114,33 @@ public class MarkerServiceHandler {
|
||||
/**
|
||||
* 绘制Marker
|
||||
* 建议使用
|
||||
*
|
||||
* @see MapMarkerManager#drawMapMarker(MarkerResponse)
|
||||
*/
|
||||
@Deprecated
|
||||
public static void drawMapMarker(MarkerResponse response) {
|
||||
getMapMarkerManager().drawMapMarker(response);
|
||||
public static void drawMapMarker( MarkerResponse response ) {
|
||||
getMapMarkerManager().drawMapMarker( response );
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制Marker
|
||||
* 建议使用
|
||||
*
|
||||
* @see MapMarkerManager#drawMapMarker(MarkerShowEntity)
|
||||
*/
|
||||
@Deprecated
|
||||
public static void drawMapMarker(MarkerShowEntity markerShowEntity) {
|
||||
getMapMarkerManager().drawMapMarker(markerShowEntity);
|
||||
public static void drawMapMarker( MarkerShowEntity markerShowEntity ) {
|
||||
getMapMarkerManager().drawMapMarker( markerShowEntity );
|
||||
}
|
||||
|
||||
/**
|
||||
* 对指定类型高亮处理
|
||||
* 建议使用
|
||||
* @see MapMarkerManager#highlightedMarker(String,boolean)
|
||||
*
|
||||
* @see MapMarkerManager#highlightedMarker(String, boolean)
|
||||
*/
|
||||
@Deprecated
|
||||
public static void highlightedMarker(String typeTag) {
|
||||
getMapMarkerManager().highlightedMarker(typeTag,false);
|
||||
public static void highlightedMarker( String typeTag ) {
|
||||
getMapMarkerManager().highlightedMarker( typeTag, false );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import android.content.IntentFilter;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.Trace;
|
||||
import android.text.TextUtils;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
@@ -143,11 +144,7 @@ public class MogoServices implements IMogoMapListener,
|
||||
mRefreshRemainingTime -= ServiceConst.DECREASE_INTERVAL;
|
||||
if ( mRefreshRemainingTime == 0 ) {
|
||||
Logger.d( TAG, "move to center and refresh data." );
|
||||
mStatusManager.setUserInteractionStatus( ServiceConst.TYPE, true, false );
|
||||
mUiController.recoverLockMode();
|
||||
mStatusManager.setUserInteractionStatus( TAG, true, false );
|
||||
mUiController.changeZoom( 16.0f );
|
||||
notifyRefreshData( mLastAutoRefreshLocation, getQueryRadius(), mAutoRefreshCallback );
|
||||
invokeAutoRefresh();
|
||||
} else {
|
||||
mHandler.sendEmptyMessageDelayed( msg.what, ServiceConst.DECREASE_INTERVAL );
|
||||
}
|
||||
@@ -158,11 +155,21 @@ public class MogoServices implements IMogoMapListener,
|
||||
}
|
||||
if ( mLoopRequest ) {
|
||||
Logger.d( TAG, "补偿刷新触发" );
|
||||
notifyRefreshData( mLastAutoRefreshLocation, getQueryRadius(), mAutoRefreshCallback );
|
||||
invokeAutoRefresh();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动刷新:锁车、缩放比例:16、半径 2KM
|
||||
*/
|
||||
private void invokeAutoRefresh() {
|
||||
mStatusManager.setUserInteractionStatus( ServiceConst.TYPE, true, false );
|
||||
mUiController.setLockZoom( ServiceConst.DEFAULT_LOCK_CAR_ZOOM_LEVEL );
|
||||
mUiController.recoverLockMode();
|
||||
notifyRefreshData( mLastAutoRefreshLocation, ServiceConst.DEFAULT_AUTO_REFRESH_DATA_RADIUS, mAutoRefreshCallback );
|
||||
}
|
||||
};
|
||||
private Context mContext;
|
||||
|
||||
@@ -246,6 +253,7 @@ public class MogoServices implements IMogoMapListener,
|
||||
registerCenter.registerMogoLocationListener( ServiceConst.TYPE, this );
|
||||
registerCenter.registerMogoNaviListener( ServiceConst.TYPE, this );
|
||||
registerCenter.registerMogoMapListener( ServiceConst.TYPE, this );
|
||||
registerCenter.registerMogoAimlessModeListener( ServiceConst.TYPE, this );
|
||||
|
||||
mIntentManager = ( IMogoIntentManager ) ARouter.getInstance().build( MogoServicePaths.PATH_INTENT_MANAGER ).navigation( context );
|
||||
mIntentManager.registerIntentListener( MogoReceiver.ACTIION_ADAS, this );
|
||||
@@ -454,6 +462,7 @@ public class MogoServices implements IMogoMapListener,
|
||||
*/
|
||||
private boolean invokeRefreshWhenTranslationByUser( MogoLatLng latLng ) {
|
||||
try {
|
||||
Trace.beginSection( "timer.invokeRefreshWhenTranslationByUser" );
|
||||
float factor = 0.0f;
|
||||
if ( mIsVertical ) {
|
||||
factor = getMapCameraFactWidth();
|
||||
@@ -465,6 +474,7 @@ public class MogoServices implements IMogoMapListener,
|
||||
}
|
||||
Logger.d( TAG, "invokeRefreshWhenTranslationByUser,mLastCustomRefreshCenterLocation = %s, latLng = %s", mLastCustomRefreshCenterLocation, latLng );
|
||||
float distance = Utils.calculateLineDistance( latLng, mLastCustomRefreshCenterLocation );
|
||||
Trace.endSection();
|
||||
return distance > factor;
|
||||
} catch ( Exception e ) {
|
||||
Logger.e( TAG, e, "warming. " );
|
||||
@@ -500,7 +510,7 @@ public class MogoServices implements IMogoMapListener,
|
||||
mStatusManager.setUserInteractionStatus( ServiceConst.TYPE, true, false );
|
||||
mUiController.recoverLockMode();
|
||||
mStatusManager.setUserInteractionStatus( TAG, true, false );
|
||||
mUiController.changeZoom( 16.0f );
|
||||
mUiController.changeZoom( ServiceConst.DEFAULT_ZOOM_LEVEL );
|
||||
mLastAutoRefreshLocation = point;
|
||||
notifyRefreshData( mLastAutoRefreshLocation, getQueryRadius(), mAutoRefreshCallback );
|
||||
}
|
||||
@@ -548,8 +558,8 @@ public class MogoServices implements IMogoMapListener,
|
||||
case USER_INTERACTED:
|
||||
if ( isTrue && !mRefreshRemainingTimeStatus ) {
|
||||
mRefreshRemainingTimeStatus = true;
|
||||
mRefreshRemainingTime += mAutoRefreshStrategy.getInterruptInterval();
|
||||
Logger.i( TAG, "用户状态改变,自动刷新时间延时,%s ms后自动刷新", mRefreshRemainingTime );
|
||||
mRefreshRemainingTime = ServiceConst.DEFAULT_AUTO_REFRESH_WHEN_INTERRUPT;
|
||||
Logger.i( TAG, "用户状态改变,下次刷新时间:%ss后", mRefreshRemainingTime );
|
||||
}
|
||||
break;
|
||||
case SEARCH_UI:
|
||||
@@ -636,7 +646,7 @@ public class MogoServices implements IMogoMapListener,
|
||||
return;
|
||||
}
|
||||
int status = intent.getIntExtra( MogoReceiver.PARAM_ADAS_STATUS, 0 );
|
||||
mUiController.setLockZoom( status == 1 ? 15 : 16 );
|
||||
mUiController.setLockZoom( status == 1 ? 15 : ServiceConst.DEFAULT_LOCK_CAR_ZOOM_LEVEL );
|
||||
mStatusManager.setADASUIShow( ServiceConst.TYPE, status == 1 );
|
||||
mUiController.showMyLocation( true );
|
||||
} else if ( Intent.ACTION_POWER_CONNECTED.equals( command ) ) {
|
||||
|
||||
@@ -62,4 +62,30 @@ public class ServiceConst {
|
||||
*/
|
||||
public static final String CARD_TYPE_NOVELTY = "CARD_TYPE_NOVELTY";
|
||||
|
||||
/**
|
||||
* 运营位
|
||||
*/
|
||||
public static final String CARD_TYPE_BUSINESS_OPERATION = "CARD_TYPE_BUSINESS_OPERATION";
|
||||
|
||||
/**
|
||||
* 默认地图缩放比例
|
||||
*/
|
||||
public static final float DEFAULT_ZOOM_LEVEL = 16.0f;
|
||||
|
||||
/**
|
||||
* 默认地图锁车缩放比例
|
||||
*/
|
||||
public static final int DEFAULT_LOCK_CAR_ZOOM_LEVEL = 16;
|
||||
|
||||
/**
|
||||
* 自动酸辛默认半径
|
||||
*/
|
||||
public static final int DEFAULT_AUTO_REFRESH_DATA_RADIUS = 2_000;
|
||||
|
||||
/**
|
||||
* 30 s
|
||||
*/
|
||||
public static final int DEFAULT_AUTO_REFRESH_WHEN_INTERRUPT = 30 * 1_000;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@ public class AutoRefreshStrategy {
|
||||
private long interval = 3 * ONE_MINUTE;
|
||||
|
||||
/**
|
||||
* 用户打断后的延时(s)
|
||||
* 用户打断后的延时(s)【2.0.2后不再延时】
|
||||
*/
|
||||
private long interruptInterval = 1 * ONE_MINUTE;
|
||||
private long interruptInterval = 0 * ONE_MINUTE;
|
||||
|
||||
/**
|
||||
* 距离(米)
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.mogo.service;
|
||||
import android.content.Context;
|
||||
|
||||
import com.alibaba.android.arouter.facade.template.IProvider;
|
||||
import com.mogo.service.adas.IMogoADASController;
|
||||
import com.mogo.service.analytics.IMogoAnalytics;
|
||||
import com.mogo.service.cardmanager.IMogoCardManager;
|
||||
import com.mogo.service.connection.IMogoSocketManager;
|
||||
@@ -103,7 +104,7 @@ public interface IMogoServiceApis extends IProvider {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
IMogoSettingManager getSettingManager();
|
||||
IMogoSettingManager getSettingManagerApi();
|
||||
|
||||
/**
|
||||
* 网络接口api
|
||||
@@ -129,5 +130,12 @@ public interface IMogoServiceApis extends IProvider {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
IMogoWindowManager getWindowManager();
|
||||
IMogoWindowManager getWindowManagerApi();
|
||||
|
||||
/**
|
||||
* 辅助驾驶控制接口
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
IMogoADASController getAdasControllerApi();
|
||||
}
|
||||
|
||||
@@ -132,6 +132,12 @@ public class MogoServicePaths {
|
||||
@Deprecated
|
||||
public static final String PATH_DATA_MANAGER = "/datamanager/api";
|
||||
|
||||
/**
|
||||
* adas 控制
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String PATH_ADAS_CONTROLLER = "/adascontroller/api";
|
||||
|
||||
/**
|
||||
* 接口集合
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.mogo.service.adas;
|
||||
|
||||
import com.alibaba.android.arouter.facade.template.IProvider;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-03-10
|
||||
* <p>
|
||||
* v2x 页面控制
|
||||
*/
|
||||
public interface IMogoADASController extends IProvider {
|
||||
|
||||
/**
|
||||
* 打开adas
|
||||
*/
|
||||
void openADAS();
|
||||
|
||||
/**
|
||||
* 关闭adas
|
||||
*/
|
||||
void closeADAS();
|
||||
|
||||
}
|
||||
@@ -12,11 +12,21 @@ public interface IMogoCardManager extends IProvider {
|
||||
|
||||
/**
|
||||
* 切换卡片
|
||||
* <p>
|
||||
* 实际调用 switch2(cardType, false)
|
||||
*
|
||||
* @param cardType
|
||||
*/
|
||||
void switch2( String cardType );
|
||||
|
||||
/**
|
||||
* 切换卡片
|
||||
*
|
||||
* @param cardType 卡片类型
|
||||
* @param lockCar 是否锁车[将视图拉回车位]
|
||||
*/
|
||||
void switch2( String cardType, boolean lockCar );
|
||||
|
||||
/**
|
||||
* 注册卡片切换监听
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.mogo.service.datamanager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-02-11
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.mogo.map.marker.IMogoMarkerManager;
|
||||
import com.mogo.map.navi.IMogoNavi;
|
||||
import com.mogo.map.navi.IMogoNaviListener;
|
||||
import com.mogo.map.navi.IMogoNaviListenerRegister;
|
||||
import com.mogo.map.overlay.IMogoOverlayManager;
|
||||
import com.mogo.map.search.geo.IMogoGeoSearch;
|
||||
import com.mogo.map.search.inputtips.IMogoInputtipsSearch;
|
||||
import com.mogo.map.search.inputtips.query.MogoInputtipsQuery;
|
||||
@@ -68,7 +69,8 @@ public interface IMogoMapService extends IProvider {
|
||||
*/
|
||||
IMogoPoiSearch getPoiSearch( Context context, MogoPoiSearchQuery query );
|
||||
|
||||
/**f
|
||||
/**
|
||||
* f
|
||||
* 获取导航操作实例
|
||||
*
|
||||
* @param context
|
||||
@@ -96,4 +98,12 @@ public interface IMogoMapService extends IProvider {
|
||||
* @return
|
||||
*/
|
||||
IMogoHosListenerRegister getHostListenerRegister();
|
||||
|
||||
/**
|
||||
* 覆盖物操作
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
IMogoOverlayManager getOverlayManager( Context context );
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.alibaba.android.arouter.launcher.ARouter;
|
||||
import com.mogo.connection.socket.SocketManager;
|
||||
import com.mogo.service.IMogoServiceApis;
|
||||
import com.mogo.service.MogoServicePaths;
|
||||
import com.mogo.service.adas.IMogoADASController;
|
||||
import com.mogo.service.analytics.IMogoAnalytics;
|
||||
import com.mogo.service.cardmanager.IMogoCardManager;
|
||||
import com.mogo.service.connection.IMogoSocketManager;
|
||||
@@ -114,15 +115,20 @@ public class MogoServiceApis implements IMogoServiceApis {
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMogoSettingManager getSettingManager() {
|
||||
public IMogoSettingManager getSettingManagerApi() {
|
||||
return getApiInstance( IMogoSettingManager.class, MogoServicePaths.PATH_SETTING_MANAGER );
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMogoWindowManager getWindowManager() {
|
||||
public IMogoWindowManager getWindowManagerApi() {
|
||||
return getApiInstance( IMogoWindowManager.class, MogoServicePaths.PATH_WINDOW_MANAGER );
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMogoADASController getAdasControllerApi() {
|
||||
return getApiInstance( IMogoADASController.class, MogoServicePaths.PATH_ADAS_CONTROLLER );
|
||||
}
|
||||
|
||||
private static < T extends IProvider > T getApiInstance( Class< T > clazz, String path ) {
|
||||
T inst = SingletonsHolder.get( clazz );
|
||||
if ( inst == null ) {
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.mogo.service.impl.adas;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.alibaba.android.arouter.facade.annotation.Route;
|
||||
import com.mogo.commons.AbsMogoApplication;
|
||||
import com.mogo.service.MogoServicePaths;
|
||||
import com.mogo.service.adas.IMogoADASController;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-03-10
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
@Route( path = MogoServicePaths.PATH_ADAS_CONTROLLER )
|
||||
public class MogoADASController implements IMogoADASController {
|
||||
|
||||
private static final String TAG = "MogoADASController";
|
||||
|
||||
public static final String ACTION = "com.zhidao.speech.awake.notify";
|
||||
public static final String PARAM_COMMAND = "command";
|
||||
public static final String VAL_COMMAND = "system.application.operation";
|
||||
public static final String PARAM_DATA = "data";
|
||||
public static final String PARAM_OBJECT = "object";
|
||||
public static final String VAL_OBJECT = "辅助驾驶";
|
||||
public static final String PARAM_OPERATION = "operation";
|
||||
public static final String VAL_OPEN = "打开";
|
||||
public static final String VAL_CLOSE = "关闭";
|
||||
|
||||
@Override
|
||||
public void openADAS() {
|
||||
Intent intent = new Intent( ACTION );
|
||||
intent.putExtra( PARAM_COMMAND, VAL_COMMAND );
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
object.put( PARAM_OBJECT, VAL_OBJECT );
|
||||
object.put( PARAM_OPERATION, VAL_OPEN );
|
||||
intent.putExtra( PARAM_DATA, object.toString() );
|
||||
sendBroadcast( intent );
|
||||
} catch ( Exception e ) {
|
||||
Logger.e( TAG, e, "error." );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeADAS() {
|
||||
Intent intent = new Intent( ACTION );
|
||||
intent.putExtra( PARAM_COMMAND, VAL_COMMAND );
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
object.put( PARAM_OBJECT, VAL_OBJECT );
|
||||
object.put( PARAM_OPERATION, VAL_CLOSE );
|
||||
intent.putExtra( PARAM_DATA, object.toString() );
|
||||
sendBroadcast( intent );
|
||||
} catch ( Exception e ) {
|
||||
Logger.e( TAG, e, "error." );
|
||||
}
|
||||
}
|
||||
|
||||
private void sendBroadcast( Intent intent ) {
|
||||
Application app = AbsMogoApplication.getApp();
|
||||
if ( app == null ) {
|
||||
Logger.e( TAG, "un handle Application instance." );
|
||||
return;
|
||||
}
|
||||
app.sendBroadcast( intent );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init( Context context ) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -10,12 +10,14 @@ import com.mogo.map.MogoLocationClient;
|
||||
import com.mogo.map.MogoMapUIController;
|
||||
import com.mogo.map.MogoMarkerManager;
|
||||
import com.mogo.map.MogoNavi;
|
||||
import com.mogo.map.MogoOverlayManager;
|
||||
import com.mogo.map.MogoPoiSearch;
|
||||
import com.mogo.map.listener.IMogoHosListenerRegister;
|
||||
import com.mogo.map.listener.MogoHosListenerRegister;
|
||||
import com.mogo.map.location.IMogoLocationClient;
|
||||
import com.mogo.map.marker.IMogoMarkerManager;
|
||||
import com.mogo.map.navi.IMogoNavi;
|
||||
import com.mogo.map.overlay.IMogoOverlayManager;
|
||||
import com.mogo.map.search.geo.IMogoGeoSearch;
|
||||
import com.mogo.map.search.inputtips.IMogoInputtipsSearch;
|
||||
import com.mogo.map.search.inputtips.query.MogoInputtipsQuery;
|
||||
@@ -79,6 +81,11 @@ public class MogoMapService implements IMogoMapService {
|
||||
return MogoHosListenerRegister.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMogoOverlayManager getOverlayManager( Context context ) {
|
||||
return MogoOverlayManager.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init( Context context ) {
|
||||
MogoInitor.init( context );
|
||||
|
||||
@@ -4,6 +4,7 @@ include ':foudations:mogo-utils'
|
||||
include ':services:mogo-service-api'
|
||||
include ':services:mogo-service'
|
||||
include ':libraries:mogo-map'
|
||||
include ':libraries:card-library'
|
||||
include ':foudations:mogo-commons'
|
||||
include ':modules:mogo-module-map'
|
||||
include ':modules:mogo-module-common'
|
||||
|
||||