From 15f5680b532238290d0adf095a93e5af1c5f1203 Mon Sep 17 00:00:00 2001 From: zuoxiao <470321431@qq.com> Date: 星期五, 07 二月 2025 17:14:57 +0800 Subject: [PATCH] 1.添加显示隐藏取水口、分水房功能 2.完善图例自定义控件功能和显示 3.处理工单添加选择时间功能 --- app/src/main/assets/js/map.js | 71 ++++ app/src/main/java/com/dayu/pipirrapp/activity/OrderDealActivity.java | 13 app/src/main/res/layout/activity_order_deal.xml | 10 app/src/main/java/com/dayu/pipirrapp/MyApplication.java | 2 app/src/main/java/com/dayu/pipirrapp/dao/DivideDao.java | 4 app/src/main/java/com/dayu/pipirrapp/dao/MarkerDao.java | 2 app/src/main/java/com/dayu/pipirrapp/utils/DateUtils.java | 14 app/src/main/res/drawable/divide_home_unselected.xml | 25 + app/src/main/res/layout/fragment_map.xml | 17 expand_button/src/main/res/values/attrs.xml | 6 app/src/main/res/drawable/marker_blue.xml | 9 app/src/main/res/drawable/marker_unselected.xml | 9 expand_button/src/main/java/com/example/expand_button/ExpandButton.kt | 416 +++++++++++++++++++++++---- app/src/main/java/com/dayu/pipirrapp/fragment/MapFragment.java | 222 +++++++++----- app/src/main/res/drawable/divide_home_blue.xml | 25 + 15 files changed, 672 insertions(+), 173 deletions(-) diff --git a/app/src/main/assets/js/map.js b/app/src/main/assets/js/map.js index 85b3113..bfd0f8d 100644 --- a/app/src/main/assets/js/map.js +++ b/app/src/main/assets/js/map.js @@ -27,6 +27,12 @@ let pipeLineList = []; let currentPipePath = []; + // 瀛樺偍鎵�鏈夊彇姘村彛鏍囪鐨勬暟缁� + let waterIntakeMarkers = []; + + // 瀛樺偍鎵�鏈夊垎姘存埧鏍囪鐨勬暟缁� + let divideMarkers = []; + // 灏嗘柟娉曟寕杞藉埌 window 涓� function mountMethodToWindow() { window.locationOverLay = locationOverLay; @@ -46,6 +52,10 @@ window.hideAllPipeLines = hideAllPipeLines; window.clearAllPipeLines = clearAllPipeLines; window.addPipeNetwork = addPipeNetwork; + window.hideAllWaterIntakes = hideAllWaterIntakes; + window.showAllWaterIntakes = showAllWaterIntakes; + window.hideAllDivides = hideAllDivides; + window.showAllDivides = showAllDivides; } @@ -242,19 +252,26 @@ let label = new T.Label({ text: `<div style='position:absolute;left:-50%;transform: translateX(-50%);'>${name}<div>`, position: marker.getLngLat(), - offset: new T.Point(0, 8), // 璁剧疆鏍囨敞鏂囧瓧鐨勪綅缃� - opacity: 1, // 璁剧疆鏂囨湰鐨勬樉绀轰笉閫忔槑搴︼紙鑼冨洿0-1锛� + offset: new T.Point(0, 8), + opacity: 1, }); - label.setBorderLine(0); // 璁剧疆鏂囨湰鐨勮竟妗嗙嚎瀹� - label.setBackgroundColor("transparent"); // 璁剧疆鏂囨湰鐨勮儗鏅壊锛堥�忔槑鑹诧級 + label.setBorderLine(0); + label.setBackgroundColor("transparent"); label.setFontColor("#FFFFFF"); label.setFontSize(10); marker.label = label; if (isRed) { lastClickedMarker = marker; } + + // 灏嗘爣璁板拰鏍囩瀛樺偍鍒版暟缁勪腑 + waterIntakeMarkers.push({ + marker: marker, + label: label + }); + map.addOverLay(label); - map.addOverLay(marker); // 灏嗘爣娉ㄦ坊鍔犲埌鍦板浘涓� + map.addOverLay(marker); return "addMarker鍔犺浇鎴愬姛 id:" + id } //鏇存柊浣嶅潗鏍� @@ -538,6 +555,13 @@ if (isRed) { lastClickedMarker = marker; } + + // 灏嗗垎姘存埧鏍囪鍜屾爣绛惧瓨鍌ㄥ埌鏁扮粍涓� + divideMarkers.push({ + marker: marker, + label: label + }); + map.addOverLay(label); map.addOverLay(marker); // 灏嗘爣娉ㄦ坊鍔犲埌鍦板浘涓� return "addMarker鍔犺浇鎴愬姛 id:" + id @@ -577,9 +601,44 @@ window.Android.showDivideDetail(data); } + /** + * 闅愯棌鎵�鏈夊彇姘村彛鏍囪 + */ + function hideAllWaterIntakes() { + waterIntakeMarkers.forEach(item => { + map.removeOverLay(item.marker); + map.removeOverLay(item.label); + }); + } + /** + * 鏄剧ず鎵�鏈夊彇姘村彛鏍囪 + */ + function showAllWaterIntakes() { + waterIntakeMarkers.forEach(item => { + map.addOverLay(item.marker); + map.addOverLay(item.label); + }); + } + /** + * 闅愯棌鎵�鏈夊垎姘存埧鏍囪 + */ + function hideAllDivides() { + divideMarkers.forEach(item => { + map.removeOverLay(item.marker); + map.removeOverLay(item.label); + }); + } - + /** + * 鏄剧ず鎵�鏈夊垎姘存埧鏍囪 + */ + function showAllDivides() { + divideMarkers.forEach(item => { + map.addOverLay(item.marker); + map.addOverLay(item.label); + }); + } })(); diff --git a/app/src/main/java/com/dayu/pipirrapp/MyApplication.java b/app/src/main/java/com/dayu/pipirrapp/MyApplication.java index 1bb8f2f..3681ff6 100644 --- a/app/src/main/java/com/dayu/pipirrapp/MyApplication.java +++ b/app/src/main/java/com/dayu/pipirrapp/MyApplication.java @@ -32,7 +32,7 @@ // JPushInterface.setDebugMode(true); // JPushInterface.init(this); - CrashReport.initCrashReport(getApplicationContext(), "3d4bcf7046", false); + CrashReport.initCrashReport(getApplicationContext(), "f6dea280a2", false); // // 璁剧疆鍏ㄥ眬鐨刄ncaughtExceptionHandler // Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { diff --git a/app/src/main/java/com/dayu/pipirrapp/activity/OrderDealActivity.java b/app/src/main/java/com/dayu/pipirrapp/activity/OrderDealActivity.java index 0d707c0..411a8e2 100644 --- a/app/src/main/java/com/dayu/pipirrapp/activity/OrderDealActivity.java +++ b/app/src/main/java/com/dayu/pipirrapp/activity/OrderDealActivity.java @@ -23,13 +23,11 @@ import com.dayu.pipirrapp.bean.net.AddProcessingRequest; import com.dayu.pipirrapp.bean.net.InsectionResult; import com.dayu.pipirrapp.bean.net.UplodFileState; -import com.dayu.pipirrapp.dao.DaoSingleton; import com.dayu.pipirrapp.databinding.ActivityOrderDealBinding; import com.dayu.pipirrapp.fragment.OrderFragment; import com.dayu.pipirrapp.net.ApiManager; import com.dayu.pipirrapp.net.BaseResponse; import com.dayu.pipirrapp.net.subscribers.SubscriberListener; -import com.dayu.pipirrapp.net.upload.UploadFileListener; import com.dayu.pipirrapp.tool.FileUploadUtils; import com.dayu.pipirrapp.tool.FullyGridLayoutManager; import com.dayu.pipirrapp.tool.GlideEngine; @@ -58,10 +56,8 @@ import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import retrofit2.Call; @@ -87,6 +83,7 @@ Map<String, UplodFileState> uplodFileStates = new HashMap<>(); String workOrderId; LatLonBean latLonBean; + String strCompleteTime; /** * 瀹氫綅鐩戝惉 @@ -124,13 +121,15 @@ new CardDatePickerDialog.Builder(this) .setTitle("閫夋嫨澶勭悊鏃堕棿") .setOnChoose("纭畾", aLong -> { - //aLong = millisecond - + //aLong = millisecond + strCompleteTime = com.dayu.pipirrapp.utils.DateUtils.formatTimestamp(aLong); + binding.timeData.setText(strCompleteTime); return null; }) .showBackNow(true) .setDefaultTime(time) .setMaxTime(time) + .setMinTime(time - 365L * 24 * 60 * 60 * 1000) // 璁剧疆鏈�灏忔椂闂翠负涓�骞村墠 .setDisplayType(list) .build().show(); }); @@ -306,7 +305,7 @@ result.setContent(binding.contentET.getText().toString()); result.setInspectorId(MyApplication.myApplication.userId); result.setWorkOrderId(workOrderId); - result.setCompleteTime(com.dayu.pipirrapp.utils.DateUtils.getNowDateToMMStr()); + result.setCompleteTime(strCompleteTime); if (latLonBean != null) { result.setLat(String.valueOf(latLonBean.getLatitude())); result.setLng(String.valueOf(latLonBean.getLongitude())); diff --git a/app/src/main/java/com/dayu/pipirrapp/dao/DivideDao.java b/app/src/main/java/com/dayu/pipirrapp/dao/DivideDao.java index aa9295a..a574aa0 100644 --- a/app/src/main/java/com/dayu/pipirrapp/dao/DivideDao.java +++ b/app/src/main/java/com/dayu/pipirrapp/dao/DivideDao.java @@ -17,7 +17,7 @@ import io.reactivex.rxjava3.core.Maybe; /** - * DivideDao - + * DivideDao -鍒嗘按鎴� * * @author zuoxiao * @version 1.0 @@ -52,6 +52,6 @@ @Query("select * from DivideBean") Single<List<DivideBean>> findAllToSingle(); - @Query("SELECT * FROM divide") + @Query("SELECT * FROM DivideBean") Maybe<List<DivideBean>> getAll(); // 鏀逛负杩斿洖Maybe<List<DivideBean>> } diff --git a/app/src/main/java/com/dayu/pipirrapp/dao/MarkerDao.java b/app/src/main/java/com/dayu/pipirrapp/dao/MarkerDao.java index 0323b6d..4bd9344 100644 --- a/app/src/main/java/com/dayu/pipirrapp/dao/MarkerDao.java +++ b/app/src/main/java/com/dayu/pipirrapp/dao/MarkerDao.java @@ -19,7 +19,7 @@ * author: zuo * Date: 2024-09-30 * Time: 14:39 - * 澶囨敞锛� + * 澶囨敞锛氬彇姘村彛 */ @Dao public interface MarkerDao { diff --git a/app/src/main/java/com/dayu/pipirrapp/fragment/MapFragment.java b/app/src/main/java/com/dayu/pipirrapp/fragment/MapFragment.java index ddfb4c4..7229bca 100644 --- a/app/src/main/java/com/dayu/pipirrapp/fragment/MapFragment.java +++ b/app/src/main/java/com/dayu/pipirrapp/fragment/MapFragment.java @@ -5,9 +5,11 @@ import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; +import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -20,6 +22,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; import androidx.lifecycle.Observer; import com.dayu.pipirrapp.MyApplication; @@ -62,6 +65,7 @@ import com.dayu.pipirrapp.utils.WebViewUtils; import com.dayu.pipirrapp.view.ConfirmDialog; import com.dayu.pipirrapp.view.TipUtil; +import com.example.expand_button.ExpandButton; import com.hjq.permissions.OnPermissionCallback; import com.hjq.permissions.Permission; import com.hjq.permissions.XXPermissions; @@ -80,6 +84,7 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.disposables.CompositeDisposable; import io.reactivex.rxjava3.schedulers.Schedulers; +import kotlin.Triple; /** * author: zuo @@ -178,69 +183,69 @@ private void loadLocalData() { // 寮傛鍔犺浇涓績鐐规暟鎹� compositeDisposable.add( - DaoSingleton.getAsynchInstance(this.getContext()).centerPointDao().findFirst() - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(result -> { - centerPointBean = result; - if (centerPointBean == null) { - getCenterPoint(); - } else { - jumpCenterPoint(); - } - }, throwable -> { - Log.e(TAG, "Load centerPoint error: " + throwable); - getCenterPoint(); - }, () -> { - // 褰揗aybe涓虹┖鏃惰皟鐢� - getCenterPoint(); - }) + DaoSingleton.getAsynchInstance(this.getContext()).centerPointDao().findFirst() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(result -> { + centerPointBean = result; + if (centerPointBean == null) { + getCenterPoint(); + } else { + jumpCenterPoint(); + } + }, throwable -> { + Log.e(TAG, "Load centerPoint error: " + throwable); + getCenterPoint(); + }, () -> { + // 褰揗aybe涓虹┖鏃惰皟鐢� + getCenterPoint(); + }) ); // 寮傛鍔犺浇鍙栨按鍙f暟鎹� compositeDisposable.add( - DaoSingleton.getAsynchInstance(this.getContext()).markerDao().getAll() - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(markers -> { - if (markers == null || markers.isEmpty()) { - getMarkerData(); - } else { - for (MarkerBean marker : markers) { - markerBeanSet.put(marker.getId(), marker); - setMapMarker(marker); - } - } - }, throwable -> { - Log.e(TAG, "Load markers error: " + throwable.getMessage()); - getMarkerData(); - }, () -> { - // 褰揗aybe涓虹┖鏃惰皟鐢� - getMarkerData(); - }) + DaoSingleton.getAsynchInstance(this.getContext()).markerDao().getAll() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(markers -> { + if (markers == null || markers.isEmpty()) { + getMarkerData(); + } else { + for (MarkerBean marker : markers) { + markerBeanSet.put(marker.getId(), marker); + setMapMarker(marker); + } + } + }, throwable -> { + Log.e(TAG, "Load markers error: " + throwable.getMessage()); + getMarkerData(); + }, () -> { + // 褰揗aybe涓虹┖鏃惰皟鐢� + getMarkerData(); + }) ); // 寮傛鍔犺浇鍒嗘按鎴挎暟鎹� compositeDisposable.add( - DaoSingleton.getAsynchInstance(this.getContext()).divideDao().getAll() - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(divides -> { - if (divides == null || divides.isEmpty()) { - getDivideList(); - } else { - for (DivideBean divide : divides) { - divideBeanMap.put(divide.getId(), divide); - setMapDivide(divide); - } - } - }, throwable -> { - Log.e(TAG, "Load divides error: " + throwable.getMessage()); - getDivideList(); - }, () -> { - // 褰揗aybe涓虹┖鏃惰皟鐢� - getDivideList(); - }) + DaoSingleton.getAsynchInstance(this.getContext()).divideDao().getAll() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(divides -> { + if (divides == null || divides.isEmpty()) { + getDivideList(); + } else { + for (DivideBean divide : divides) { + divideBeanMap.put(divide.getId(), divide); + setMapDivide(divide); + } + } + }, throwable -> { + Log.e(TAG, "Load divides error: " + throwable.getMessage()); + getDivideList(); + }, () -> { + // 褰揗aybe涓虹┖鏃惰皟鐢� + getDivideList(); + }) ); } @@ -370,19 +375,19 @@ // 浣跨敤 CompositeDisposable 绠$悊鏁版嵁搴撴彃鍏ユ搷浣� compositeDisposable.add( - DaoSingleton.getAsynchInstance(MapFragment.this.getContext()).markerDao().insertAll(markerBeans) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe( - () -> { - // 鎻掑叆鎴愬姛 - Log.i("mWebView", "鏁版嵁鎻掑叆鎴愬姛"); - }, - throwable -> { - // 鎻掑叆澶辫触 - Log.e("mWebView", "鏁版嵁鎻掑叆澶辫触: " + throwable.getMessage()); - } - ) + DaoSingleton.getAsynchInstance(MapFragment.this.getContext()).markerDao().insertAll(markerBeans) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + () -> { + // 鎻掑叆鎴愬姛 + Log.i("mWebView", "鏁版嵁鎻掑叆鎴愬姛"); + }, + throwable -> { + // 鎻掑叆澶辫触 + Log.e("mWebView", "鏁版嵁鎻掑叆澶辫触: " + throwable.getMessage()); + } + ) ); } @@ -432,8 +437,27 @@ Intent issue = new Intent(MapFragment.this.getActivity(), AddIssueActivity.class); MapFragment.this.getActivity().startActivity(issue); }); + binding.expandButton.setLegendsArray(new Triple<>( + ContextCompat.getDrawable(requireContext(), R.drawable.marker_blue), + ContextCompat.getDrawable(requireContext(), R.drawable.marker_unselected), + "鍙栨按鍙�" + ), + new Triple<>( + ContextCompat.getDrawable(requireContext(), R.drawable.divide_home_blue), + ContextCompat.getDrawable(requireContext(), R.drawable.divide_home_unselected), + "鍒嗘按鎴�" + )); + binding.expandButton.setOnLegendItemClickListener((position, isSelected) -> { + switch (position) { + case 0: + showMarkers(isSelected); + break; + case 1: + showDivideMarkers(isSelected); + break; - + } + }); } /** @@ -1010,22 +1034,22 @@ setMapDivide(divideBean); divideBeans.add(divideBean); } - + // 浣跨敤 CompositeDisposable 绠$悊鏁版嵁搴撴彃鍏ユ搷浣� compositeDisposable.add( - DaoSingleton.getAsynchInstance(MapFragment.this.getContext()).divideDao().insertAll(divideBeans) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe( - () -> { - // 鎻掑叆鎴愬姛 - Log.i("mWebView", "鏁版嵁鎻掑叆鎴愬姛"); - }, - throwable -> { - // 鎻掑叆澶辫触 - Log.e("mWebView", "鏁版嵁鎻掑叆澶辫触: " + throwable.getMessage()); - } - ) + DaoSingleton.getAsynchInstance(MapFragment.this.getContext()).divideDao().insertAll(divideBeans) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + () -> { + // 鎻掑叆鎴愬姛 + Log.i("mWebView", "鏁版嵁鎻掑叆鎴愬姛"); + }, + throwable -> { + // 鎻掑叆澶辫触 + Log.e("mWebView", "鏁版嵁鎻掑叆澶辫触: " + throwable.getMessage()); + } + ) ); } } else { @@ -1157,4 +1181,36 @@ mWebView.restoreState(savedInstanceState); } } + + /** + * 鏄剧ず鎴栭殣钘忓湴鍥句笂鐨勫彇姘村彛 + * + * @param isShow + */ + private void showMarkers(boolean isShow) { + if (isShow) { + mWebView.evaluateJavascript("javascript:showAllWaterIntakes()", value -> { + }); + } else { + mWebView.evaluateJavascript("javascript:hideAllWaterIntakes()", value -> { + }); + } + + } + + /** + * 鏄剧ず鎴栭殣钘忓湴鍥句笂鐨勫垎姘存埧 + * + * @param isShow + */ + private void showDivideMarkers(boolean isShow) { + if (isShow) { + mWebView.evaluateJavascript("javascript:showAllDivides()", value -> { + }); + } else { + mWebView.evaluateJavascript("javascript:hideAllDivides()", value -> { + }); + } + } + } diff --git a/app/src/main/java/com/dayu/pipirrapp/utils/DateUtils.java b/app/src/main/java/com/dayu/pipirrapp/utils/DateUtils.java index 1d25d66..1cdc3c5 100644 --- a/app/src/main/java/com/dayu/pipirrapp/utils/DateUtils.java +++ b/app/src/main/java/com/dayu/pipirrapp/utils/DateUtils.java @@ -31,15 +31,25 @@ /** * 杩斿洖缁熶竴鏍煎紡鐨勫綋鍓嶆椂闂存埅姝㈠埌鍒嗛挓 * - * @return yyyy-MM-dd HH:mm:ss + * @return yyyy-MM-dd HH:mm */ public static String getNowDateToMMStr() { // 褰撳墠鏃堕棿 Date date = new Date(); // 鍒涘缓 SimpleDateFormat 瀵硅薄锛岃缃棩鏈熸牸寮� - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault()); // 鏍煎紡鍖栧綋鍓嶆椂闂翠负瀛楃涓� return sdf.format(date); } + /** + * 灏嗘椂闂存埑杞崲涓烘寚瀹氭牸寮忕殑瀛楃涓� + * @param timestamp 鏃堕棿鎴� + * @return 鏍煎紡鍖栧悗鐨勬椂闂村瓧绗︿覆 (yyyy-MM-dd HH:mm) + */ + public static String formatTimestamp(long timestamp) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault()); + return sdf.format(new Date(timestamp)); + } + } diff --git a/app/src/main/res/drawable/divide_home_blue.xml b/app/src/main/res/drawable/divide_home_blue.xml new file mode 100644 index 0000000..30680be --- /dev/null +++ b/app/src/main/res/drawable/divide_home_blue.xml @@ -0,0 +1,25 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="48" + android:viewportHeight="48"> + <path + android:pathData="M9,18V42H39V18L24,6L9,18Z" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#1890FF" + android:strokeLineCap="round"/> + <path + android:pathData="M19,29V42H29V29H19Z" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#1890FF"/> + <path + android:pathData="M9,42H39" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#1890FF" + android:strokeLineCap="round"/> +</vector> diff --git a/app/src/main/res/drawable/divide_home_unselected.xml b/app/src/main/res/drawable/divide_home_unselected.xml new file mode 100644 index 0000000..a37f1fe --- /dev/null +++ b/app/src/main/res/drawable/divide_home_unselected.xml @@ -0,0 +1,25 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="48" + android:viewportHeight="48"> + <path + android:pathData="M9,18V42H39V18L24,6L9,18Z" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#757575" + android:strokeLineCap="round"/> + <path + android:pathData="M19,29V42H29V29H19Z" + android:strokeLineJoin="round" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#757575"/> + <path + android:pathData="M9,42H39" + android:strokeWidth="4" + android:fillColor="#00000000" + android:strokeColor="#757575" + android:strokeLineCap="round"/> +</vector> diff --git a/app/src/main/res/drawable/marker_blue.xml b/app/src/main/res/drawable/marker_blue.xml new file mode 100644 index 0000000..e3e70bf --- /dev/null +++ b/app/src/main/res/drawable/marker_blue.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,2L12,2C8.13,2 5,5.13 5,9c0,1.74 0.5,3.37 1.41,4.84c0.95,1.54 2.2,2.86 3.16,4.4c0.47,0.75 0.81,1.45 1.17,2.26C11,21.05 11.21,22 12,22h0c0.79,0 1,-0.95 1.25,-1.5c0.37,-0.81 0.7,-1.51 1.17,-2.26c0.96,-1.53 2.21,-2.85 3.16,-4.4C18.5,12.37 19,10.74 19,9C19,5.13 15.87,2 12,2zM12,11.75c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5s2.5,1.12 2.5,2.5S13.38,11.75 12,11.75z" + android:fillColor="#1890FF"/> +</vector> diff --git a/app/src/main/res/drawable/marker_unselected.xml b/app/src/main/res/drawable/marker_unselected.xml new file mode 100644 index 0000000..24a8afd --- /dev/null +++ b/app/src/main/res/drawable/marker_unselected.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M12,2L12,2C8.13,2 5,5.13 5,9c0,1.74 0.5,3.37 1.41,4.84c0.95,1.54 2.2,2.86 3.16,4.4c0.47,0.75 0.81,1.45 1.17,2.26C11,21.05 11.21,22 12,22h0c0.79,0 1,-0.95 1.25,-1.5c0.37,-0.81 0.7,-1.51 1.17,-2.26c0.96,-1.53 2.21,-2.85 3.16,-4.4C18.5,12.37 19,10.74 19,9C19,5.13 15.87,2 12,2zM12,11.75c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5s2.5,1.12 2.5,2.5S13.38,11.75 12,11.75z" + android:fillColor="#757575"/> +</vector> diff --git a/app/src/main/res/layout/activity_order_deal.xml b/app/src/main/res/layout/activity_order_deal.xml index 3bc03cb..8481bf9 100644 --- a/app/src/main/res/layout/activity_order_deal.xml +++ b/app/src/main/res/layout/activity_order_deal.xml @@ -62,7 +62,15 @@ android:text="鍙嶉鏃堕棿锛�" android:textColor="@color/black" android:textSize="@dimen/order_detail_button_size" /> - + <TextView + android:id="@+id/timeData" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:layout_toEndOf="@+id/timeTV" + android:layout_marginLeft="10dp" + android:textColor="@color/black" + android:textSize="@dimen/order_detail_button_size" /> <ImageView android:layout_width="25dp" android:layout_height="25dp" diff --git a/app/src/main/res/layout/fragment_map.xml b/app/src/main/res/layout/fragment_map.xml index e0de4e9..9a71ebc 100644 --- a/app/src/main/res/layout/fragment_map.xml +++ b/app/src/main/res/layout/fragment_map.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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" - xmlns:app="http://schemas.android.com/apk/res-auto"> + android:layout_height="match_parent"> <!-- <com.github.lzyzsd.jsbridge.BridgeWebView--> <!-- android:id="@+id/webView"--> @@ -110,17 +110,18 @@ android:id="@+id/expandButton" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:padding="10dp" - android:background="@drawable/ic_green_bg" android:layout_alignParentRight="true" android:layout_marginTop="180dp" - android:textSize="18sp" android:layout_marginRight="15dp" + android:background="@drawable/ic_green_bg" + android:padding="10dp" android:textColor="@color/white" + android:textSize="18sp" + app:animDuration="300" + app:collapsedText="渚�" app:letterSpacing="10dp" - app:expandedText="鐐瑰嚮灞曞紑" - app:collapsedText="鐐�" - app:animDuration="300" /> + app:expandedTextSize="12sp"/> + <RelativeLayout android:id="@+id/pointRL" android:layout_width="match_parent" diff --git a/expand_button/src/main/java/com/example/expand_button/ExpandButton.kt b/expand_button/src/main/java/com/example/expand_button/ExpandButton.kt index c024329..1ac7b29 100644 --- a/expand_button/src/main/java/com/example/expand_button/ExpandButton.kt +++ b/expand_button/src/main/java/com/example/expand_button/ExpandButton.kt @@ -25,10 +25,23 @@ defStyleAttr: Int = 0 ) : AppCompatTextView(context, attrs, defStyleAttr) { + // 淇敼灞炴�� + private data class LegendItem( + val selectedIcon: Drawable, + val unselectedIcon: Drawable, + val description: String, + var isSelected: Boolean = true + ) + + private var legendItems: List<LegendItem> = listOf() + private var itemSpacing: Float = context.resources.displayMetrics.density * 16 // 鍥句緥椤逛箣闂寸殑姘村钩闂磋窛 + private var iconSize: Int = (24 * context.resources.displayMetrics.density).toInt() // 鍥炬爣澶у皬 + private var iconTextSpacing: Float = context.resources.displayMetrics.density * 4 // 鍥炬爣鍜屾枃瀛椾箣闂寸殑鍨傜洿闂磋窛 + // 灞曞紑鏃舵樉绀虹殑瀹屾暣鏂囧瓧 - private var expandedText: String = "" + private var expandedText: String = "鏍囨敞鐐�: 褰撳墠浣嶇疆\n鍖哄煙: 閰嶉�佽寖鍥�" // 鏀惰捣鏃舵樉绀虹殑鍗曚釜瀛楃 - private var collapsedText: String = "" + private var collapsedText: String = "鍥句緥" // 褰撳墠鏄惁澶勪簬灞曞紑鐘舵�� private var isExpanded: Boolean = false // 鍔ㄧ敾鎸佺画鏃堕棿锛岄粯璁�300姣 @@ -50,7 +63,33 @@ // 涓夎褰㈠浘鏍囦笌鏂囧瓧鐨勯棿璺濓紝榛樿涓�8dp private var triangleMargin: Float = 3 * context.resources.displayMetrics.density + // 娣诲姞鏂板睘鎬� + private var textLines: List<String> = listOf() + + // 娣诲姞鐐瑰嚮鍥炶皟鎺ュ彛 + interface OnLegendItemClickListener { + fun onLegendItemClick(position: Int, isSelected: Boolean) + } + + private var legendItemClickListener: OnLegendItemClickListener? = null + + // 淇敼鍥句緥椤圭殑鎬婚珮搴﹁绠� + private val legendItemHeight: Int + get() = iconSize + iconTextSpacing.toInt() + paint.textSize.toInt() + paint.descent().toInt() - paint.ascent().toInt() + + // 娣诲姞灞曞紑鍚庣殑瀛椾綋澶у皬灞炴�� + private var expandedTextSize: Float = textSize + + // 娣诲姞涓�涓彉閲忎繚瀛橀粯璁ゅ瓧浣撳ぇ灏� + private var defaultTextSize: Float = 0f + + // 娣诲姞涓�涓睘鎬у畾涔変笁瑙掑舰鍥炬爣鐨勭偣鍑诲尯鍩熸墿灞曡寖鍥� + private val triangleClickPadding: Float = 15f * context.resources.displayMetrics.density // 20dp + init { + // 淇濆瓨 XML 涓缃殑榛樿瀛椾綋澶у皬 + defaultTextSize = textSize + // 璇诲彇鑷畾涔夊睘鎬� context.theme.obtainStyledAttributes( attrs, @@ -60,10 +99,14 @@ ).apply { try { customLetterSpacing = getDimension(R.styleable.ExpandButton_letterSpacing, customLetterSpacing) - expandedText = getString(R.styleable.ExpandButton_expandedText) ?: "" - collapsedText = getString(R.styleable.ExpandButton_collapsedText) ?: "" + expandedText = getString(R.styleable.ExpandButton_expandedText) ?: "鏍囨敞鐐�: 褰撳墠浣嶇疆\n鍖哄煙: 閰嶉�佽寖鍥�" + collapsedText = getString(R.styleable.ExpandButton_collapsedText) ?: "鍥句緥" animationDuration = getInteger(R.styleable.ExpandButton_animDuration, 300).toLong() triangleMargin = getDimension(R.styleable.ExpandButton_triangleMargin, triangleMargin) + itemSpacing = getDimension(R.styleable.ExpandButton_itemSpacing, itemSpacing) + iconSize = getDimension(R.styleable.ExpandButton_iconSize, iconSize.toFloat()).toInt() + iconTextSpacing = getDimension(R.styleable.ExpandButton_iconTextSpacing, iconTextSpacing) + expandedTextSize = getDimension(R.styleable.ExpandButton_expandedTextSize, defaultTextSize) } finally { recycle() } @@ -80,26 +123,11 @@ } } - // 璁剧疆鏂囨湰鍙偣鍑伙紝浠呭湪鏀惰捣鐘舵�佹椂鍝嶅簲鐐瑰嚮灞曞紑 - setOnClickListener { - if (!isExpanded) { - toggleExpand() - } - } - - // 娣诲姞瑙︽懜浜嬩欢澶勭悊 - setOnTouchListener { _, event -> - when (event.action) { - MotionEvent.ACTION_DOWN -> { - // 妫�鏌ョ偣鍑绘槸鍚﹀湪涓夎褰㈠浘鏍囧尯鍩熷唴 - if (isClickOnTriangle(event.x)) { - toggleExpand() - return@setOnTouchListener true - } - } - } - false - } + // 淇敼瑙︽懜浜嬩欢澶勭悊 + setOnTouchListener(null) // 绉婚櫎鍘熸湁鐨勮Е鎽哥洃鍚櫒 + + // 绉婚櫎鍘熸湁鐨勭偣鍑荤洃鍚櫒 + setOnClickListener(null) // 璁剧疆宸﹁竟璺濓紝涓哄浘鏍囩暀鍑虹┖闂� compoundDrawablePadding = triangleMargin.toInt() @@ -111,23 +139,107 @@ ) // 璁剧疆鍗曡鏄剧ず锛岄槻姝㈤珮搴﹀彉鍖� - maxLines = 1 - isSingleLine = true + maxLines = if (isExpanded) Int.MAX_VALUE else 1 + isSingleLine = !isExpanded // 璁剧疆鏂囧瓧鍨傜洿灞呬腑 gravity = Gravity.CENTER_VERTICAL + + // 璁剧疆榛樿鐨勫唴杈硅窛 + val defaultPadding = (8 * context.resources.displayMetrics.density).toInt() + setPadding( + (16 * context.resources.displayMetrics.density + triangleMargin).toInt(), // 宸﹁竟璺濆鍔狅紝涓哄浘鏍囩暀绌洪棿 + defaultPadding, // 涓婅竟璺� + defaultPadding, // 鍙宠竟璺� + defaultPadding // 涓嬭竟璺� + ) + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + + if (isExpanded) { + // 灞曞紑鐘舵�佷笅鐨勯珮搴﹁绠� + val desiredHeight = legendItemHeight + paddingTop + paddingBottom + setMeasuredDimension(measuredWidth, desiredHeight) + } } override fun onDraw(canvas: Canvas) { - // 淇濆瓨鐢诲竷鐘舵�� + // 缁樺埗灞曞紑/鏀惰捣鍥炬爣 + drawTriangle(canvas) + + if (!isExpanded) { + // 鏀惰捣鐘舵�佷娇鐢ㄩ粯璁ゅ瓧浣撳ぇ灏� + paint.textSize = defaultTextSize + super.onDraw(canvas) + return + } + + // 灞曞紑鐘舵�佷娇鐢ㄥ睍寮�鍚庣殑瀛椾綋澶у皬 + paint.textSize = expandedTextSize + + // 璁$畻鎵�鏈夊浘渚嬮」涓渶瀹界殑瀹藉害 + val maxWidth = legendItems.maxOf { item -> + maxOf(paint.measureText(item.description), iconSize.toFloat()) + } + + // 璁$畻鎬诲搴︼紙娣诲姞棣栧熬鐨勮竟璺濓級 + val totalWidth = legendItems.size * maxWidth + + (legendItems.size + 1) * itemSpacing // 淇敼杩欓噷锛屾坊鍔犱竴涓澶栫殑闂磋窛 + + // 璁$畻璧峰x鍧愭爣锛屼娇鏁翠綋姘村钩灞呬腑 + var x = (width - totalWidth) / 2 + itemSpacing // 娣诲姞璧峰杈硅窛 + + // 璁$畻鍨傜洿灞呬腑鐨剏鍧愭爣锛岃�冭檻涓婁笅杈硅窛 + val centerY = height / 2f + + legendItems.forEachIndexed { index, item -> + // 璁$畻褰撳墠鍥句緥椤圭殑璧峰浣嶇疆锛堢Щ闄ndex > 0鐨勫垽鏂級 + val itemStartX = x + + // 璁$畻鍥炬爣鐨勬按骞充綅缃紙灞呬腑浜庡浘渚嬮」锛� + val iconLeft = itemStartX + (maxWidth - iconSize) / 2 + + // 璁$畻鏂囧瓧鐨勪綅缃� + val textWidth = paint.measureText(item.description) + val textX = itemStartX + (maxWidth - textWidth) / 2 + + // 缁樺埗鍥炬爣锛屾牴鎹�変腑鐘舵�侀�夋嫨涓嶅悓鐨勫浘鏍� + val iconTop = paddingTop + (height - legendItemHeight) / 2 + val currentIcon = if (item.isSelected) item.selectedIcon else item.unselectedIcon + currentIcon.setBounds( + iconLeft.toInt(), + iconTop.toInt(), + (iconLeft + iconSize).toInt(), + (iconTop + iconSize).toInt() + ) + currentIcon.draw(canvas) + + // 缁樺埗鏂囧瓧锛屾牴鎹�変腑鐘舵�佷娇鐢ㄤ笉鍚岀殑棰滆壊 + paint.color = if (item.isSelected) + currentTextColor + else + 0xFF999999.toInt() // 鐏拌壊 + val textY = iconTop + iconSize + iconTextSpacing - paint.ascent() + canvas.drawText(item.description, textX, textY, paint) + + // 鏇存柊涓嬩竴涓浘渚嬮」鐨勮捣濮嬩綅缃� + x = itemStartX + maxWidth + itemSpacing + } + + // 鎭㈠鐢荤瑪棰滆壊 + paint.color = currentTextColor + } + + // 灏嗗師鏉ョ殑onDraw涓殑涓夎褰㈢粯鍒堕�昏緫鎻愬彇鍑烘潵 + private fun drawTriangle(canvas: Canvas) { canvas.save() - // 璁$畻鍥炬爣浣嶇疆 val iconSize = triangleDrawable.intrinsicWidth val iconLeft = paddingLeft - iconSize - compoundDrawablePadding val iconTop = (height - iconSize) / 2 - // 璁剧疆鍥炬爣杈圭晫 triangleDrawable.setBounds( iconLeft, iconTop, @@ -135,20 +247,15 @@ iconTop + iconSize ) - // 鏃嬭浆鐢诲竷 canvas.rotate( triangleRotation, (iconLeft + iconSize / 2).toFloat(), (iconTop + iconSize / 2).toFloat() ) - // 缁樺埗鍥炬爣 triangleDrawable.draw(canvas) - // 鎭㈠鐢诲竷鐘舵�� canvas.restore() - - super.onDraw(canvas) } /** @@ -193,13 +300,18 @@ /** * 鍒囨崲灞曞紑/鏀惰捣鐘舵�� - * 浣跨敤ValueAnimator瀹炵幇瀹藉害鍔ㄧ敾鍜屽浘鏍囨棆杞� */ private fun toggleExpand() { isExpanded = !isExpanded // 璁$畻鏀惰捣鍜屽睍寮�鐘舵�佺殑瀹藉害 - val collapsedWidth = paint.measureText(collapsedText).toInt() + paddingLeft + paddingRight + val collapsedWidth = run { + paint.textSize = defaultTextSize + val width = paint.measureText(collapsedText).toInt() + paddingLeft + paddingRight + paint.textSize = if (isExpanded) expandedTextSize else defaultTextSize + width + } + val expandedWidth = calculateExpandedWidth() // 鍒涘缓瀹藉害鍔ㄧ敾 @@ -225,31 +337,46 @@ duration = animationDuration addUpdateListener { animator -> triangleRotation = animator.animatedValue as Float - invalidate() // 閲嶇粯浠ユ洿鏂板浘鏍囨棆杞� + invalidate() } start() } - // 鏇存柊鏂囨湰 + // 鏇存柊鏂囨湰鍜屽瓧浣撳ぇ灏� if (isExpanded) { - setExpandedClickableText() + paint.textSize = expandedTextSize } else { text = collapsedText + paint.textSize = defaultTextSize + setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, defaultTextSize) } + + invalidate() } /** * 璁$畻灞曞紑鍚庣殑鎬诲搴� */ private fun calculateExpandedWidth(): Int { - val spaceWidth = paint.measureText(" ") * (customLetterSpacing / 10) - // 璁$畻鎵�鏈夊瓧绗︾殑鎬诲搴� - val textWidth = expandedText.fold(0f) { acc, char -> - acc + paint.measureText(char.toString()) + // 涓存椂淇濆瓨褰撳墠瀛椾綋澶у皬 + val currentTextSize = paint.textSize + // 璁剧疆涓哄睍寮�鐘舵�佺殑瀛椾綋澶у皬 + paint.textSize = expandedTextSize + + try { + // 璁$畻鎵�鏈夊浘渚嬮」涓渶瀹界殑瀹藉害 + val maxWidth = legendItems.maxOf { item -> + maxOf(paint.measureText(item.description), iconSize.toFloat()) + } + + // 璁$畻鎬诲搴� = 鎵�鏈夊浘渚嬮」鐨勫搴� + 鎵�鏈夐棿璺濓紙鍖呮嫭棣栧熬锛� + 宸﹀彸鍐呰竟璺� + return (legendItems.size * maxWidth + + (legendItems.size + 1) * itemSpacing + + paddingLeft + paddingRight).toInt() + } finally { + // 鎭㈠鍘熸潵鐨勫瓧浣撳ぇ灏� + paint.textSize = currentTextSize } - // 璁$畻闂磋窛鐨勬�诲搴︼紙瀛楃鏁伴噺鍑�1涓棿璺濓級 - val spacesWidth = spaceWidth * (expandedText.length - 1) - return (textWidth + spacesWidth).toInt() + paddingLeft + paddingRight } /** @@ -257,39 +384,76 @@ */ private fun setExpandedClickableText() { val builder = SpannableStringBuilder() - expandedText.forEachIndexed { index, char -> - // 娣诲姞瀛楃 - builder.append(char) + + // 璁$畻鎵�鏈夊浘渚嬮」涓渶瀹界殑瀹藉害 + val maxWidth = legendItems.maxOf { item -> + maxOf(paint.measureText(item.description), iconSize.toFloat()) + } + + // 璁$畻鎬诲搴� + val totalWidth = legendItems.size * maxWidth + + (legendItems.size - 1) * itemSpacing + + // 璁$畻鏁翠綋姘村钩灞呬腑闇�瑕佺殑璧峰绌烘牸 + val startPadding = ((width - totalWidth) / 2 / paint.measureText(" ")).toInt() + if (startPadding > 0) { + builder.append(" ".repeat(startPadding)) + } + + // 娣诲姞鍨傜洿绌洪棿锛屼负鍥炬爣棰勭暀浣嶇疆 + val verticalSpaces = ((iconSize + iconTextSpacing) / paint.textSize).toInt() + builder.append("\n".repeat(verticalSpaces)) + + legendItems.forEachIndexed { index, item -> + if (index > 0) { + // 鍦ㄥ浘渚嬮」涔嬮棿娣诲姞姘村钩闂磋窛 + builder.append(" ".repeat((itemSpacing / paint.measureText(" ")).toInt())) + } - // 涓哄瓧绗﹁缃偣鍑讳簨浠� + // 璁$畻姘村钩灞呬腑鎵�闇�鐨勭┖鏍兼暟 + val textWidth = paint.measureText(item.description) + val paddingSpaces = ((maxWidth - textWidth) / 2 / paint.measureText(" ")).toInt() + + // 娣诲姞宸︿晶绌烘牸瀹炵幇灞呬腑 + if (paddingSpaces > 0) { + builder.append(" ".repeat(paddingSpaces)) + } + + // 娣诲姞鎻忚堪鏂囨湰 + val startPosition = builder.length + builder.append(item.description) + + // 娣诲姞鍙充晶绌烘牸浠ョ‘淇濆搴︿竴鑷� + val remainingSpaces = ((maxWidth - textWidth) / paint.measureText(" ")).toInt() - paddingSpaces + if (remainingSpaces > 0) { + builder.append(" ".repeat(remainingSpaces)) + } + + // 涓烘枃瀛楄缃偣鍑讳簨浠� val clickableSpan = object : ClickableSpan() { override fun onClick(view: View) { - onCharClickListener?.invoke(char, index) + onCharClickListener?.invoke(item.description[0], index) } override fun updateDrawState(ds: android.text.TextPaint) { super.updateDrawState(ds) - // 绉婚櫎涓嬪垝绾� ds.isUnderlineText = false - // 淇濇寔鍘熷鏂囧瓧棰滆壊 ds.color = currentTextColor } } + builder.setSpan( clickableSpan, - builder.length - 1, - builder.length, + startPosition, + startPosition + item.description.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE ) - - // 鍙湪闈炴渶鍚庝竴涓瓧绗﹀悗娣诲姞绌烘牸浣滀负闂磋窛 - if (index < expandedText.length - 1) { - builder.append(" ".repeat((customLetterSpacing / 10).toInt())) - } } + // 璁剧疆鏂囨湰瀵归綈鏂瑰紡涓哄眳涓� + gravity = Gravity.CENTER + text = builder - // 鍚敤LinkMovementMethod浠ュ搷搴擟lickableSpan鐨勭偣鍑讳簨浠� movementMethod = android.text.method.LinkMovementMethod.getInstance() } @@ -299,7 +463,10 @@ private fun isClickOnTriangle(x: Float): Boolean { val iconSize = triangleDrawable.intrinsicWidth val iconLeft = paddingLeft - iconSize - compoundDrawablePadding - return x <= paddingLeft && x >= iconLeft + + // 鎵╁ぇ鐐瑰嚮鍖哄煙锛氬乏鍙冲悇澧炲姞 triangleClickPadding + return x <= (paddingLeft + triangleClickPadding) && + x >= (iconLeft - triangleClickPadding) } /** @@ -316,4 +483,129 @@ paddingBottom ) } + + /** + * 璁剧疆鍥句緥鍐呭 + */ + @JvmName("setLegendsList") + fun setLegends(items: List<Triple<Drawable, Drawable, String>>) { + legendItems = items.map { (selectedIcon, unselectedIcon, description) -> + selectedIcon.setBounds(0, 0, iconSize, iconSize) + unselectedIcon.setBounds(0, 0, iconSize, iconSize) + LegendItem(selectedIcon, unselectedIcon, description) + } + + if (!isExpanded) { + text = collapsedText + } else { + invalidate() + } + requestLayout() + } + + // 娣诲姞涓�涓� Java 鍙嬪ソ鐨勬柟娉� + @JvmName("setLegendsArray") + fun setLegends(vararg items: Triple<Drawable, Drawable, String>) { + setLegends(items.toList()) + } + + /** + * 娣诲姞璁剧疆鐩戝惉鍣ㄧ殑鏂规硶 + */ + fun setOnLegendItemClickListener(listener: OnLegendItemClickListener) { + legendItemClickListener = listener + } + + /** + * 澶勭悊瑙︽懜浜嬩欢 + */ + override fun onTouchEvent(event: MotionEvent): Boolean { + when (event.action) { + MotionEvent.ACTION_DOWN -> { + // 妫�鏌ョ偣鍑绘槸鍚﹀湪涓夎褰㈠浘鏍囧尯鍩熷唴 + if (isClickOnTriangle(event.x)) { + toggleExpand() + return true + } + + // 濡傛灉鏄睍寮�鐘舵�侊紝妫�鏌ユ槸鍚︾偣鍑讳簡鍥句緥椤� + if (isExpanded) { + val clickedIndex = getClickedItemIndex(event.x, event.y) + if (clickedIndex != -1) { + toggleItemSelection(clickedIndex) + return true + } + } else if (!isExpanded && event.x > paddingLeft) { + // 鍦ㄦ敹璧风姸鎬佷笅锛岀偣鍑婚潪涓夎褰㈠尯鍩熶篃灞曞紑 + toggleExpand() + return true + } + } + } + return super.onTouchEvent(event) + } + + /** + * 鑾峰彇鐐瑰嚮浣嶇疆瀵瑰簲鐨勫浘渚嬮」绱㈠紩 + */ + private fun getClickedItemIndex(x: Float, y: Float): Int { + if (!isExpanded) return -1 + + val maxWidth = legendItems.maxOf { item -> + maxOf(paint.measureText(item.description), iconSize.toFloat()) + } + + val totalWidth = legendItems.size * maxWidth + + (legendItems.size - 1) * itemSpacing + + val startX = (width - totalWidth) / 2 + val iconTop = paddingTop + (height - legendItemHeight) / 2 + val iconBottom = iconTop + legendItemHeight + + // 妫�鏌ュ瀭鐩存柟鍚戞槸鍚﹀湪鍥句緥椤硅寖鍥村唴 + if (y < iconTop || y > iconBottom) return -1 + + // 妫�鏌ユ按骞虫柟鍚戠偣鍑荤殑鏄摢涓浘渚嬮」 + legendItems.forEachIndexed { index, _ -> + val itemStartX = startX + index * (maxWidth + itemSpacing) + val itemEndX = itemStartX + maxWidth + if (x >= itemStartX && x <= itemEndX) { + return index + } + } + return -1 + } + + /** + * 鍒囨崲鍥句緥椤圭殑閫変腑鐘舵�� + */ + private fun toggleItemSelection(index: Int) { + if (index < 0 || index >= legendItems.size) return + + legendItems[index].isSelected = !legendItems[index].isSelected + legendItemClickListener?.onLegendItemClick( + index, + legendItems[index].isSelected + ) + invalidate() + } + + /** + * 璁剧疆灞曞紑鍚庣殑瀛椾綋澶у皬 + * @param size 瀛椾綋澶у皬锛堝儚绱狅級 + */ + fun setExpandedTextSize(size: Float) { + this.expandedTextSize = size + if (isExpanded) { + invalidate() + } + } + + /** + * 璁剧疆灞曞紑鍚庣殑瀛椾綋澶у皬锛圫P锛� + * @param sp 瀛椾綋澶у皬锛圫P锛� + */ + fun setExpandedTextSizeSp(sp: Float) { + setExpandedTextSize(sp * context.resources.displayMetrics.scaledDensity) + } } \ No newline at end of file diff --git a/expand_button/src/main/res/values/attrs.xml b/expand_button/src/main/res/values/attrs.xml index 1d34c70..aca0c25 100644 --- a/expand_button/src/main/res/values/attrs.xml +++ b/expand_button/src/main/res/values/attrs.xml @@ -11,5 +11,11 @@ <attr name="animDuration" format="integer"/> <!-- 涓夎褰㈠浘鏍囦笌鏂囧瓧鐨勯棿璺� --> <attr name="triangleMargin" format="dimension"/> + <!-- 鏂板灞炴�� --> + <attr name="itemSpacing" format="dimension"/> + <attr name="iconSize" format="dimension"/> + <attr name="iconTextSpacing" format="dimension"/> + <!-- 鏂板灞曞紑鍚庣殑瀛椾綋澶у皬灞炴�� --> + <attr name="expandedTextSize" format="dimension"/> </declare-styleable> </resources> \ No newline at end of file -- Gitblit v1.8.0