最近开发车主相关的App功用, 做一个出行功用大致和高德道路规划功用相当。 对高德的道路规划交做了详尽的调研。 功用拆分开来,道路规划逻辑首要涉及:POI查找和 道路规划; UI部分首要任务在查找输入框开发, 列表开发, 道路图层开发。 道路的查找和道路规划及其规划线路绘制方面高德敞开渠道均有文档详细介绍,就不再细谈了;此篇首要介绍仿高德的道路查找交互界面的开发,本文简称为道路查找框开发。
此道路查找框有两种状况,修改途径点态和无途径点态; 此外 修改途径点态还包含拖动地址改动顺序功用。 考虑拖动的交互,Android里常选的计划是RecyclerView实现;但是今日咱们选用Tween动画实现拖动的交互作用。 Tween Animation 和属性动画不一样,不改动View的实在属性数据(也就不改动子View实在方位),仅动画作用的显现,可利用此特性来展现拖动时的切换作用,和拖动完毕时回到实在状况的一个切换。 利用数据交流来刷新 拖动后台的UI。
UI全体布局选用XML硬编码的形式引进,使用include的方式复用每条方位POI查找框。
<LinearLayout
android:id="@+id/ll_more_edit_line"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/ll_edit_action"
android:orientation="vertical">
<include
android:id="@+id/ll_start_location"
layout="@layout/edit_search_key" />
<include
android:id="@+id/ll_end_location"
layout="@layout/edit_search_key" />
</LinearLayout>
edit_search_key.xml文件, 定义每条查找POI的子View
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RelativeLayout
android:id="@+id/ll_edit_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_edt"
android:layout_width="@dimen/dp_32"
android:layout_height="@dimen/dp_32"
android:scaleType="centerInside"
android:src="@drawable/start_location_point" />
<EditText
android:id="@+id/edt_input_key"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/iv_edt"
android:background="@color/transparent"
android:hint=""
android:minHeight="@dimen/dp_32"
android:paddingVertical="@dimen/dp_6"
android:singleLine="true"
android:text="@string/confirm"
android:textColor="@color/text_content_first"
android:textColorHint="@color/text_content_five"
android:textSize="@dimen/dp_14" />
<ImageView
android:id="@+id/iv_edit_move_tag"
android:layout_width="@dimen/fit_dp_20"
android:layout_height="@dimen/fit_dp_20"
android:layout_alignRight="@+id/edt_input_key"
android:layout_centerVertical="true"
android:layout_marginRight="@dimen/fit_dp_8"
android:src="@drawable/icon_edit_move"
android:visibility="gone" />
</RelativeLayout>
<ImageView
android:id="@+id/iv_del_edit"
android:layout_width="@dimen/dp_20"
android:layout_height="@dimen/dp_20"
android:layout_gravity="center_vertical"
android:layout_marginLeft="@dimen/dp_8"
android:scaleType="centerInside"
android:src="@drawable/ic_close"
android:visibility="gone" />
</LinearLayout>
增删途径点,经过LinearLayout布局动态AddView()和RemoveView()实现; 增加途径点
/**
* @param middleIndex 从0开端,扫除起点和结尾之外的列表
*/
private fun addMiddleLocation(middleIndex: Int = 0): EditText {
val params = LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
val top: Int = resources.getDimensionPixelSize(R.dimen.dp_6)
val bottom = 0
params.topMargin = top
params.bottomMargin = bottom
val middleViewBinding = createMiddleLocationEditView();
var middlePos: Int = middleIndex
if (getMiddleCount() > middleIndex) {
binding.llMoreEditLine.addView(middleViewBinding.root, middleIndex + 1, params)
} else {
val index = binding.llMoreEditLine.childCount - 1;
binding.llMoreEditLine.addView(middleViewBinding.root, index, params)
middlePos = getMiddleCount() - 1;
}
val middleData = EditLocation.createMiddleLocation()
middleViewBinding.root.setTag(R.id.cb_item_tag, middleData)
middleViewBinding.edtInputKey.setTag(R.id.cb_item_tag, middleData)
locationList.add(middlePos + 1, middleData)
updateAddMoreUIState()
post {
middleViewBinding.edtInputKey.requestFocus()
}
return middleViewBinding.edtInputKey
}
删除途径点
/**
* @param middleIndex 从0开端,扫除起点和结尾之外的列表
*/
private fun removeMiddleLocation(middleIndex: Int) {
getMiddleItemViewAt(middleIndex)?.let { child ->
binding.llMoreEditLine.removeView(child)
(child.getTag(R.id.cb_item_tag) as? EditLocation).let { data ->
locationList.remove(data)
}
}
val count = getMiddleCount()
switchUIState(true, count)
updateAddMoreUIState()
}
长按事情的触发直接在事情分发的顶层阻拦接触事情判断是否长按:
val mainHandler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
when (msg.what) {
MSG_LONG_CLICK -> {
val obj = msg.obj as Point
val windowX = obj.x;
val windowY = obj.y
findLongTouchValidView(windowX, windowY)?.let { findDragView ->
onDragStart(findDragView, msg.arg1, msg.arg2)
}
}
}
}
}
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
var dy = 0f
val tempDragView = dragSelectedView;
when (ev?.action) {
MotionEvent.ACTION_DOWN -> {
yPos = ev.y
mainHandler.removeMessages(MSG_LONG_CLICK)
val msg = mainHandler.obtainMessage(MSG_LONG_CLICK)
msg.arg1 = ev.x.toInt()
msg.arg2 = ev.y.toInt()
msg.obj = Point(ev.rawX.toInt(), ev.rawY.toInt())
mainHandler.sendMessageDelayed(msg, LONG_TIME)
}
MotionEvent.ACTION_MOVE -> {
dy = ev.y - yPos;
yPos = ev.y
if (tempDragView != null && dy != 0f) {
mainHandler.removeMessages(MSG_LONG_CLICK)
onDragMove(tempDragView!!, ev.x.toInt(), ev.y.toInt(), dy)
}
}
MotionEvent.ACTION_CANCEL -> {
mainHandler.removeMessages(MSG_LONG_CLICK)
if (tempDragView != null) {
onDragEnd()
}
}
MotionEvent.ACTION_UP -> {
mainHandler.removeMessages(MSG_LONG_CLICK)
if (tempDragView != null) {
onDragEnd()
}
}
}
if (tempDragView != null) {
return true
}
return super.dispatchTouchEvent(ev);
}
拖动的View是一个可以悬浮在容器之上的空间中, 需求定义一个View来显现拖拽的目标View,这里选用的是ImageView; 把即将拖拽的View生成对应Bitmap来显现到悬浮的ImageView中,并把悬浮的方位设定在拖拽View的方位,实现拖拽重合移动作用。 代码片段如下:
/**
* 开端拖拽,在长按事情触发之后
*/
private fun onDragStart(dragItemVIew: View, touchX: Int, touchY: Int) {
try {
if (itemEditHeight != 0 && isDragEnable()) {
val itemView = dragItemVIew
val vImage = vToBitmap(itemView)
floatView.setImageBitmap(vImage)
val top = itemView.top + ((itemView.parent as? View)?.top ?: 0)
Log.w(TAG, "top === $top");
floatView.tag = top;
setViewTopMargin(floatView, top)
floatView.visibility = View.VISIBLE
itemView.visibility = INVISIBLE
dragSelectedView = itemView;
dragInsertViewStack.clear();
resetItemViewRectInfo()
ClickVibrator.clickSingle(context, 100L)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
/**
* 拖拽移动
*/
private fun onDragMove(dragItemVIew: View, touchX: Int, touchY: Int, dy: Float) {
val newTop: Int = floatView.tag as Int + dy.toInt()
val newBottom: Int = newTop + itemEditHeight;
if (newTop in minDragTop..maxDragTop) {
floatView.tag = newTop
setViewTopMargin(floatView, newTop)
//磕碰检测
for (rect in itemRectHashMap.keys) {
val line = rect.top + rect.height() / 2
val itemView = itemRectHashMap.get(rect)
if (itemView == dragSelectedView) {
continue
}
if (line in newTop..newBottom) {
//产生磕碰
val dTop = line - newTop;
val dBottom = newBottom - line;
Log.w(TAG, "move === $dTop -- $dBottom")
val fromTop = rect.top;
val animDistance = rect.height() + resources.getDimensionPixelSize(R.dimen.dp_6)
if (dTop < dBottom) {
//item down
post {
val destTop = fromTop + animDistance
itemView?.let {
itemRectHashMap.remove(rect)
val newRect =
Rect(rect.left, destTop, rect.right, destTop + itemEditHeight)
itemRectHashMap.put(newRect, itemView)
trans(itemView, rect, newRect)
}
}
} else {
//item up
post {
val destTop = fromTop - animDistance
itemView?.let {
itemRectHashMap.remove(rect)
val newRect =
Rect(rect.left, destTop, rect.right, destTop + itemEditHeight)
itemRectHashMap.put(newRect, itemView)
trans(itemView, rect, newRect)
}
}
}
break;
}
}
}
}
/**
* 拖拽完毕
*/
private fun onDragEnd() {
val replaceView = if (dragInsertViewStack.isEmpty()) null else dragInsertViewStack.pop()
if (dragSelectedView != null && replaceView != null) {
val dragData = dragSelectedView?.getTag(R.id.cb_item_tag) as? EditLocation
val replaceData = replaceView.getTag(R.id.cb_item_tag) as? EditLocation
callEditLocationDataChange(dragData, replaceData)
}
clearDragUIState()
}
平移动画实现,需求注意的是:平移的参数首要是相对View的原始方位 核算上下移动的方位。 所以需求改根据方位核算坐标变换。
private fun trans(item: View?, fromRect: Rect, toRect: Rect) {
val divideTop = binding.rlEditLocationContainer.top
val fromTop = fromRect.top - divideTop
val destTop = toRect.top - divideTop
val originTop = (item?.top ?: 0) + ((item?.parent as? View)?.top ?: 0)
val animationDis = destTop - fromTop
val moveOut = originTop == fromTop
if (moveOut) {
dragInsertViewStack.push(item)
} else if (!dragInsertViewStack.isEmpty()) {
dragInsertViewStack.pop();
}
val fromY = if (moveOut) 0 else -1 * animationDis
val toY = if (moveOut) animationDis else 0;
Log.w(TAG, "trans start == $originTop --- $fromY,$toY")
val tran = TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f,
Animation.ABSOLUTE, fromY.toFloat(), Animation.ABSOLUTE, toY.toFloat()
)
tran.duration = (300L)
tran.fillAfter = true;
item?.startAnimation(tran)
}
在拖动完毕时清空所用动画和 核算交流后的数据,从头更新对应方位的显现数据。
private fun callEditLocationDataChange(dragData: EditLocation?, replaceData: EditLocation?) {
if (dragData == null || replaceData == null) {
return;
}
val tempList = ArrayList<EditLocation>();
val tempPoiList = ArrayList<EditLocation>();
tempList.addAll(locationList)
val dragIndex = tempList.indexOf(dragData)
val replaceIndex = tempList.indexOf(replaceData);
if (dragIndex != -1 && replaceIndex != -1 && dragIndex != replaceIndex) {
tempList.removeAt(dragIndex);
val insertIndex = tempList.indexOf(replaceData);
if (insertIndex != -1) {
val addIndex = if (dragIndex > replaceIndex) insertIndex else insertIndex + 1
tempList.add(addIndex, dragData)
}
if (tempList.size == locationList.size) {
for (item in tempList) {
val temp = EditLocation()
temp.poi = item.poi;
temp.editContent = item.editContent
tempPoiList.add(temp)
}
for (i in 0 until locationList.size) {
val item = locationList[i]
val tempData = tempPoiList[i]
item.poi = tempData.poi;
item.editContent = tempData.editContent
val tv = findLocationTextView(i)
updateLocationUI(item, tv)
}
}
}
tempList.clear()
tempPoiList.clear()
}
private fun clearDragUIState() {
dragSelectedView?.visibility = View.VISIBLE
floatView.visibility = View.GONE
dragSelectedView = null
for (i in 0 until binding.llMoreEditLine.childCount) {
binding.llMoreEditLine.getChildAt(i)?.clearAnimation()
}
dragInsertViewStack.clear()
}
附上完好代码:
package com.cw.widget.map
import android.content.Context
import android.graphics.*
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.animation.Animation
import android.view.animation.TranslateAnimation
import android.widget.ImageView
import com.cw.widget.R
import com.cw.widget.utils.ClickVibrator
import java.util.*
class DragEditTripLocationView : EditTripLocationListView {
val TAG = "Car-EditTrip %s"
constructor(context: Context) : super(context) {}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
) {
}
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes) {
}
companion object {
const val LONG_TIME = 1000L;
const val MSG_LONG_CLICK = 100;
const val isDebug = false;
}
val floatView: ImageView
var itemEditHeight: Int = 0;
var itemEditWidth: Int = 0;
var minDragTop: Int = 0;
var maxDragTop: Int = 0;
var testPaint: Paint = Paint()
var dragSelectedView: View? = null;
val itemRectHashMap = HashMap<Rect, View>();
val floatPaint = Paint();
/**
* 脱拽过程中插入的View
*/
private val dragInsertViewStack = Stack<View?>();
val mainHandler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
when (msg.what) {
MSG_LONG_CLICK -> {
val obj = msg.obj as Point
val windowX = obj.x;
val windowY = obj.y
findLongTouchValidView(windowX, windowY)?.let { findDragView ->
onDragStart(findDragView, msg.arg1, msg.arg2)
}
}
}
}
}
init {
floatView = ImageView(context)
binding.rlEditTwoLocation.addView(
floatView,
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT
)
floatView.visibility = View.GONE
testPaint.color = Color.RED;
testPaint.style = Paint.Style.STROKE
floatPaint.color = Color.parseColor("#ffc0df17");
floatPaint.strokeWidth = 2f;
floatPaint.style = Paint.Style.STROKE
}
private fun setViewTopMargin(v: View, top: Int) {
(v.layoutParams as? MarginLayoutParams)?.let { p ->
p.topMargin = top;
v.layoutParams = p;
}
}
private fun vToBitmap(v: View): Bitmap {
val w = v.width;
val h = v.height;
val bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565)
val canvas = Canvas(bitmap)
canvas.drawColor(Color.WHITE)
v.draw(canvas)
val editWidth = v.findViewById<View>(R.id.ll_edit_content)?.width ?: w
val corners = resources.getDimensionPixelSize(R.dimen.dp_2)
canvas.drawRoundRect(
RectF(0f, 0f, editWidth.toFloat(), h.toFloat()),
corners.toFloat(),
corners.toFloat(),
floatPaint
)
canvas.setBitmap(null)
return bitmap
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
itemEditWidth = getMiddleItemViewAt(0)?.width ?: 0
itemEditHeight = getMiddleItemViewAt(0)?.height ?: 0
}
override fun dispatchDraw(canvas: Canvas?) {
super.dispatchDraw(canvas)
if (isDebug) {
if (itemRectHashMap.isNotEmpty()) {
for (item in itemRectHashMap.keys) {
canvas?.drawRect(item, testPaint)
}
}
}
}
private fun resetItemViewRectInfo() {
minDragTop = 0;
maxDragTop = binding.rlEditTwoLocation.height - itemEditHeight;
itemRectHashMap.clear();
for (i in 0 until binding.llMoreEditLine.childCount) {
val itemView = binding.llMoreEditLine.getChildAt(i)
if (itemView != null && itemView != dragSelectedView) {
itemRectHashMap.put(getViewRect(itemView), itemView)
}
}
}
/**
* 获取相对于整个View 的Rect数据
*/
private fun getViewRect(v: View): Rect {
val pTop = binding.rlEditLocationContainer.top + ((v.parent as? View)?.top ?: 0)
val top = v.top + pTop
val bottom = v.bottom + pTop;
val left = 0;
val right = v.width;
return Rect(left, top, right, bottom)
}
private fun findLongTouchValidView(x: Int, y: Int): View? {
val rect = Rect();
for (i in 0 until binding.llMoreEditLine.childCount) {
binding.llMoreEditLine.getChildAt(i)?.let {
it.getGlobalVisibleRect(rect)
if (rect.contains(x, y)) {
return it
}
}
}
return null;
}
private fun isDragEnable(): Boolean {
return binding.rlMoreAddLocation.visibility == View.VISIBLE
}
/**
* 开端拖拽,在长按事情触发之后
*/
private fun onDragStart(dragItemVIew: View, touchX: Int, touchY: Int) {
try {
if (itemEditHeight != 0 && isDragEnable()) {
val itemView = dragItemVIew
val vImage = vToBitmap(itemView)
floatView.setImageBitmap(vImage)
val top = itemView.top + ((itemView.parent as? View)?.top ?: 0)
Log.w(TAG, "top === $top");
floatView.tag = top;
setViewTopMargin(floatView, top)
floatView.visibility = View.VISIBLE
itemView.visibility = INVISIBLE
dragSelectedView = itemView;
dragInsertViewStack.clear();
resetItemViewRectInfo()
ClickVibrator.clickSingle(context, 100L)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
/**
* 拖拽移动
*/
private fun onDragMove(dragItemVIew: View, touchX: Int, touchY: Int, dy: Float) {
val newTop: Int = floatView.tag as Int + dy.toInt()
val newBottom: Int = newTop + itemEditHeight;
if (newTop in minDragTop..maxDragTop) {
floatView.tag = newTop
setViewTopMargin(floatView, newTop)
//磕碰检测
for (rect in itemRectHashMap.keys) {
val line = rect.top + rect.height() / 2
val itemView = itemRectHashMap.get(rect)
if (itemView == dragSelectedView) {
continue
}
if (line in newTop..newBottom) {
//产生磕碰
val dTop = line - newTop;
val dBottom = newBottom - line;
Log.w(TAG, "move === $dTop -- $dBottom")
val fromTop = rect.top;
val animDistance = rect.height() + resources.getDimensionPixelSize(R.dimen.dp_6)
if (dTop < dBottom) {
//item down
post {
val destTop = fromTop + animDistance
itemView?.let {
itemRectHashMap.remove(rect)
val newRect =
Rect(rect.left, destTop, rect.right, destTop + itemEditHeight)
itemRectHashMap.put(newRect, itemView)
trans(itemView, rect, newRect)
}
}
} else {
//item up
post {
val destTop = fromTop - animDistance
itemView?.let {
itemRectHashMap.remove(rect)
val newRect =
Rect(rect.left, destTop, rect.right, destTop + itemEditHeight)
itemRectHashMap.put(newRect, itemView)
trans(itemView, rect, newRect)
}
}
}
break;
}
}
}
}
private fun trans(item: View?, fromRect: Rect, toRect: Rect) {
val divideTop = binding.rlEditLocationContainer.top
val fromTop = fromRect.top - divideTop
val destTop = toRect.top - divideTop
val originTop = (item?.top ?: 0) + ((item?.parent as? View)?.top ?: 0)
val animationDis = destTop - fromTop
val moveOut = originTop == fromTop
if (moveOut) {
dragInsertViewStack.push(item)
} else if (!dragInsertViewStack.isEmpty()) {
dragInsertViewStack.pop();
}
val fromY = if (moveOut) 0 else -1 * animationDis
val toY = if (moveOut) animationDis else 0;
Log.w(TAG, "trans start == $originTop --- $fromY,$toY")
val tran = TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f,
Animation.ABSOLUTE, fromY.toFloat(), Animation.ABSOLUTE, toY.toFloat()
)
tran.duration = (300L)
tran.fillAfter = true;
item?.startAnimation(tran)
}
/**
* 拖拽完毕
*/
private fun onDragEnd() {
val replaceView = if (dragInsertViewStack.isEmpty()) null else dragInsertViewStack.pop()
if (dragSelectedView != null && replaceView != null) {
val dragData = dragSelectedView?.getTag(R.id.cb_item_tag) as? EditLocation
val replaceData = replaceView.getTag(R.id.cb_item_tag) as? EditLocation
callEditLocationDataChange(dragData, replaceData)
}
clearDragUIState()
}
private fun callEditLocationDataChange(dragData: EditLocation?, replaceData: EditLocation?) {
if (dragData == null || replaceData == null) {
return;
}
val tempList = ArrayList<EditLocation>();
val tempPoiList = ArrayList<EditLocation>();
tempList.addAll(locationList)
val dragIndex = tempList.indexOf(dragData)
val replaceIndex = tempList.indexOf(replaceData);
if (dragIndex != -1 && replaceIndex != -1 && dragIndex != replaceIndex) {
tempList.removeAt(dragIndex);
val insertIndex = tempList.indexOf(replaceData);
if (insertIndex != -1) {
val addIndex = if (dragIndex > replaceIndex) insertIndex else insertIndex + 1
tempList.add(addIndex, dragData)
}
if (tempList.size == locationList.size) {
for (item in tempList) {
val temp = EditLocation()
temp.poi = item.poi;
temp.editContent = item.editContent
tempPoiList.add(temp)
}
for (i in 0 until locationList.size) {
val item = locationList[i]
val tempData = tempPoiList[i]
item.poi = tempData.poi;
item.editContent = tempData.editContent
val tv = findLocationTextView(i)
updateLocationUI(item, tv)
}
}
}
tempList.clear()
tempPoiList.clear()
}
private fun clearDragUIState() {
dragSelectedView?.visibility = View.VISIBLE
floatView.visibility = View.GONE
dragSelectedView = null
for (i in 0 until binding.llMoreEditLine.childCount) {
binding.llMoreEditLine.getChildAt(i)?.clearAnimation()
}
dragInsertViewStack.clear()
}
private var yPos = 0f;
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
var dy = 0f
val tempDragView = dragSelectedView;
when (ev?.action) {
MotionEvent.ACTION_DOWN -> {
yPos = ev.y
mainHandler.removeMessages(MSG_LONG_CLICK)
val msg = mainHandler.obtainMessage(MSG_LONG_CLICK)
msg.arg1 = ev.x.toInt()
msg.arg2 = ev.y.toInt()
msg.obj = Point(ev.rawX.toInt(), ev.rawY.toInt())
mainHandler.sendMessageDelayed(msg, LONG_TIME)
}
MotionEvent.ACTION_MOVE -> {
dy = ev.y - yPos;
yPos = ev.y
if (tempDragView != null && dy != 0f) {
mainHandler.removeMessages(MSG_LONG_CLICK)
onDragMove(tempDragView!!, ev.x.toInt(), ev.y.toInt(), dy)
}
}
MotionEvent.ACTION_CANCEL -> {
mainHandler.removeMessages(MSG_LONG_CLICK)
if (tempDragView != null) {
onDragEnd()
}
}
MotionEvent.ACTION_UP -> {
mainHandler.removeMessages(MSG_LONG_CLICK)
if (tempDragView != null) {
onDragEnd()
}
}
}
if (tempDragView != null) {
return true
}
return super.dispatchTouchEvent(ev);
}
}
package com.cw.widget.map
import android.app.Activity
import android.content.Context
import android.graphics.ColorMatrix
import android.graphics.ColorMatrixColorFilter
import android.graphics.Paint
import android.text.Editable
import android.text.TextWatcher
import android.util.AttributeSet
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.EditText
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.TextView
import com.blankj.utilcode.util.KeyboardUtils
import com.blankj.utilcode.util.ToastUtils
import com.cw.widget.R
import com.cw.widget.bean.POIType
import com.cw.widget.bean.SearchPOI
import com.cw.widget.databinding.EditSearchKeyBinding
import com.cw.widget.databinding.EditTripLocationListBinding
/**
* 新建,修改行程的修改View
*/
open class EditTripLocationListView : FrameLayout {
constructor(context: Context) : super(context) {}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
) {
}
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes) {
}
val binding: EditTripLocationListBinding
val MAX_MIDDLE_NUM = 3;
val locationList: ArrayList<EditLocation>
private val startLocation: EditLocation
private val endLocation: EditLocation
var onEventListener: OnEventListener? = null
/**
* 文字改变疏忽改动
*/
var textChangeIgnoreTask: TextChangeIgnore? = null
init {
startLocation = EditLocation.createStartLocation(context)
endLocation = EditLocation.createEndLocation()
locationList = ArrayList<EditLocation>()
locationList.add(startLocation)
locationList.add(endLocation)
binding = EditTripLocationListBinding.inflate(LayoutInflater.from(context))
addView(binding.root, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
binding.llStartLocation.ivEdt.setImageResource(R.drawable.start_location_point)
binding.llStartLocation.edtInputKey.setText("")
binding.llStartLocation.edtInputKey.hint = "请输入起点"
binding.llStartLocation.edtInputKey.contentDescription = "起点"
setUpEditViewKeyboard(binding.llStartLocation.edtInputKey)
val startWatcher = EditTextWatcher(this, binding.llStartLocation.edtInputKey)
binding.llStartLocation.edtInputKey.addTextChangedListener(startWatcher)
binding.llStartLocation.root.setTag(R.id.cb_item_tag, startLocation)
binding.llStartLocation.edtInputKey.setTag(R.id.cb_item_tag, startLocation)
updateLocationUI(startLocation)
binding.llEndLocation.ivEdt.setImageResource(R.drawable.end_location_point)
binding.llEndLocation.root.setTag(R.id.cb_item_tag, endLocation)
binding.llEndLocation.edtInputKey.setTag(R.id.cb_item_tag, endLocation)
binding.llEndLocation.edtInputKey.contentDescription = "结尾"
setUpEditViewKeyboard(binding.llEndLocation.edtInputKey)
val endWatcher = EditTextWatcher(this, binding.llEndLocation.edtInputKey)
binding.llEndLocation.edtInputKey.addTextChangedListener(endWatcher)
binding.llEndLocation.edtInputKey.setText("")
binding.llEndLocation.edtInputKey.hint = "请输入结尾"
switchUIState(false)
post {
if (binding.llStartLocation.edtInputKey.text.isNullOrEmpty()) {
binding.llStartLocation.edtInputKey.requestFocus()
} else {
binding.llEndLocation.edtInputKey.requestFocus()
}
}
binding.ivAddLocation.setOnClickListener {
val index = getMiddleCount()
if (index < MAX_MIDDLE_NUM) {
var addIndex = index
(findFocusEditTextView()?.getTag(R.id.cb_item_tag) as? EditLocation)?.let {
val findIndex = locationList.indexOf(it)
if (findIndex != -1) {
addIndex = findIndex;
}
}
addMiddleLocation(addIndex)
switchUIState(true)
} else {
ToastUtils.showShort("最多可增加${MAX_MIDDLE_NUM}个途经点")
}
}
binding.rlMoreAdd.setOnClickListener {
binding.ivAddLocation.performClick()
}
binding.llStartLocation.ivDelEdit.setOnClickListener {
if (locationList.size > 2 &&
locationList[1].locationType == EditLocation.TYPE_MIDDLE
) {
startLocation.poi = locationList[1].poi
removeMiddleLocation(0)
} else {
startLocation.poi = null
}
updateLocationUI(startLocation)
}
binding.llEndLocation.ivDelEdit.setOnClickListener {
val index = locationList.size - 2
if (locationList.size > 2 &&
locationList[index].locationType == EditLocation.TYPE_MIDDLE
) {
endLocation.poi = locationList[index].poi
val middleIndex = getMiddleCount() - 1
removeMiddleLocation(middleIndex)
} else {
endLocation.poi = null
}
updateLocationUI(endLocation)
}
binding.ivBackFinish.setOnClickListener { v ->
onEventListener?.onCloseClick(v)
}
binding.ivLocationChangeMore.setOnClickListener {
binding.ivSwitchLocation.performClick();
}
binding.ivSwitchLocation.setOnClickListener { v ->
val temp = startLocation.poi
val tempEditContent = startLocation.editContent
startLocation.poi = endLocation.poi
startLocation.editContent = endLocation.editContent
endLocation.poi = temp
endLocation.editContent = tempEditContent
updateLocationUI(startLocation)
updateLocationUI(endLocation)
val start = 1;
val end = locationList.lastIndex - 1
//途经点交流次数
val switchCount = locationList.size / 2 - 1
for (i in 0 until switchCount) {
val index = start + i;
val switchIndex = end - i;
if (switchIndex != index && switchIndex >= 0) {
val temp = locationList.getOrNull(index)?.poi
locationList.getOrNull(index)?.poi = locationList.getOrNull(switchIndex)?.poi
locationList.getOrNull(switchIndex)?.poi = temp;
locationList.getOrNull(index)?.let {
updateLocationUI(it, findMidLocationTextView(index))
}
locationList.getOrNull(switchIndex)?.let {
updateLocationUI(it, findMidLocationTextView(switchIndex))
}
}
}
findFirstNoneEditTextView()?.let {
if (!it.text.isNullOrEmpty()) {
callOnTextChanged(it, it.text)
}
requestFocus(it, true)
}
}
binding.btnEditLocationComplete.setOnClickListener {
val dataList = ArrayList<EditLocation>()
for (item in locationList) {
if (item.poi != null) {
dataList.add(item)
}
}
if (startLocation.poi == null && !startLocation.editContent.isNullOrEmpty()) {
ToastUtils.showShort("请挑选起点")
requestFocus(binding.llStartLocation.edtInputKey)
return@setOnClickListener
}
if (endLocation.poi == null && !endLocation.editContent.isNullOrEmpty()) {
ToastUtils.showShort("请挑选结尾")
requestFocus(binding.llEndLocation.edtInputKey)
return@setOnClickListener
}
if (dataList.size < 2) {
if (startLocation?.poi == null) {
ToastUtils.showShort("请挑选起点")
requestFocus(binding.llStartLocation.edtInputKey)
} else if (endLocation?.poi == null) {
ToastUtils.showShort("请挑选结尾")
requestFocus(binding.llEndLocation.edtInputKey)
}
return@setOnClickListener
}
if (getMiddleCount() + 2 != dataList.size) {
for (i in 0 until getMiddleCount()) {
val editInText = !findMidLocationTextView(i + 1)?.text.isNullOrEmpty()
val poiNoSelected = locationList.getOrNull(i + 1)?.poi == null
if (editInText && poiNoSelected) {
ToastUtils.showShort("请挑选第${i + 1}个途经点")
return@setOnClickListener
}
}
}
val resultList = ArrayList<EditLocation>()
var latestData: EditLocation? = null
for (data in dataList) {
if (data.poi?.poiName != latestData?.poi?.poiName ||
data.poi?.poiType != latestData?.poi?.poiType
) {
resultList.add(data)
}
latestData = data
}
if (resultList.size == 2) {
if (isSamePOI(resultList[0].poi, resultList[1].poi)) {
ToastUtils.showShort("起点与结尾不能相同")
return@setOnClickListener
}
} else if (resultList.size < 2) {
ToastUtils.showShort("起点与结尾不能相同")
return@setOnClickListener
}
hideSoftInput()
onEventListener?.onLocationEditComplete(resultList)
}
}
/**
* 获取途经点个数
*/
protected fun getMiddleCount(): Int {
val allCount = binding.llMoreEditLine.childCount - 2
if (allCount >= 0) {
return allCount;
}
return 0;
}
private fun isSamePOI(poi1: SearchPOI?, poi2: SearchPOI?): Boolean {
return poi1 == poi2 || poi1?.poiName == poi2?.poiName ||
(poi1?.poiType == POIType.userPosition && POIType.userPosition == poi2?.poiType)
|| (poi1?.poiType == POIType.carPosition && POIType.carPosition == poi2?.poiType)
}
private fun requestFocus(view: TextView, isSelectedText: Boolean = false) {
post {
view.requestFocus()
if (view is EditText && isSelectedText) {
val length = view.text.length;
(view as EditText).setSelection(0, length)
KeyboardUtils.showSoftInput(view)
}
}
}
fun setLocationList(list: List<EditLocation>) {
list.getOrNull(0)?.let {
startLocation.poi = it.poi
updateLocationUI(startLocation)
}
list.getOrNull(list.lastIndex)?.let {
endLocation.poi = it.poi
updateLocationUI(endLocation)
}
locationList.clear()
locationList.add(startLocation)
locationList.add(endLocation)
removeAllMiddleView()
switchUIState(list.size > 2)
for (i in 1 until list.lastIndex) {
val v = addMiddleLocation(i - 1)
val item = list[i]
locationList[i].poi = item.poi
updateLocationUI(locationList[i], v)
}
}
private fun removeAllMiddleView() {
var hasCount = binding.llMoreEditLine.childCount
while (hasCount > 2) {
val index = hasCount - 1 - 1;
binding.llMoreEditLine.getChildAt(index)?.let { v ->
binding.llMoreEditLine.removeView(v)
}
hasCount = binding.llMoreEditLine.childCount
}
}
fun setIndexFocus(focusIndex: Int) {
locationList.getOrNull(focusIndex)?.let {
if (it.locationType == EditLocation.TYPE_START) {
requestFocus(binding.llStartLocation.edtInputKey, true)
} else if (it.locationType == EditLocation.TYPE_END) {
requestFocus(binding.llEndLocation.edtInputKey, true)
} else {
getMiddleItemViewAt(focusIndex - 1)
?.findViewById<EditText>(R.id.edt_input_key)
?.let { v ->
requestFocus(v, true)
}
}
}
}
/**
* @param middleIndex 从0开端,扫除起点和结尾之外的列表
*/
protected fun getMiddleItemViewAt(middleIndex: Int): View? {
return binding.llMoreEditLine.getChildAt(middleIndex + 1)
}
fun showSoftInput() {
if (context is Activity) {
KeyboardUtils.showSoftInput(context as Activity)
} else {
KeyboardUtils.showSoftInput();
}
}
fun showSoftInput(editText: View) {
KeyboardUtils.showSoftInput(editText)
}
fun hideSoftInput() {
if (context is Activity) {
KeyboardUtils.hideSoftInput(context as Activity)
} else {
KeyboardUtils.hideSoftInput(this)
}
}
/**
* 设置POI ; 有光标时就填充对应的项;没有光标时优先填充未填写项,顺序:结尾、起点、途经点
*/
fun setPoi(poi: SearchPOI) {
val v = findFocusEditTextView()
if (v != null) {
val tagData = v.getTag(R.id.cb_item_tag)
if (tagData is EditLocation) {
tagData.poi = poi
updateLocationUI(tagData, v)
}
} else if (endLocation.poi == null) {
endLocation.poi = poi
updateLocationUI(endLocation)
} else if (startLocation.poi == null) {
startLocation.poi = poi
updateLocationUI(startLocation)
} else {
val index = findNonePoiMiddleLocation()
if (index <= 0) {
endLocation.poi = poi
updateLocationUI(endLocation)
} else {
locationList[index].poi = poi
getMiddleItemViewAt(index - 1)
?.findViewById<EditText>(R.id.edt_input_key)
?.let { v ->
updateLocationUI(locationList[index], v)
}
}
}
//光标自动聚焦到下一个空的输入框
findFirstNoneEditTextView()?.let {
requestFocus(it)
callOnTextChanged(it, it.text)
} ?: let {
callOnTextChanged(null, "")
hideSoftInput()
}
//无途经点
if (getMiddleCount() <= 0) {
if (startLocation.poi != null && endLocation.poi != null) {
if (isSamePOI(startLocation.poi, endLocation.poi)) {
ToastUtils.showShort("起点与结尾不能相同")
} else {
val resultList = ArrayList<EditLocation>();
resultList.add(startLocation)
resultList.add(endLocation)
hideSoftInput()
onEventListener?.onLocationEditComplete(resultList)
}
}
}
}
private fun setUpEditViewKeyboard(editText: EditText?) {
editText?.imeOptions = EditorInfo.IME_ACTION_SEARCH
editText?.setOnEditorActionListener { v, actionId, event ->
val isClick = event?.keyCode == KeyEvent.KEYCODE_ENTER;
if (actionId == EditorInfo.IME_ACTION_SEARCH || isClick) {
onEventListener?.onEditTextChange(v as? EditText, v.text)
return@setOnEditorActionListener true;
}
return@setOnEditorActionListener false;
}
editText?.isLongClickable = false;
editText?.setOnFocusChangeListener { v, hasFocus ->
if (hasFocus) {
(v as? EditText)?.let { edit ->
edit.postDelayed({
edit.setSelection(0, edit.text?.length ?: 0)
}, 100);
}
}
}
editText?.setOnClickListener { v ->
(v as? EditText)?.let { edit ->
edit.setSelection(0, edit.text?.length ?: 0)
}
}
}
private fun findNonePoiMiddleLocation(): Int {
for (index in 1..locationList.size - 2) {
val item = locationList[index]
if (item.poi == null) {
return index
}
}
return -1;
}
private fun findFirstNoneEditTextView(): EditText? {
if (startLocation.poi == null) {
return binding.llStartLocation.edtInputKey
}
if (endLocation.poi == null) {
return binding.llEndLocation.edtInputKey
}
for (i in 0 until getMiddleCount()) {
val itemView = getMiddleItemViewAt(i)
val editText = itemView?.findViewById<EditText>(R.id.edt_input_key)
if (editText != null && (editText.getTag(R.id.cb_item_tag) as? EditLocation)?.poi == null) {
return editText
}
}
return null
}
private fun findFocusEditTextView(): EditText? {
if (binding.llStartLocation.edtInputKey.hasFocus()) {
return binding.llStartLocation.edtInputKey
}
if (binding.llEndLocation.edtInputKey.hasFocus()) {
return binding.llEndLocation.edtInputKey
}
for (i in 0 until getMiddleCount()) {
val itemView = getMiddleItemViewAt(i)
val editText = itemView?.findViewById<EditText>(R.id.edt_input_key)
if (editText != null && editText.hasFocus()) {
return editText
}
}
return null
}
private fun findMidLocationTextView(index: Int): EditText? {
val middleIndex = index - 1;
val itemView = getMiddleItemViewAt(middleIndex)
return itemView?.findViewById<EditText>(R.id.edt_input_key)
}
protected fun findLocationTextView(index: Int): EditText? {
val itemView = binding.llMoreEditLine.getChildAt(index)
return itemView?.findViewById<EditText>(R.id.edt_input_key)
}
protected fun updateLocationUI(location: EditLocation, textView: TextView? = null) {
var addressName: String = location.poi?.poiName ?: ""
if (location.poi?.poiType == POIType.userPosition) {
addressName = "我的方位"
} else if (location.poi?.poiType == POIType.carPosition) {
addressName = "车辆方位"
}
var editView: TextView? = null
if (location.locationType == EditLocation.TYPE_START) {
editView = binding.llStartLocation.edtInputKey;
} else if (location.locationType == EditLocation.TYPE_END) {
editView = binding.llEndLocation.edtInputKey
} else {
editView = textView
}
if (editView != null && !addressName.isNullOrEmpty()) {
textChangeIgnoreTask = TextChangeIgnore(editView, addressName)
}
val showText = addressName.ifEmpty { (location.editContent ?: "") }
editView?.text = showText
editView?.text?.length?.let { l ->
(editView as? EditText)?.setSelection(l)
}
}
private fun setViewMargin(v: View, left: Int, top: Int, right: Int, bottom: Int) {
v.layoutParams?.let {
val p = it as MarginLayoutParams
if (p.leftMargin != left ||
p.topMargin != top ||
p.rightMargin != right ||
p.bottomMargin != bottom
) {
p.setMargins(left, top, right, bottom)
v.layoutParams = p
}
}
}
private fun switchUIState(isHasMiddleLocation: Boolean, middleCount: Int = 1) {
if (isHasMiddleLocation) {
binding.rlEditLocationContainer.setBackgroundResource(R.drawable.bg_transparent)
binding.llStartLocation.llEditContent.setBackgroundResource(R.drawable.bg_edit_box)
binding.llEndLocation.llEditContent.setBackgroundResource(R.drawable.bg_edit_box)
binding.llStartLocation.ivDelEdit.visibility =
if (middleCount == 0) View.GONE else View.VISIBLE
binding.llEndLocation.ivDelEdit.visibility =
if (middleCount == 0) View.GONE else View.VISIBLE
binding.llEditAction.visibility = View.GONE
binding.llStartLocation.ivEditMoveTag.visibility = View.VISIBLE
binding.llEndLocation.ivEditMoveTag.visibility = View.VISIBLE
binding.ivLocationChangeMore.visibility = View.VISIBLE
binding.rlMoreAddLocation.visibility = View.VISIBLE
binding.twoLineSplit.visibility = View.GONE
setViewMargin(
binding.llEndLocation.root, 0, resources.getDimensionPixelSize(R.dimen.dp_6),
0, 0
)
} else {
binding.rlEditLocationContainer.setBackgroundResource(R.drawable.bg_edit_box)
binding.llStartLocation.llEditContent.setBackgroundResource(R.drawable.bg_transparent)
binding.llEndLocation.llEditContent.setBackgroundResource(R.drawable.bg_transparent)
binding.llStartLocation.ivDelEdit.visibility = View.GONE
binding.llEndLocation.ivDelEdit.visibility = View.GONE
binding.llStartLocation.ivEditMoveTag.visibility = View.GONE
binding.llEndLocation.ivEditMoveTag.visibility = View.GONE
binding.llEditAction.visibility = View.VISIBLE
binding.ivLocationChangeMore.visibility = View.GONE
binding.rlMoreAddLocation.visibility = View.GONE
removeAllMiddleView()
binding.twoLineSplit.visibility = View.VISIBLE
setViewMargin(
binding.llEndLocation.root, 0, 0,
0, 0
)
}
}
/**
* @param middleIndex 从0开端,扫除起点和结尾之外的列表
*/
private fun addMiddleLocation(middleIndex: Int = 0): EditText {
val params = LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
val top: Int = resources.getDimensionPixelSize(R.dimen.dp_6)
val bottom = 0
params.topMargin = top
params.bottomMargin = bottom
val middleViewBinding = createMiddleLocationEditView();
var middlePos: Int = middleIndex
if (getMiddleCount() > middleIndex) {
binding.llMoreEditLine.addView(middleViewBinding.root, middleIndex + 1, params)
} else {
val index = binding.llMoreEditLine.childCount - 1;
binding.llMoreEditLine.addView(middleViewBinding.root, index, params)
middlePos = getMiddleCount() - 1;
}
val middleData = EditLocation.createMiddleLocation()
middleViewBinding.root.setTag(R.id.cb_item_tag, middleData)
middleViewBinding.edtInputKey.setTag(R.id.cb_item_tag, middleData)
locationList.add(middlePos + 1, middleData)
updateAddMoreUIState()
post {
middleViewBinding.edtInputKey.requestFocus()
}
return middleViewBinding.edtInputKey
}
private fun updateAddMoreUIState() {
val couldAddSize = MAX_MIDDLE_NUM - getMiddleCount()
binding.tvAddNum.text = if (couldAddSize <= 0) "已到达上限" else "还可增加${couldAddSize}个"
if (couldAddSize <= 0) {
binding.rlMoreAdd.tag = false
setViewColorFilter(binding.rlMoreAdd, 0.5f)
} else {
binding.rlMoreAdd.tag = true;
setViewColorFilter(binding.rlMoreAdd, 1f)
}
}
private fun setViewColorFilter(view: View, alphaScale: Float) {
val paint = Paint()
val cm = ColorMatrix()
cm.setScale(1f, 1f, 1f, alphaScale)
paint.colorFilter = ColorMatrixColorFilter(cm)
view.setLayerType(View.LAYER_TYPE_HARDWARE, paint)
}
/**
* @param middleIndex 从0开端,扫除起点和结尾之外的列表
*/
private fun removeMiddleLocation(middleIndex: Int) {
getMiddleItemViewAt(middleIndex)?.let { child ->
binding.llMoreEditLine.removeView(child)
(child.getTag(R.id.cb_item_tag) as? EditLocation).let { data ->
locationList.remove(data)
}
}
/*val index = middleIndex + 1
val location = locationList.getOrNull(index)
if (location != null && location.locationType == EditLocation.TYPE_MIDDLE) {
locationList.removeAt(index)
}*/
val count = getMiddleCount()
switchUIState(true, count)
updateAddMoreUIState()
}
private fun createMiddleLocationEditView(): EditSearchKeyBinding {
val tempBinding = EditSearchKeyBinding.inflate(LayoutInflater.from(context))
val itemView: View = tempBinding.root
tempBinding.ivEdt.setImageResource(R.drawable.middle_location_point)
tempBinding.llEditContent.setBackgroundResource(R.drawable.bg_edit_box)
tempBinding.edtInputKey.setText("")
tempBinding.edtInputKey.hint = "请输入途经点"
setUpEditViewKeyboard(tempBinding.edtInputKey)
val middleWatcher = EditTextWatcher(this, tempBinding.edtInputKey)
tempBinding.edtInputKey.addTextChangedListener(middleWatcher)
tempBinding.ivEditMoveTag.visibility = View.VISIBLE
tempBinding.ivDelEdit.visibility = View.VISIBLE
tempBinding.ivDelEdit.setTag(itemView)
tempBinding.ivDelEdit.setOnClickListener { v ->
if (v.tag != null && v.tag is View) {
val index = binding.llMoreEditLine.indexOfChild(v.tag as View) - 1
removeMiddleLocation(index)
}
}
return tempBinding
}
private fun callOnTextChanged(editText: EditText?, text: CharSequence?) {
if (textChangeIgnoreTask?.isIgnore(editText, text?.toString() ?: "") != true) {
(editText?.getTag(R.id.cb_item_tag) as? EditLocation)?.let {
it.editContent = text?.toString();
it.poi = null;
}
onEventListener?.onEditTextChange(editText, text)
}
textChangeIgnoreTask = null
}
interface OnEventListener {
fun onEditTextChange(editText: EditText?, text: CharSequence?)
fun onCloseClick(v: View)
fun onLocationEditComplete(locationList: List<EditLocation>)
}
class TextChangeIgnore(val tagView: View, val ignoreText: String) {
fun isIgnore(changeView: View?, changeText: String): Boolean {
return tagView == changeView && changeText == ignoreText;
}
}
class EditTextWatcher(val v: EditTripLocationListView, val editText: EditText) : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
var inputText = s?.toString() ?: ""
if (inputText.length > 200) {
inputText = inputText.substring(0, 200)
editText.setText(inputText)
val selection = editText.text.length
editText.setSelection(selection)
}
v.callOnTextChanged(editText, inputText)
}
}
}
class EditLocation {
companion object {
const val TYPE_START = 0;
const val TYPE_MIDDLE = 1;
const val TYPE_END = 2;
fun createStartLocation(context: Context): EditLocation {
val location = EditLocation()
location.locationType = TYPE_START
val userPoi = SearchPOI()
userPoi.poiType = POIType.userPosition;
location.poi = userPoi;
return location
}
fun createMiddleLocation(): EditLocation {
val location = EditLocation()
location.locationType = TYPE_MIDDLE
return location
}
fun createEndLocation(): EditLocation {
val location = EditLocation()
location.locationType = TYPE_END
return location
}
}
var locationType: Int = TYPE_START
var poi: SearchPOI? = null
/**
* 修改的文字
*/
var editContent: String? = null;
}
终究的作用: