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:
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.mogo.module.common.animation;
|
||||
|
||||
interface Animation {
|
||||
|
||||
void start();
|
||||
|
||||
void stop();
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
@@ -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 场景类型
|
||||
*/
|
||||
|
||||
@@ -24,6 +24,7 @@ public class V2XRoadEventEntity implements Serializable {
|
||||
private MarkerExploreWay noveltyInfo;
|
||||
// tts 提示
|
||||
private String tts;
|
||||
|
||||
// ADAS 展示文案
|
||||
private String alarmContent;
|
||||
// 距离当前车辆的距离
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -33,6 +33,6 @@ interface IWindowManagerView {
|
||||
void hide();
|
||||
|
||||
interface OnViewClickListener {
|
||||
void onClick( View view );
|
||||
void onClick( View view, float xPos, float yPos );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user