Merge branch 'dev' into demo/shunyi_v2v_merge

# Conflicts:
#	app/src/main/java/com/mogo/launcher/MogoApplication.java
#	config.gradle
#	foudations/mogo-commons/src/main/java/com/mogo/commons/debug/DebugConfig.java
#	modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/entrance/EntranceFragment.java
#	modules/mogo-module-extensions/src/main/res/values-mdpi/dimens.xml
#	modules/mogo-module-extensions/src/main/res/values-xhdpi/dimens.xml
#	modules/mogo-module-extensions/src/main/res/values/dimens.xml
#	modules/mogo-module-media/src/main/java/com/mogo/module/media/window/MediaWindow2.java
#	modules/mogo-module-v2x/src/main/res/layout/item_v2x_fault_help.xml
#	modules/mogo-module-v2x/src/main/res/values-xhdpi/dimens.xml
#	modules/mogo-module-v2x/src/main/res/values/dimens.xml
#	services/mogo-service-api/src/main/java/com/mogo/service/IMogoServiceApis.java
#	services/mogo-service/src/main/java/com/mogo/service/impl/MogoServiceApis.java
#	upload.sh
This commit is contained in:
wangcongtao
2020-10-18 16:40:27 +08:00
479 changed files with 7101 additions and 8317 deletions

View File

@@ -0,0 +1,52 @@
package com.mogo.module.common;
import com.alibaba.android.arouter.launcher.ARouter;
import com.mogo.service.IMogoServiceApis;
/**
* @author congtaowang
* @since 2020/9/21
* <p>
* 描述
*/
public final class MogoApisHandler {
private IMogoServiceApis sApis;
private static volatile MogoApisHandler sInstance;
private MogoApisHandler() {
sApis = ARouter.getInstance().navigation( IMogoServiceApis.class );
}
public static MogoApisHandler getInstance() {
if ( sInstance == null ) {
synchronized ( MogoApisHandler.class ) {
if ( sInstance == null ) {
sInstance = new MogoApisHandler();
}
}
}
return sInstance;
}
public synchronized void release() {
sInstance = null;
}
private Object readResolve() {
// 阻止反序列化,必须实现 Serializable 接口
return sInstance;
}
public IMogoServiceApis getApis() {
if ( sApis == null ) {
synchronized ( this ) {
if ( sApis != null ) {
sApis = ARouter.getInstance().navigation( IMogoServiceApis.class );
}
}
}
return sApis;
}
}

View File

@@ -0,0 +1,9 @@
package com.mogo.module.common.animation;
interface Animation {
void start();
void stop();
}

View File

@@ -0,0 +1,70 @@
package com.mogo.module.common.animation;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.widget.ProgressBar;
public class AnimationManager implements Animation {
private static final String TAG = "V2XAnimationManager";
private ProgressBar targetImageView;
private boolean isStarted = false;
private int mStartIndex = 0;
private final static int MSG_LOOP = 3004;
private long INTERVAL = 100L;
private Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MSG_LOOP:
if (isStarted) {
// targetImageView.setImageResource( AnimationResources.loadingRes[mStartIndex++ % AnimationResources.loadingRes.length] );
mHandler.sendEmptyMessageDelayed(MSG_LOOP, INTERVAL);
}
break;
}
}
};
public void animationWithTarget(ProgressBar imageView, int[] resources, int duration) {
targetImageView = imageView;
INTERVAL = duration;
start();
}
@Override
synchronized public void start() {
isStarted = true;
mHandler.sendEmptyMessage(MSG_LOOP);
if (targetImageView != null) {
targetImageView.setVisibility(View.VISIBLE);
}
}
@Override
synchronized public void stop() {
isStarted = false;
mHandler.removeMessages(MSG_LOOP);
if (targetImageView != null) {
targetImageView.setVisibility(View.INVISIBLE);
}
}
public void soptWithError() {
stop();
if (targetImageView != null) {
targetImageView.setVisibility(View.VISIBLE);
}
}
public void release() {
stop();
}
}

View File

@@ -0,0 +1,36 @@
package com.mogo.module.common.animation;
import com.mogo.module.common.R;
public class AnimationResources {
public static final int loadingRes[] = {
// R.drawable.v_to_x_loading_car0000,
// R.drawable.v_to_x_loading_car0002,
// R.drawable.v_to_x_loading_car0004,
// R.drawable.v_to_x_loading_car0006,
// R.drawable.v_to_x_loading_car0008,
// R.drawable.v_to_x_loading_car0010,
// R.drawable.v_to_x_loading_car0012,
// R.drawable.v_to_x_loading_car0014,
// R.drawable.v_to_x_loading_car0016,
// R.drawable.v_to_x_loading_car0018,
// R.drawable.v_to_x_loading_car0020,
// R.drawable.v_to_x_loading_car0022,
// R.drawable.v_to_x_loading_car0024,
// R.drawable.v_to_x_loading_car0025,
// R.drawable.v_to_x_loading_car0027,
// R.drawable.v_to_x_loading_car0029,
// R.drawable.v_to_x_loading_car0031,
// R.drawable.v_to_x_loading_car0033,
// R.drawable.v_to_x_loading_car0035,
// R.drawable.v_to_x_loading_car0037,
// R.drawable.v_to_x_loading_car0039,
// R.drawable.v_to_x_loading_car0041,
// R.drawable.v_to_x_loading_car0043,
// R.drawable.v_to_x_loading_car0045,
// R.drawable.v_to_x_loading_car0047,
// R.drawable.v_to_x_loading_car0048,
};
}

View File

@@ -0,0 +1,27 @@
package com.mogo.module.common.animation;
import android.graphics.drawable.AnimationDrawable;
public class DelegateDrawable implements Animation {
private AnimationDrawable drawable;
public DelegateDrawable(AnimationDrawable drawable) {
this.drawable = drawable;
}
@Override
public void start() {
if (drawable != null) {
drawable.start();
}
}
@Override
public void stop() {
if (drawable != null) {
drawable.stop();
}
}
}

View File

@@ -0,0 +1,81 @@
package com.mogo.module.common.api;
import android.content.Context;
import com.alibaba.android.arouter.launcher.ARouter;
import com.mogo.module.carchattingprovider.ICarsChattingProvider;
import com.mogo.module.common.entity.MarkerOnlineCar;
import com.mogo.utils.logger.Logger;
import com.zhidao.carchattingprovider.MogoDriverInfo;
public
/**
* @author congtaowang
* @since 2020/9/24
*
* 车聊聊接口
*/
class CallChatApi {
private static final String TAG = "CallChatApi";
private static volatile CallChatApi sInstance;
private CallChatApi() {
mApiProvider = ARouter.getInstance().navigation( ICarsChattingProvider.class );
}
public static CallChatApi getInstance() {
if ( sInstance == null ) {
synchronized ( CallChatApi.class ) {
if ( sInstance == null ) {
sInstance = new CallChatApi();
}
}
}
return sInstance;
}
public synchronized void release() {
sInstance = null;
}
private Object readResolve() {
// 阻止反序列化,必须实现 Serializable 接口
return sInstance;
}
public ICarsChattingProvider getApiProvider() {
return mApiProvider;
}
private ICarsChattingProvider mApiProvider;
public void showUserWindow( Context context, MarkerOnlineCar onlineCar ) throws Exception {
if ( mApiProvider == null ) {
Logger.e( TAG, "no call chat api instance." );
return;
}
MogoDriverInfo driverInfo = new MogoDriverInfo();
driverInfo.setAge( onlineCar.getUserInfo().getAgeNumber() );
driverInfo.setCarTypeName( onlineCar.getCarInfo().getCarTypeName() );
driverInfo.setGender( onlineCar.getUserInfo().getGender() );
driverInfo.setLat( onlineCar.getLocation().getLat() );
driverInfo.setLon( onlineCar.getLocation().getLon() );
driverInfo.setLocationInfo( onlineCar.getLocation().getAddress() );
driverInfo.setSn( onlineCar.getUserInfo().getSn() );
driverInfo.setUserHead( onlineCar.getUserInfo().getUserHead() );
driverInfo.setUserName( onlineCar.getUserInfo().getUserName() );
mApiProvider.showUserWindow( TAG, driverInfo, context );
}
public void hideUserWindow( Context context ) {
if ( mApiProvider != null ) {
if ( mApiProvider == null ) {
Logger.e( TAG, "no call chat api instance." );
return;
}
}
mApiProvider.hideUserWindow( TAG, context, null );
}
}

View File

@@ -33,6 +33,19 @@ public class V2XMessageEntity<T> implements Serializable {
*/
boolean showState;
/**
* 是否需要判断重复事件
* true-判断false-不判断
* 默认需要判断
*/
boolean isNeedCompareSameScenario = true;
//是否播报tts
private boolean onlyShow = false;
//本机与事件是否连线
private boolean needAddLine = true;
/**
* 场景具体的数据内容
*/
@@ -54,6 +67,14 @@ public class V2XMessageEntity<T> implements Serializable {
this.showState = showState;
}
public boolean isNeedCompareSameScenario() {
return isNeedCompareSameScenario;
}
public void setNeedCompareSameScenario(boolean needCompareSameScenario) {
isNeedCompareSameScenario = needCompareSameScenario;
}
public T getContent() {
return content;
}
@@ -76,6 +97,22 @@ public class V2XMessageEntity<T> implements Serializable {
return Objects.hash(type, content);
}
public boolean isOnlyShow() {
return onlyShow;
}
public void setOnlyShow(boolean onlyShow) {
this.onlyShow = onlyShow;
}
public boolean isNeedAddLine() {
return needAddLine;
}
public void setNeedAddLine(boolean needAddLine) {
this.needAddLine = needAddLine;
}
/**
* V2X 场景类型
*/

View File

@@ -24,6 +24,7 @@ public class V2XRoadEventEntity implements Serializable {
private MarkerExploreWay noveltyInfo;
// tts 提示
private String tts;
// ADAS 展示文案
private String alarmContent;
// 距离当前车辆的距离

View File

@@ -1,7 +1,7 @@
package com.mogo.module.common.map;
import com.mogo.commons.debug.DebugConfig;
import com.mogo.map.uicontroller.IMogoMapUIController;
import com.mogo.module.common.utils.CarSeries;
import com.mogo.utils.UiThreadHandler;
import com.mogo.utils.logger.Logger;
@@ -18,112 +18,102 @@ public class MapCenterPointStrategy {
private static final String TAG = "MapCenterPointStrategy";
private static Map< Integer, Map< Integer, MapCenterPoint > > sStrategies = new HashMap<>();
private static Map< Integer, Map< String, MapCenterPoint > > sStrategies = new HashMap<>();
public static final MapCenterPoint DEFAULT = new MapCenterPoint( 0.677734D, 0.5733333D );
private static MapCenterPoint sLastPoint = DEFAULT;
public static void init() {
{
// 选点场景,定位中心点
Map< Integer, MapCenterPoint > choosePoint = new HashMap<>();
choosePoint.put( CarSeries.CAR_SERIES_D80X, new MapCenterPoint( 0.5D, 0.5D ) );
choosePoint.put( CarSeries.CAR_SERIES_E84X, new MapCenterPoint( 0.5D, 0.5D ) );
choosePoint.put( CarSeries.CAR_SERIES_E84XCD, new MapCenterPoint( 0.5D, 0.5D ) );
choosePoint.put( CarSeries.CAR_SERIES_F80X, new MapCenterPoint( 0.5D, 0.5D ) );
Map< String, MapCenterPoint > choosePoint = new HashMap<>();
choosePoint.put( "d80x", new MapCenterPoint( 0.5D, 0.5D ) );
choosePoint.put( "em4", new MapCenterPoint( 0.5D, 0.5D ) );
choosePoint.put( "e8xx", new MapCenterPoint( 0.5D, 0.5D ) );
choosePoint.put( "f80x", new MapCenterPoint( 0.5D, 0.5D ) );
choosePoint.put( "f8xx", new MapCenterPoint( 0.5D, 0.5D ) );
sStrategies.put( Scene.CHOOSE_POINT, choosePoint );
}
{
// 导航场景,定位视图右下角偏下
Map< Integer, MapCenterPoint > navi = new HashMap<>();
navi.put( CarSeries.CAR_SERIES_D80X, new MapCenterPoint( 0.669444444444444, 0.573333333333D ) );
navi.put( CarSeries.CAR_SERIES_E84X, new MapCenterPoint( 0.734375D, 0.573333333333D ) );
navi.put( CarSeries.CAR_SERIES_E84XCD, new MapCenterPoint( 0.734375D, 0.573333333333D ) );
navi.put( CarSeries.CAR_SERIES_F80X, new MapCenterPoint( 0.705208333D, 0.575D ) );
Map< String, MapCenterPoint > navi = new HashMap<>();
navi.put( "d80x", new MapCenterPoint( 0.669444444444444, 0.573333333333D ) );
navi.put( "em4", new MapCenterPoint( 0.734375D, 0.573333333333D ) );
navi.put( "e8xx", new MapCenterPoint( 0.734375D, 0.573333333333D ) );
navi.put( "f80x", new MapCenterPoint( 0.705208333D, 0.575D ) );
navi.put( "f8xx", new MapCenterPoint( 0.705208333D, 0.575D ) );
sStrategies.put( Scene.NAVI, navi );
}
{
// 导航场景 vs 道路事件展示场景,定位视图右下角偏下
Map< Integer, MapCenterPoint > naviWithRoadEvent = new HashMap<>();
naviWithRoadEvent.put( CarSeries.CAR_SERIES_D80X, new MapCenterPoint( 0.669444444444444, 0.73936170212766D ) );
naviWithRoadEvent.put( CarSeries.CAR_SERIES_E84X, new MapCenterPoint( 0.734375D, 0.73936170212766D ) );
naviWithRoadEvent.put( CarSeries.CAR_SERIES_E84XCD, new MapCenterPoint( 0.734375D, 0.73936170212766D ) );
naviWithRoadEvent.put( CarSeries.CAR_SERIES_F80X, new MapCenterPoint( 0.705208333D, 0.683333333333D ) );
Map< String, MapCenterPoint > naviWithRoadEvent = new HashMap<>();
naviWithRoadEvent.put( "d80x", new MapCenterPoint( 0.669444444444444, 0.73936170212766D ) );
naviWithRoadEvent.put( "em4", new MapCenterPoint( 0.734375D, 0.73936170212766D ) );
naviWithRoadEvent.put( "e8xx", new MapCenterPoint( 0.734375D, 0.73936170212766D ) );
naviWithRoadEvent.put( "f80x", new MapCenterPoint( 0.705208333D, 0.683333333333D ) );
naviWithRoadEvent.put( "f8xx", new MapCenterPoint( 0.705208333D, 0.683333333333D ) );
sStrategies.put( Scene.NAVI_WITH_ROAD_EVENT, naviWithRoadEvent );
}
{
// 巡航场景
Map< Integer, MapCenterPoint > aimless = new HashMap<>();
aimless.put( CarSeries.CAR_SERIES_D80X, new MapCenterPoint( 0.669444444444444, 0.5D ) );
aimless.put( CarSeries.CAR_SERIES_E84X, new MapCenterPoint( 0.734375D, 0.5D ) );
aimless.put( CarSeries.CAR_SERIES_E84XCD, new MapCenterPoint( 0.734375D, 0.5D ) );
aimless.put( CarSeries.CAR_SERIES_F80X, new MapCenterPoint( 0.705208333D, 0.5D ) );
Map< String, MapCenterPoint > aimless = new HashMap<>();
aimless.put( "d80x", new MapCenterPoint( 0.669444444444444, 0.5D ) );
aimless.put( "em4", new MapCenterPoint( 0.734375D, 0.5D ) );
aimless.put( "e8xx", new MapCenterPoint( 0.734375D, 0.5D ) );
aimless.put( "f80x", new MapCenterPoint( 0.705208333D, 0.5D ) );
aimless.put( "f8xx", new MapCenterPoint( 0.705208333D, 0.5D ) );
sStrategies.put( Scene.AIMLESS, aimless );
}
{
// 巡航场景 vs 道路事件展示场景
Map< Integer, MapCenterPoint > aimlessWithRoadEvent = new HashMap<>();
aimlessWithRoadEvent.put( CarSeries.CAR_SERIES_D80X, new MapCenterPoint( 0.669444444444444, 0.68617 ) );
aimlessWithRoadEvent.put( CarSeries.CAR_SERIES_E84X, new MapCenterPoint( 0.734375D, 0.68617 ) );
aimlessWithRoadEvent.put( CarSeries.CAR_SERIES_E84XCD, new MapCenterPoint( 0.734375D, 0.68617 ) );
aimlessWithRoadEvent.put( CarSeries.CAR_SERIES_F80X, new MapCenterPoint( 0.705208333D, 0.599074074D ) );
Map< String, MapCenterPoint > aimlessWithRoadEvent = new HashMap<>();
aimlessWithRoadEvent.put( "d80x", new MapCenterPoint( 0.669444444444444, 0.68617 ) );
aimlessWithRoadEvent.put( "em4", new MapCenterPoint( 0.734375D, 0.68617 ) );
aimlessWithRoadEvent.put( "e8xx", new MapCenterPoint( 0.734375D, 0.68617 ) );
aimlessWithRoadEvent.put( "f80x", new MapCenterPoint( 0.705208333D, 0.599074074D ) );
aimlessWithRoadEvent.put( "f8xx", new MapCenterPoint( 0.705208333D, 0.599074074D ) );
sStrategies.put( Scene.AIMLESS_WITH_ROAD_EVENT, aimlessWithRoadEvent );
}
{
// 规划路线,定位视图右边
Map< Integer, MapCenterPoint > calculatePath = new HashMap<>();
calculatePath.put( CarSeries.CAR_SERIES_D80X, new MapCenterPoint( 0.733398D, 0.610833D ) );
calculatePath.put( CarSeries.CAR_SERIES_E84X, new MapCenterPoint( 0.733398D, 0.610833D ) );
calculatePath.put( CarSeries.CAR_SERIES_E84XCD, new MapCenterPoint( 0.733398D, 0.610833D ) );
calculatePath.put( CarSeries.CAR_SERIES_F80X, new MapCenterPoint( 0.703125D, 0.6083333D ) );
Map< String, MapCenterPoint > calculatePath = new HashMap<>();
calculatePath.put( "d80x", new MapCenterPoint( 0.733398D, 0.610833D ) );
calculatePath.put( "em4", new MapCenterPoint( 0.733398D, 0.610833D ) );
calculatePath.put( "e8xx", new MapCenterPoint( 0.733398D, 0.610833D ) );
calculatePath.put( "f80x", new MapCenterPoint( 0.703125D, 0.6083333D ) );
calculatePath.put( "f8xx", new MapCenterPoint( 0.703125D, 0.6083333D ) );
sStrategies.put( Scene.CALCULATE_PATH, calculatePath );
}
{
// 分类搜索,定位视图右边
Map< Integer, MapCenterPoint > categorySearch = new HashMap<>();
categorySearch.put( CarSeries.CAR_SERIES_D80X, new MapCenterPoint( 0.733398D, 0.5D ) );
categorySearch.put( CarSeries.CAR_SERIES_E84X, new MapCenterPoint( 0.733398D, 0.5D ) );
categorySearch.put( CarSeries.CAR_SERIES_E84XCD, new MapCenterPoint( 0.733398D, 0.5D ) );
categorySearch.put( CarSeries.CAR_SERIES_F80X, new MapCenterPoint( 0.733594D, 0.5D ) );
Map< String, MapCenterPoint > categorySearch = new HashMap<>();
categorySearch.put( "d80x", new MapCenterPoint( 0.733398D, 0.5D ) );
categorySearch.put( "em4", new MapCenterPoint( 0.733398D, 0.5D ) );
categorySearch.put( "e8xx", new MapCenterPoint( 0.733398D, 0.5D ) );
categorySearch.put( "f80x", new MapCenterPoint( 0.733594D, 0.5D ) );
categorySearch.put( "f8xx", new MapCenterPoint( 0.733594D, 0.5D ) );
sStrategies.put( Scene.CATEGORY_SEARCH, categorySearch );
}
{
// V2X场景视图右边
Map< Integer, MapCenterPoint > categoryV2XEvent = new HashMap<>();
categoryV2XEvent.put( CarSeries.CAR_SERIES_D80X, new MapCenterPoint( 0.669444444444444, 0.7D ) );
categoryV2XEvent.put( CarSeries.CAR_SERIES_E84X, new MapCenterPoint( 0.677734375D, 0.7D ) );
categoryV2XEvent.put( CarSeries.CAR_SERIES_E84XCD, new MapCenterPoint( 0.677734375D, 0.7D ) );
categoryV2XEvent.put( CarSeries.CAR_SERIES_F80X, new MapCenterPoint( 0.6963541D, 0.65D ) );
Map< String, MapCenterPoint > categoryV2XEvent = new HashMap<>();
categoryV2XEvent.put( "d80x", new MapCenterPoint( 0.669444444444444, 0.7D ) );
categoryV2XEvent.put( "em4", new MapCenterPoint( 0.677734375D, 0.7D ) );
categoryV2XEvent.put( "e8xx", new MapCenterPoint( 0.677734375D, 0.7D ) );
categoryV2XEvent.put( "f80x", new MapCenterPoint( 0.6963541D, 0.65D ) );
categoryV2XEvent.put( "f8xx", new MapCenterPoint( 0.6963541D, 0.65D ) );
sStrategies.put( Scene.CATEGORY_V2X_EVENT, categoryV2XEvent );
}
try {
sLastPoint = sStrategies.get( Scene.AIMLESS ).get( CarSeries.getSeries() );
} catch ( Exception e ) {
sLastPoint = DEFAULT;
}
}
public static void restoreLastScene( IMogoMapUIController controller ) {
if ( sLastPoint == null ) {
return;
}
if ( controller == null ) {
return;
}
controller.setPointToCenter( sLastPoint.x, sLastPoint.y );
}
public static void addScene( int scene, Map< Integer, MapCenterPoint > config ) {
public static void addScene( int scene, Map< String, MapCenterPoint > config ) {
if ( sStrategies.containsKey( scene ) ) {
Logger.w( TAG, "scene has already defined, append config..." );
}
@@ -147,25 +137,21 @@ public class MapCenterPointStrategy {
if ( !sStrategies.containsKey( scene ) ) {
Logger.w( TAG, "no strategy for scene: %s, use DEFAULT", scene );
controller.setPointToCenter( DEFAULT.x, DEFAULT.y );
sLastPoint = DEFAULT;
return;
}
Map< Integer, MapCenterPoint > points = sStrategies.get( scene );
int car = CarSeries.getSeries();
Map< String, MapCenterPoint > points = sStrategies.get( scene );
String car = DebugConfig.getProductFlavor();
if ( !points.containsKey( car ) ) {
Logger.w( TAG, "no strategy for series: %s, use DEFAULT", scene );
controller.setPointToCenter( DEFAULT.x, DEFAULT.y );
sLastPoint = DEFAULT;
return;
}
MapCenterPoint point = points.get( car );
if ( point == null ) {
Logger.w( TAG, "no strategy config for series: %s, use DEFAULT", scene );
controller.setPointToCenter( DEFAULT.x, DEFAULT.y );
sLastPoint = DEFAULT;
return;
}
sLastPoint = point;
controller.setPointToCenter( point.x, point.y );
}

View File

@@ -0,0 +1,10 @@
package com.mogo.module.common.utils;
public class Const {
/**
* V2X 场景广播 Action
*/
public static final String BROADCAST_SCENE_HANDLER_ACTION = "com.v2x.scene_handler_broadcast";
public static final String BROADCAST_SCENE_EXTRA_KEY = "V2XMessageEntity";
}

View File

@@ -0,0 +1,22 @@
package com.mogo.module.common.utils;
/**
* 多模块之间SP状态公共类
*/
public class SPConst {
private static String SP_GUIDE = "SP_GUIDE_2020_09_09";
//用于多模块之间引导状态判断
public static String getSpGuide() {
return SP_GUIDE;
}
private static String SP_GUIDE_FIRST_TIME_RECORD = "SP_GUIDE_FIRST_TIME_RECORD";
//用于多模块之间首次引导时间记录
public static String getSPGuideRecord(){
return SP_GUIDE_FIRST_TIME_RECORD;
}
}

View File

@@ -0,0 +1,298 @@
package com.mogo.module.common.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.mogo.module.common.R;
import java.math.BigDecimal;
public class CustomRatingBar extends LinearLayout {
private Context mContext;
/*
是否可点击
* */
private boolean mClickable;
/*
* 单元总数(心形/星星)
* */
private int elementCount;
/*
* 单元点击事件
* */
private OnRatingChangeListener mOnRatingBarChangeListener;
/*
* 每个单元的大小
* */
private float elementWidth;
private float elementHeight;
public float getElementWidth() {
return elementWidth;
}
public void setElementWidth(float elementWidth) {
this.elementWidth = elementWidth;
}
public float getElementHeight() {
return elementHeight;
}
public void setElementHeight(float elementHeight) {
this.elementHeight = elementHeight;
}
/*
* 每个单元间的距离
* */
private float elementPadding;
/*
*单元的显示数量,支持小数点
* */
private float elementStep;
/*
* 空白的默认单元图片
* */
private Drawable elementEmptyDrawable;
/*
* 选中后的单元图片
* */
private Drawable elementFillDrawable;
/*
* 半颗单元图片
* */
private Drawable elementHarfDrawable;
/*
* 每次点击单元所增加的量是半个还是整个
* */
private StepSize stepSize;
@Override
public boolean isClickable() {
return mClickable;
}
@Override
public void setClickable(boolean clickable) {
mClickable = clickable;
}
public int getElementCount() {
return elementCount;
}
public void setElementCount(int elementCount) {
this.elementCount = elementCount;
}
public OnRatingChangeListener getOnRatingBarChangeListener() {
return mOnRatingBarChangeListener;
}
public void setOnRatingChangeListener(OnRatingChangeListener onRatingBarChangeListener) {
mOnRatingBarChangeListener = onRatingBarChangeListener;
}
public float getElementPadding() {
return elementPadding;
}
public void setElementPadding(float elementPadding) {
this.elementPadding = elementPadding;
}
public float getElementStep() {
return elementStep;
}
public void setElementStep(float elementStep) {
this.elementStep = elementStep;
}
public Drawable getElementEmptyDrawable() {
return elementEmptyDrawable;
}
public void setElementEmptyDrawable(Drawable elementEmptyDrawable) {
this.elementEmptyDrawable = elementEmptyDrawable;
}
public Drawable getElementFillDrawable() {
return elementFillDrawable;
}
public void setElementFillDrawable(Drawable elementFillDrawable) {
this.elementFillDrawable = elementFillDrawable;
}
public Drawable getElementHarfDrawable() {
return elementHarfDrawable;
}
public void setElementHarfDrawable(Drawable elementHarfDrawable) {
this.elementHarfDrawable = elementHarfDrawable;
}
public void setStepSize(StepSize stepSize) {
this.stepSize = stepSize;
}
public CustomRatingBar(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mContext = context;
setOrientation(LinearLayout.HORIZONTAL);
TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomRatingBar);
elementWidth = mTypedArray.getDimension(R.styleable.CustomRatingBar_elenmentWidth,
context.getResources().getDimension(R.dimen.heart_ratingbar_width));
elementHeight = mTypedArray.getDimension(R.styleable.CustomRatingBar_elenmentHeight,
context.getResources().getDimension(R.dimen.heart_ratingbar_height));
elementPadding = mTypedArray.getDimension(R.styleable.CustomRatingBar_elenmentPadding, 10);
elementStep = mTypedArray.getFloat(R.styleable.CustomRatingBar_elenmentStep, 1.0f);
stepSize = StepSize.fromStep(mTypedArray.getInt(R.styleable.CustomRatingBar_stepSize, 1));
elementCount = mTypedArray.getInteger(R.styleable.CustomRatingBar_elenmentCount, 5);
stepSize = StepSize.Half;
Drawable drawable_empty_default = ContextCompat.getDrawable(context, R.drawable.icon_heart_unchoose);
Drawable drawable_harf_default = ContextCompat.getDrawable(context, R.drawable.icon_heart_second);
Drawable drawable_fill_default = ContextCompat.getDrawable(context, R.drawable.icon_heart_choose);
Drawable drawable_empty = mTypedArray.getDrawable(R.styleable.CustomRatingBar_elenmentEmpty);
Drawable drawable_harf = mTypedArray.getDrawable(R.styleable.CustomRatingBar_elenmentHarf);
Drawable drawable_fill = mTypedArray.getDrawable(R.styleable.CustomRatingBar_elenmentFill);
elementEmptyDrawable = drawable_empty != null ? drawable_empty : drawable_empty_default;
elementFillDrawable = drawable_harf != null ? drawable_harf : drawable_fill_default;
elementHarfDrawable = drawable_fill != null ? drawable_fill : drawable_harf_default;
mClickable = mTypedArray.getBoolean(R.styleable.CustomRatingBar_clickable, false);
mTypedArray.recycle();
for (int i = 0; i < elementCount; ++i) {
final ImageView imageView = getElenmentImageView();
imageView.setImageDrawable(elementEmptyDrawable);
imageView.setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
if (mClickable) {
//浮点数的整数部分
int fint = (int) elementStep;
BigDecimal b1 = new BigDecimal(Float.toString(elementStep));
BigDecimal b2 = new BigDecimal(Integer.toString(fint));
//浮点数的小数部分
float fPoint = b1.subtract(b2).floatValue();
if (fPoint == 0) {
fint -= 1;
}
if (indexOfChild(v) > fint) {
setRating(indexOfChild(v) + 1);
} else if (indexOfChild(v) == fint) {
if (stepSize == StepSize.Full) {//如果是满星 就不考虑半颗星了
return;
}
//点击之后默认每次先增加一颗星,再次点击变为半颗星
if (imageView.getDrawable().getCurrent().getConstantState().
equals(elementHarfDrawable.getConstantState())) {
setRating(indexOfChild(v) + 1);
} else {
setRating(indexOfChild(v) + 0.5f);
}
} else {
setRating(indexOfChild(v) + 1f);
}
}
}
}
);
addView(imageView);
}
setRating(elementStep);
}
private ImageView getElenmentImageView() {
ImageView imageView = new ImageView(getContext());
LayoutParams layout = new LayoutParams(
Math.round(mContext.getResources().getDimension(R.dimen.heart_ratingbar_width)),
Math.round(mContext.getResources().getDimension(R.dimen.heart_ratingbar_width)));//设置每个单元格在线性布局的大小
layout.setMargins(0, 0, Math.round(elementPadding), 0);//设置每颗星星在线性布局的间距
imageView.setLayoutParams(layout);
imageView.setAdjustViewBounds(true);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setImageDrawable(elementEmptyDrawable);
imageView.setMinimumWidth((int) elementWidth);
imageView.setMaxWidth((int) elementWidth);
imageView.setMinimumHeight((int) elementHeight);
imageView.setMaxHeight((int) elementHeight);
return imageView;
}
public void setRating(float rating) {
if (rating > elementCount)
rating = elementCount;
if (mOnRatingBarChangeListener != null) {
mOnRatingBarChangeListener.onRatingChange(rating);
}
this.elementStep = rating;
//浮点数的整数部分
int fint = (int) rating;
BigDecimal b1 = new BigDecimal(Float.toString(rating));
BigDecimal b2 = new BigDecimal(Integer.toString(fint));
//浮点数的小数部分
float fPoint = b1.subtract(b2).floatValue();
//设置选中的单元
for (int i = 0; i < fint; ++i) {
((ImageView) getChildAt(i)).setImageDrawable(elementFillDrawable);
}
//设置没有选中的单元
for (int i = fint; i < elementCount; i++) {
((ImageView) getChildAt(i)).setImageDrawable(elementEmptyDrawable);
}
//小数点默认增加半个
if (fPoint > 0) {
((ImageView) getChildAt(fint)).setImageDrawable(elementHarfDrawable);
}
}
public interface OnRatingChangeListener {
void onRatingChange(float ratingCount);
}
/**
* 每次增加的方式整颗还是半颗,枚举类型
* 类似于View.GONE
*/
public enum StepSize {
Half(0), Full(1);
int step;
StepSize(int step) {
this.step = step;
}
public static StepSize fromStep(int step) {
for (StepSize f : values()) {
if (f.step == step) {
return f;
}
}
throw new IllegalArgumentException();
}
}
}

View File

@@ -0,0 +1,96 @@
package com.mogo.module.common.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.mogo.module.common.R;
import com.mogo.module.common.animation.AnimationResources;
import com.mogo.module.common.animation.AnimationManager;
public class NetworkLoadingView extends RelativeLayout {
private ProgressBar loadView;
private TextView textView;
private AnimationManager mAnimationManager;
public Button refresButton;
private String loadingText = "正在获取信息…";
public NetworkLoadingView(Context context) {
super(context);
}
public NetworkLoadingView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.network_loading_item, this);
initView();
/*
添加动画图片资源
* */
setLoadingImage(AnimationResources.loadingRes);
}
public NetworkLoadingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void initView() {
mAnimationManager = new AnimationManager();
loadView = findViewById(R.id.loading_imageview);
textView = findViewById(R.id.loading_text);
refresButton = findViewById(R.id.refresh_button);
}
public void setLoadingText(String text) {
if (textView != null) {
textView.setText(text);
}
}
public void setLoadingImage(int[] resources) {
mAnimationManager.animationWithTarget(loadView, resources, 100);
}
public void start() {
if (mAnimationManager != null) {
mAnimationManager.start();
this.setVisibility(View.VISIBLE);
}
if (refresButton != null) {
refresButton.setVisibility(GONE);
}
if (textView != null) {
textView.setText(loadingText);
}
}
public void stop() {
if (mAnimationManager != null) {
mAnimationManager.stop();
this.setVisibility(GONE);
}
}
public void stopWithError(String errormsg, int showRefreshButton) {
if (mAnimationManager != null) {
mAnimationManager.soptWithError();
}
if (textView != null) {
textView.setText(errormsg);
}
if (refresButton != null) {
refresButton.setVisibility(showRefreshButton);
}
}
}

View File

@@ -0,0 +1,39 @@
package com.mogo.module.common.view;
import android.view.View;
public
/**
* @author congtaowang
* @since 2020/9/25
*
* 防止短时间内多次点击
*/
abstract class OnPreventFastClickListener implements View.OnClickListener {
public static final long INTERVAL = 1_000L;
private long mInterval;
private long mLastClickTime = 0L;
public OnPreventFastClickListener() {
this( INTERVAL );
}
public OnPreventFastClickListener( long interval ) {
if ( interval < 0L ) {
interval = INTERVAL;
}
this.mInterval = interval;
}
@Override
public final void onClick( View v ) {
if ( System.currentTimeMillis() - mLastClickTime > mInterval ) {
onClickImpl( v );
mLastClickTime = System.currentTimeMillis();
}
}
public abstract void onClickImpl( View v );
}

View File

@@ -0,0 +1,337 @@
package com.mogo.module.common.widget;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.util.AttributeSet;
import android.widget.ImageView;
import androidx.annotation.ColorInt;
import androidx.annotation.ColorRes;
import androidx.annotation.DrawableRes;
import com.mogo.module.common.R;
@SuppressLint("AppCompatCustomView")
public class CustomCircleImageView extends ImageView {
private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;
private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
private static final int COLORDRAWABLE_DIMENSION = 2;
private static final int DEFAULT_BORDER_WIDTH = 0;
private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
private static final int DEFAULT_FILL_COLOR = Color.TRANSPARENT;
private static final boolean DEFAULT_BORDER_OVERLAY = false;
private final RectF mDrawableRect = new RectF();
private final RectF mBorderRect = new RectF();
private final Matrix mShaderMatrix = new Matrix();
private final Paint mBitmapPaint = new Paint();
private final Paint mBorderPaint = new Paint();
private final Paint mFillPaint = new Paint();
private int mBorderColor = DEFAULT_BORDER_COLOR;
private int mBorderWidth = DEFAULT_BORDER_WIDTH;
private int mFillColor = DEFAULT_FILL_COLOR;
private Bitmap mBitmap;
private BitmapShader mBitmapShader;
private int mBitmapWidth;
private int mBitmapHeight;
private float mDrawableRadius;
private float mBorderRadius;
private ColorFilter mColorFilter;
private boolean mReady;
private boolean mSetupPending;
private boolean mBorderOverlay;
public CustomCircleImageView( Context context) {
super(context);
init();
}
public CustomCircleImageView( Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomCircleImageView( Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomCircleImageView, defStyle, 0);
mBorderWidth = a.getDimensionPixelSize(R.styleable.CustomCircleImageView_civ_border_width, DEFAULT_BORDER_WIDTH);
mBorderColor = a.getColor(R.styleable.CustomCircleImageView_civ_border_color, DEFAULT_BORDER_COLOR);
mBorderOverlay = a.getBoolean(R.styleable.CustomCircleImageView_civ_border_overlay, DEFAULT_BORDER_OVERLAY);
mFillColor = a.getColor(R.styleable.CustomCircleImageView_civ_fill_color, DEFAULT_FILL_COLOR);
a.recycle();
init();
}
private void init() {
super.setScaleType(SCALE_TYPE);
mReady = true;
if (mSetupPending) {
setup();
mSetupPending = false;
}
}
@Override
public ScaleType getScaleType() {
return SCALE_TYPE;
}
@Override
public void setScaleType(ScaleType scaleType) {
if (scaleType != SCALE_TYPE) {
throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));
}
}
@Override
public void setAdjustViewBounds(boolean adjustViewBounds) {
if (adjustViewBounds) {
throw new IllegalArgumentException("adjustViewBounds not supported.");
}
}
@Override
protected void onDraw(Canvas canvas) {
if (mBitmap == null) {
return;
}
if (mFillColor != Color.TRANSPARENT) {
canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mDrawableRadius, mFillPaint);
}
canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mDrawableRadius, mBitmapPaint);
if (mBorderWidth != 0) {
canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mBorderRadius, mBorderPaint);
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
setup();
}
public int getBorderColor() {
return mBorderColor;
}
public void setBorderColor(@ColorInt int borderColor) {
if (borderColor == mBorderColor) {
return;
}
mBorderColor = borderColor;
mBorderPaint.setColor(mBorderColor);
invalidate();
}
public void setBorderColorResource(@ColorRes int borderColorRes) {
setBorderColor(getContext().getResources().getColor(borderColorRes));
}
public int getFillColor() {
return mFillColor;
}
public void setFillColor(@ColorInt int fillColor) {
if (fillColor == mFillColor) {
return;
}
mFillColor = fillColor;
mFillPaint.setColor(fillColor);
invalidate();
}
public void setFillColorResource(@ColorRes int fillColorRes) {
setFillColor(getContext().getResources().getColor(fillColorRes));
}
public int getBorderWidth() {
return mBorderWidth;
}
public void setBorderWidth(int borderWidth) {
if (borderWidth == mBorderWidth) {
return;
}
mBorderWidth = borderWidth;
setup();
}
public boolean isBorderOverlay() {
return mBorderOverlay;
}
public void setBorderOverlay(boolean borderOverlay) {
if (borderOverlay == mBorderOverlay) {
return;
}
mBorderOverlay = borderOverlay;
setup();
}
@Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
mBitmap = bm;
setup();
}
@Override
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
mBitmap = getBitmapFromDrawable(drawable);
setup();
}
@Override
public void setImageResource(@DrawableRes int resId) {
super.setImageResource(resId);
mBitmap = getBitmapFromDrawable(getDrawable());
setup();
}
@Override
public void setImageURI(Uri uri) {
super.setImageURI(uri);
mBitmap = uri != null ? getBitmapFromDrawable(getDrawable()) : null;
setup();
}
@Override
public void setColorFilter(ColorFilter cf) {
if (cf == mColorFilter) {
return;
}
mColorFilter = cf;
mBitmapPaint.setColorFilter(mColorFilter);
invalidate();
}
private Bitmap getBitmapFromDrawable(Drawable drawable) {
if (drawable == null) {
return null;
}
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
try {
Bitmap bitmap;
if (drawable instanceof ColorDrawable) {
bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);
}
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private void setup() {
if (!mReady) {
mSetupPending = true;
return;
}
if (getWidth() == 0 && getHeight() == 0) {
return;
}
if (mBitmap == null) {
invalidate();
return;
}
mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mBitmapPaint.setAntiAlias(true);
mBitmapPaint.setShader(mBitmapShader);
mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setAntiAlias(true);
mBorderPaint.setColor(mBorderColor);
mBorderPaint.setStrokeWidth(mBorderWidth);
mFillPaint.setStyle(Paint.Style.FILL);
mFillPaint.setAntiAlias(true);
mFillPaint.setColor(mFillColor);
mBitmapHeight = mBitmap.getHeight();
mBitmapWidth = mBitmap.getWidth();
mBorderRect.set(0, 0, getWidth(), getHeight());
mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2.0f, (mBorderRect.width() - mBorderWidth) / 2.0f);
mDrawableRect.set(mBorderRect);
if (!mBorderOverlay) {
mDrawableRect.inset(mBorderWidth, mBorderWidth);
}
mDrawableRadius = Math.min(mDrawableRect.height() / 2.0f, mDrawableRect.width() / 2.0f);
updateShaderMatrix();
invalidate();
}
private void updateShaderMatrix() {
float scale;
float dx = 0;
float dy = 0;
mShaderMatrix.set(null);
if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {
scale = mDrawableRect.height() / (float) mBitmapHeight;
dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
} else {
scale = mDrawableRect.width() / (float) mBitmapWidth;
dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
}
mShaderMatrix.setScale(scale, scale);
mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top);
mBitmapShader.setLocalMatrix(mShaderMatrix);
}
}

View File

@@ -33,6 +33,6 @@ interface IWindowManagerView {
void hide();
interface OnViewClickListener {
void onClick( View view );
void onClick( View view, float xPos, float yPos );
}
}

View File

@@ -64,7 +64,10 @@ class WindowManagerImpl implements IWindowManagerView {
// 只要按钮一动位置不是很大,就认为是点击事件
if ( Math.abs( mOldOffsetX - newOffsetX ) <= 20
&& Math.abs( mOldOffsetY - newOffsetY ) <= 20 ) {
listener.onClick( mParams.mContentView );
if ( listener != null ) {
listener.onClick( mParams.mContentView, x, y );
}
return false;
}
mOldOffsetX = newOffsetX;
mOldOffsetY = newOffsetY;