Merge branch 'master' into 'release_robotaxi-d-app-module_2110_220915_2.11.0.1'

# Conflicts:
#   app_ipc_monitoring/src/main/java/com/zhidao/adas/client/ui/MainActivity.java
#   core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/adapter/MoGoHandAdasMsgManager.java
This commit is contained in:
pangfan
2022-10-31 03:08:24 +00:00
255 changed files with 10443 additions and 8 deletions

View File

@@ -5,9 +5,11 @@ import android.app.Application;
import com.zhidao.adas.client.utils.CrashHandler;
public class App extends Application {
public static App INSTANCE;
@Override
public void onCreate() {
super.onCreate();
INSTANCE = this;
CrashHandler.getInstance().init(this);
}
}

View File

@@ -0,0 +1,60 @@
package com.zhidao.adas.client.adapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.zhidao.adas.client.R;
import com.zhidao.adas.client.base.BaseAdapter;
import com.zhidao.adas.client.base.BaseViewHolder;
import com.zhidao.adas.client.bean.SpecialVehicleBean;
import java.util.List;
/**
* @author song kenan
* @des 线路
* @date 2021/8/13
*/
public class SpecialVehicleAdapter extends BaseAdapter<SpecialVehicleBean, SpecialVehicleAdapter.ViewHolder> {
public SpecialVehicleAdapter(List<SpecialVehicleBean> data) {
super(data);
}
@Override
public void setData(List<SpecialVehicleBean> mDatas) {
super.setData(mDatas);
}
@Override
protected void onBindDataToItem(ViewHolder viewHolder, SpecialVehicleBean data, int position) {
viewHolder.title.setText(data.name);
}
@Override
protected View getItemViewResource(ViewGroup viewGroup) {
return LayoutInflater.from(mContext).inflate(R.layout.item_info, viewGroup, false);
}
@Override
protected ViewHolder getViewHolder(View view) {
return new ViewHolder(view, this);
}
class ViewHolder extends BaseViewHolder<SpecialVehicleAdapter> {
TextView title;
public ViewHolder(View itemView, SpecialVehicleAdapter adapter) {
super(itemView, adapter);
// ViewGroup.LayoutParams layoutParams = itemView.getLayoutParams();
// if (layoutParams != null) {
// layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
//
// }
title = itemView.findViewById(R.id.tv_info_title);
}
}
}

View File

@@ -0,0 +1,230 @@
package com.zhidao.adas.client.bean;
import android.content.Context;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import com.google.protobuf.TextFormat;
import com.zhidao.adas.client.ui.special.SpecialVehicleFloatWindowManager;
import com.zhidao.adas.client.utils.PreferencesUtils;
import com.zhidao.support.adas.high.AdasManager;
import java.util.ArrayList;
import java.util.List;
import chassis.SpecialVehicleTaskCmdOuterClass;
public class SpecialVehicleBean {
private interface TAG {
String FTQSC = "ftqsc";//福田清扫车
String KWXB = "kwxb";//开沃小巴
}
public interface SEND_TYPE {
int ONE = 0;//单次发送
int MORE = 1;//多次发送
int ALL = 2;//两种方式都支持
}
public final String name;
public final String simpleName;//简单名字 两个字
public final List<SpecialVehicleOption> options;
private final String tag;//用于存储
public int sendType = SEND_TYPE.ONE;//发送类型
private SpecialVehicleFloatWindowManager manager;
public static final int SCREEN_MARGIN = 20;
private final String FLOAT_WINDOW_LOCATION_MIN_X;
private final String FLOAT_WINDOW_LOCATION_MIN_Y;
private final String FLOAT_WINDOW_LOCATION_MAX_X;
private final String FLOAT_WINDOW_LOCATION_MAX_Y;
private SpecialVehicleBean(@NonNull String name, @NonNull String simpleName, String tag, List<SpecialVehicleOption> options) {
this.name = name;
this.simpleName = simpleName;
this.tag = tag;
this.options = options;
FLOAT_WINDOW_LOCATION_MIN_X = tag + "_float_window_location_min_x";
FLOAT_WINDOW_LOCATION_MIN_Y = tag + "_float_window_location_min_y";
FLOAT_WINDOW_LOCATION_MAX_X = tag + "_float_window_location_max_X";
FLOAT_WINDOW_LOCATION_MAX_Y = tag + "_float_window_location_max_y";
}
public void showFloat(Context context) {
if (manager == null)
manager = new SpecialVehicleFloatWindowManager(context, this);
manager.show();
}
public void dismissFloat() {
if (manager != null) {
manager.onBack();
manager = null;
}
}
/************************悬浮窗位置******************/
public void setFloatWindowLocationMinX(Context context, int x) {
PreferencesUtils.putInt(context, FLOAT_WINDOW_LOCATION_MIN_X, x);
}
public int getFloatWindowLocationMinX(Context context) {
return PreferencesUtils.getInt(context, FLOAT_WINDOW_LOCATION_MIN_X, SCREEN_MARGIN);
}
public void setFloatWindowLocationMinY(Context context, int y) {
PreferencesUtils.putInt(context, FLOAT_WINDOW_LOCATION_MIN_Y, y);
}
public int getFloatWindowLocationMinY(Context context) {
return PreferencesUtils.getInt(context, FLOAT_WINDOW_LOCATION_MIN_Y, SCREEN_MARGIN);
}
/************************悬浮窗位置******************/
public void setFloatWindowLocationMaxX(Context context, int x) {
PreferencesUtils.putInt(context, FLOAT_WINDOW_LOCATION_MAX_X, x);
}
public int getFloatWindowLocationMaxX(Context context) {
return PreferencesUtils.getInt(context, FLOAT_WINDOW_LOCATION_MAX_X, SCREEN_MARGIN);
}
public void setFloatWindowLocationMaxY(Context context, int y) {
PreferencesUtils.putInt(context, FLOAT_WINDOW_LOCATION_MAX_Y, y);
}
public int getFloatWindowLocationMaxY(Context context) {
return PreferencesUtils.getInt(context, FLOAT_WINDOW_LOCATION_MAX_Y, SCREEN_MARGIN);
}
/**
* 命令下发
*
* @param index -1一次性发送所有命令 其他 单个命令发送
* @return
*/
public String sendCmd(int index) {
String str = "";
if (TextUtils.equals(this.tag, TAG.FTQSC)) { //福田清扫车
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.newBuilder();
if (index < 0) {
for (index = 0; index < options.size(); index++) {
SpecialVehicleOption option = options.get(index);
if (option.moreCheckPos != -1) {
option.checkPos = option.moreCheckPos;
option.moreCheckPos = -1;
}
setFuTianCleanValue(builder, index, option.checkPos);
}
} else {
int checkPos = options.get(index).checkPos;
setFuTianCleanValue(builder, index, checkPos);
}
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd fuTianCleanCmd = builder.build();
SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd fuTianTaskCmd = SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianTaskCmd.newBuilder()
.setRoboSweeperFutianCleanCmd(fuTianCleanCmd).build();
AdasManager.getInstance().sendRoboSweeperFuTianTaskCmd(fuTianTaskCmd);
str = TextFormat.printer().escapingNonAscii(false).printToString(fuTianTaskCmd).replaceAll("\n", "");
} else if (TextUtils.equals(this.tag, TAG.KWXB)) { //开沃小巴
SpecialVehicleTaskCmdOuterClass.RoboVanSkywellTaskCmd vanSkywellTaskCmd = SpecialVehicleTaskCmdOuterClass.RoboVanSkywellTaskCmd.newBuilder()
.build();
AdasManager.getInstance().sendRoboVanSkywellTaskCmd(vanSkywellTaskCmd);
}
return str;
}
private void setFuTianCleanValue(SpecialVehicleTaskCmdOuterClass.RoboSweeperFuTianCleanCmd.Builder builder, int index, int checkPos) {
switch (index) {
case 0:
builder.setCleanOpenRequirement(checkPos);
break;
case 1:
builder.setCleanModeRequirement(checkPos);
break;
case 2:
builder.setCleanDirectionRequirement(checkPos);
break;
case 3:
builder.setCleanIntensityRequirement(checkPos);
break;
case 4:
builder.setDuskCloseRequirement(checkPos);
break;
case 5:
builder.setSuctionNozzlefleOpenRequirement(checkPos);
break;
case 6:
builder.setSprayGunOpenRequirement(checkPos);
break;
case 7:
builder.setSweepdiskSpeedRequirement(checkPos);
break;
}
}
public static List<SpecialVehicleBean> init() {
List<SpecialVehicleBean> list = new ArrayList<>();
List<SpecialVehicleOption> optionsF = new ArrayList<>();
int tag = 0;
String[] value = new String[3];
value[0] = "0-No Req";
value[1] = "1-Start";
value[2] = "2-Stop";
optionsF.add(new SpecialVehicleOption("清扫作业", tag++, value, 0));
value = new String[6];
value[0] = "0-No Req";
value[1] = "1-Sweeping";
value[2] = "2-Wash Sweeper";
value[3] = "3-Pure Wash";
value[4] = "4-Pure Draw";
value[5] = "5-Close Clean";
optionsF.add(new SpecialVehicleOption("清扫模式", tag++, value, 0));
value = new String[5];
value[0] = "0-No Req";
value[1] = "1-Both";
value[2] = "2-Left";
value[3] = "3-Right";
value[4] = "4-Close Side";
optionsF.add(new SpecialVehicleOption("清扫方向", tag++, value, 0));
value = new String[3];
value[0] = "0-No Req";
value[1] = "1-Stand";
value[2] = "2-Strong";
optionsF.add(new SpecialVehicleOption("作业强度", tag++, value, 0));
value = new String[3];
value[0] = "0-No Req";
value[1] = "1-Close";
value[2] = "2-Open";
optionsF.add(new SpecialVehicleOption("降尘", tag++, value, 0));
value = new String[3];
value[0] = "0-No Req";
value[1] = "1-Open";
value[2] = "2-Close";
optionsF.add(new SpecialVehicleOption("吸嘴挡板", tag++, value, 0));
value = new String[3];
value[0] = "0-No Req";
value[1] = "1-Open";
value[2] = "2-Close";
optionsF.add(new SpecialVehicleOption("喷雾枪", tag++, value, 0));
value = new String[3];
value[0] = "0-No Req";
value[1] = "1-Decelerate";
value[2] = "2-Accelerate";
optionsF.add(new SpecialVehicleOption("扫盘加速", tag, value, 0));
SpecialVehicleBean beanF = new SpecialVehicleBean("福田清扫车", "福清", TAG.FTQSC, optionsF);
SpecialVehicleBean beanK = new SpecialVehicleBean("开沃小巴", "开巴", TAG.KWXB, null);
list.add(beanF);
list.add(beanK);
return list;
}
}

View File

@@ -0,0 +1,16 @@
package com.zhidao.adas.client.bean;
public class SpecialVehicleOption {
public final String name;
public final int tag;
public final String[] value;
public int checkPos = 0;//选中的下标
public int moreCheckPos = -1;//发送模式下多条模式时选中的下标
public SpecialVehicleOption(String name, int tag, String[] value, int checkPos) {
this.name = name;
this.tag = tag;
this.value = value;
this.checkPos = checkPos;
}
}

View File

@@ -70,6 +70,7 @@ import com.zhidao.adas.client.bean.PlanningObjects;
import com.zhidao.adas.client.bean.PredictionObstacleTrajectory;
import com.zhidao.adas.client.bean.RecordDataConfig;
import com.zhidao.adas.client.bean.RecordPanel;
import com.zhidao.adas.client.bean.SpecialVehicleBean;
import com.zhidao.adas.client.bean.StatusInfo;
import com.zhidao.adas.client.bean.TrackedObjects;
import com.zhidao.adas.client.bean.Trajectory;
@@ -77,6 +78,7 @@ import com.zhidao.adas.client.bean.VehicleState;
import com.zhidao.adas.client.bean.Warn;
import com.zhidao.adas.client.log.ConnectStatusSave;
import com.zhidao.adas.client.log.LogSave;
import com.zhidao.adas.client.ui.special.SpecialVehicleDialog;
import com.zhidao.adas.client.utils.Constants;
import com.zhidao.adas.client.utils.PreferencesUtils;
import com.zhidao.support.adas.high.AdasManager;
@@ -159,11 +161,13 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas
private String recordFileName;
private int connectStatus;
private AutoPilotModeDialog autoPilotModeDialog;
private SpecialVehicleDialog specialVehicleDialog;
private ListPopupWindow listPopupWindow;
private FloatWindow floatWindow;
private View include_title;
private boolean isAutopilotAbility = true;
private String autopilotAbilityReason;
private List<SpecialVehicleBean> specialVehicleBeanList;//特种车辆
// @Override
// protected void onStart() {
// super.onStart();
@@ -253,6 +257,14 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas
wakeLock.release();
if (wifiLock != null)
wifiLock.release();
if (autoPilotModeDialog != null && autoPilotModeDialog.isShowing()) {
autoPilotModeDialog.dismiss();
autoPilotModeDialog = null;
}
if (specialVehicleDialog != null && specialVehicleDialog.isShowing()) {
specialVehicleDialog.dismiss();
specialVehicleDialog = null;
}
}
private void canDrawOverlays() {
@@ -633,6 +645,7 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas
titleBtnData.add(Constants.TITLE.SEND_SET_AUTOPILOT_MODE_REQ);
titleBtnData.add(Constants.TITLE.SEND_GLOBAL_PATH_REQ);
titleBtnData.add(Constants.TITLE.SEND_SPECIAL_VEHICLE_TASK_CMD);
titleBtnData.add(Constants.TITLE.SEND_STATUS_QUERY_REQ);
titleBtnData.add(Constants.TITLE.SEND_BASIC_INFO_RESP);
titleBtnData.add(Constants.TITLE.SEND_RECORD_DATA_CONFIG_RESP);
@@ -1109,6 +1122,7 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas
} else if (connectStatus == IPC_CONNECTION_STATUS.DISCONNECTED) {
getHandler().sendEmptyMessage(WHAT_IPC_IP);
}
// LogSave.getInstance().saveLog("连接状态", status);
// CupidLogUtils.i(TAG, "connectStatus=" + status);
}
@@ -1210,6 +1224,17 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas
//自动驾驶路径查询
AdasManager.getInstance().sendGlobalPathReq();
break;
case Constants.TITLE.SEND_SPECIAL_VEHICLE_TASK_CMD:
if (specialVehicleBeanList == null) {
specialVehicleBeanList = SpecialVehicleBean.init();
}
if (specialVehicleDialog == null) {
specialVehicleDialog = new SpecialVehicleDialog(this, specialVehicleBeanList);
}
if (!specialVehicleDialog.isShowing()) {
specialVehicleDialog.show();
}
break;
case Constants.TITLE.SEND_STATUS_QUERY_REQ:
AdasManager.getInstance().sendStatusQueryReq();
break;
@@ -1358,6 +1383,12 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas
switch (msg.what) {
case WHAT_IPC_IP:
showIPCIP();
if (specialVehicleBeanList != null && !specialVehicleBeanList.isEmpty()) {
for (SpecialVehicleBean bean : specialVehicleBeanList) {
bean.dismissFloat();
}
specialVehicleBeanList = null;
}
break;
case WHAT_DRIVER_IP:
ipcIp.setVisibility(View.VISIBLE);

View File

@@ -0,0 +1,116 @@
package com.zhidao.adas.client.ui.special;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator;
import com.zhidao.adas.client.App;
import com.zhidao.adas.client.R;
import com.zhidao.adas.client.adapter.SpecialVehicleAdapter;
import com.zhidao.adas.client.base.BaseAdapter;
import com.zhidao.adas.client.bean.SpecialVehicleBean;
import com.zhidao.adas.client.ui.AutopilotConfigActivity;
import java.util.List;
/**
* 特种车辆
*/
public class SpecialVehicleDialog extends Dialog {
private RecyclerView recyclerView;
private List<SpecialVehicleBean> list;
public SpecialVehicleDialog(@NonNull Context context, List<SpecialVehicleBean> list) {
super(context, R.style.CustomDialog);
this.list = list;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_autopilot_mode);
//初始化界面控件
initView();
//初始化界面控件的事件
initListener();
initBtnRecyclerView();
setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
}
});
}
@Override
public void show() {
super.show();
}
private void initBtnRecyclerView() {
//初始info-recycle
LinearLayoutManager nodLinearLayoutManage = new LinearLayoutManager(getContext());
nodLinearLayoutManage.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(nodLinearLayoutManage);
//如果可以确定每个item的高度是固定的设置这个选项可以提高性能
recyclerView.setHasFixedSize(true);
//解决局部刷新闪屏问题
SimpleItemAnimator animatorInfo = (SimpleItemAnimator) recyclerView.getItemAnimator();
if (animatorInfo != null)
animatorInfo.setSupportsChangeAnimations(false);
//创建并设置Adapter
SpecialVehicleAdapter adapter = new SpecialVehicleAdapter(list);
recyclerView.setAdapter(adapter);
adapter.setOnItemClickListener(new BaseAdapter.OnItemClickListener<SpecialVehicleBean>() {
@Override
public void onItemClick(int position, SpecialVehicleBean data) {
if (data.options == null) {
Toast.makeText(getContext(), "" + data.name + "”暂未支持", Toast.LENGTH_SHORT).show();
} else {
data.showFloat(App.INSTANCE);
SpecialVehicleDialog.this.dismiss();
}
}
});
}
/**
* 初始化界面的确定和取消监听器
*/
private void initListener() {
findViewById(R.id.settings).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getContext().startActivity(new Intent(getContext(), AutopilotConfigActivity.class));
}
});
}
/**
* 初始化界面控件
*/
private void initView() {
recyclerView = findViewById(R.id.recyclerView);
findViewById(R.id.settings).setVisibility(View.GONE);
TextView textView = findViewById(R.id.title);
textView.setText("特种车辆");
}
}

View File

@@ -0,0 +1,477 @@
package com.zhidao.adas.client.ui.special;
import android.content.Context;
import android.graphics.Color;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatButton;
import com.zhidao.adas.client.R;
import com.zhidao.adas.client.bean.SpecialVehicleBean;
import com.zhidao.adas.client.bean.SpecialVehicleOption;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
/**
* 2017/1/10.
* Description全局悬浮窗口
*/
public class SpecialVehicleFloatWindow extends LinearLayout {
/*********************悬浮窗相关***********************/
private int sW;
private int sH;
private boolean isMaximize = true;//是否是最大化
private WindowManager wm;
//此wmParams变量为获取的全局变量用以保存悬浮窗口的属性
private WindowManager.LayoutParams wmParams;
private int btnMaximizeW;
private int btnMaximizeH;
/*********************CAN数据配置相关***********************/
private final static int WHAT_UPDATE_DATA = 1;
private BaseHandler mBaseHandler;
private LinearLayout layout_btn;
private HorizontalScrollView btn_list;
private AppCompatButton btn_send;
private RadioGroup rg_send_type;
private TextView text;
private TextView title;
private TextView btn_maximize;
private View can_parent;
private OnFloatWindowListener listener;
private final SpecialVehicleBean specialVehicleBean;
public interface OnFloatWindowListener {
void onBack();
void onMinimality();
void onMaximize();
}
public boolean isMaximize() {
return isMaximize;
}
public void setOnFloatWindowListener(OnFloatWindowListener listener) {
this.listener = listener;
}
public void setWmParams(WindowManager.LayoutParams wmParams) {
this.wmParams = wmParams;
}
public SpecialVehicleFloatWindow(@NonNull Context context, @NonNull SpecialVehicleBean specialVehicleBean) {
super(context, null, 0);
this.specialVehicleBean = specialVehicleBean;
wm = (WindowManager) context.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
//加载布局
LayoutInflater.from(context).inflate(R.layout.dialog_special_vehicle_config, this, true);
initParameter();
initCanView();
}
private void initParameter() {
DisplayMetrics metrics2 = getResources().getDisplayMetrics();
sW = metrics2.widthPixels;
sH = metrics2.heightPixels;
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
if (isMaximize) {
minimality();
return true;
}
}
}
return super.dispatchKeyEvent(event);
}
private float mInViewX;
private float mInViewY;
private float mDownInScreenX;
private float mDownInScreenY;
private float mInScreenX;
private float mInScreenY;
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 获取相对View的坐标即以此View左上角为原点
mInViewX = event.getX();
mInViewY = event.getY();
// 获取相对屏幕的坐标,即以屏幕左上角为原点
mDownInScreenX = event.getRawX();
mDownInScreenY = event.getRawY() - getSysBarHeight(getContext());
mInScreenX = event.getRawX();
mInScreenY = event.getRawY() - getSysBarHeight(getContext());
if (!isMaximize) {
btn_maximize.setPressed(true);
btnMaximizeW = btn_maximize.getWidth();
btnMaximizeH = btn_maximize.getHeight();
}
break;
case MotionEvent.ACTION_MOVE:
// 更新浮动窗口位置参数
mInScreenX = event.getRawX();
mInScreenY = event.getRawY() - getSysBarHeight(getContext());
wmParams.x = (int) (mInScreenX - mInViewX);
wmParams.y = (int) (mInScreenY - mInViewY);
updateViewLayout();
break;
case MotionEvent.ACTION_UP:
// 如果手指离开屏幕时xDownInScreen和xInScreen相等且yDownInScreen和yInScreen相等则视为触发了单击事件。
// if (mDownInScreenX == mInScreenX && mDownInScreenY == mInScreenY) {
float temX = Math.abs(mDownInScreenX - mInScreenX);
float temY = Math.abs(mDownInScreenY - mInScreenY);
if (temX + temY < 10) {
maximize();
} else {
if (isMaximize) {
specialVehicleBean.setFloatWindowLocationMaxX(getContext(), wmParams.x);
specialVehicleBean.setFloatWindowLocationMaxY(getContext(), wmParams.y);
} else {
btn_maximize.setPressed(false);
// 抬起手指时让floatView屏幕左右边缘 距离20个像素
// wmParams.x = wmParams.x <= (sW / 2) ? AmiConstants.SCREEN_MARGIN : sW - btnMaximizeW - AmiConstants.SCREEN_MARGIN;
int tem = wmParams.x;
if (tem < SpecialVehicleBean.SCREEN_MARGIN)
tem = SpecialVehicleBean.SCREEN_MARGIN;
else if (sW - (tem + btnMaximizeW) < SpecialVehicleBean.SCREEN_MARGIN) {
tem = sW - btnMaximizeW - SpecialVehicleBean.SCREEN_MARGIN;
}
wmParams.x = tem;
tem = wmParams.y;
if (tem < SpecialVehicleBean.SCREEN_MARGIN)
tem = SpecialVehicleBean.SCREEN_MARGIN;
else if (sH - (tem + btnMaximizeH) < SpecialVehicleBean.SCREEN_MARGIN) {
tem = sH - btnMaximizeH - SpecialVehicleBean.SCREEN_MARGIN;
}
wmParams.y = tem;
updateViewLayout();
specialVehicleBean.setFloatWindowLocationMinX(getContext(), wmParams.x);
specialVehicleBean.setFloatWindowLocationMinY(getContext(), wmParams.y);
}
}
break;
}
return true;
}
public void updateViewLayout() {
wm.updateViewLayout(this, wmParams);
}
// 获取系统状态栏高度
private int sbar = -1;
public int getSysBarHeight(Context contex) {
if (sbar == -1) {
Class<?> c;
Object obj;
Field field;
int x;
try {
c = Class.forName("com.android.internal.R$dimen");
obj = c.newInstance();
field = c.getField("status_bar_height");
x = Integer.parseInt(field.get(obj).toString());
sbar = contex.getResources().getDimensionPixelSize(x);
} catch (Exception e1) {
e1.printStackTrace();
}
}
return sbar;
}
/*****************************业务逻辑*******************************************/
private void initCanView() {
initHandler();
can_parent = findViewById(R.id.can_parent);
btn_list = findViewById(R.id.btn_list);
btn_send = findViewById(R.id.btn_send);
rg_send_type = findViewById(R.id.rg_send_type);
text = findViewById(R.id.text);
title = findViewById(R.id.title);
title.setText(specialVehicleBean.name);
btn_maximize = findViewById(R.id.btn_maximize);
btn_maximize.setText(specialVehicleBean.simpleName);
initListener();
initBtnRecyclerView();
initSendTypeView();
}
private void initSendTypeView() {
int resId;
switch (specialVehicleBean.sendType) {
default:
case SpecialVehicleBean.SEND_TYPE.ONE:
resId = R.id.btn_one;
break;
case SpecialVehicleBean.SEND_TYPE.MORE:
resId = R.id.btn_more;
break;
case SpecialVehicleBean.SEND_TYPE.ALL:
resId = R.id.btn_all;
break;
}
rg_send_type.check(resId);
btn_send.setVisibility(specialVehicleBean.sendType == SpecialVehicleBean.SEND_TYPE.ONE ? View.GONE : View.VISIBLE);
rg_send_type.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
View checkView = group.findViewById(checkedId);
if (!checkView.isPressed()) {
return;
}
int type = SpecialVehicleBean.SEND_TYPE.ONE;
if (checkedId == R.id.btn_more) {
type = SpecialVehicleBean.SEND_TYPE.MORE;
} else {
if (specialVehicleBean.sendType == SpecialVehicleBean.SEND_TYPE.MORE) {
for (int i = 0; i < layout_btn.getChildCount(); i++) {
LinearLayout view = (LinearLayout) layout_btn.getChildAt(i);
RadioGroup radioGroup = view.findViewById(R.id.item_group);
SpecialVehicleOption option = specialVehicleBean.options.get(i);
if (option.moreCheckPos != -1) {
option.moreCheckPos = -1;
radioGroup.check(option.checkPos);
}
}
}
if (checkedId == R.id.btn_one) {
type = SpecialVehicleBean.SEND_TYPE.ONE;
} else if (checkedId == R.id.btn_all) {
type = SpecialVehicleBean.SEND_TYPE.ALL;
}
}
specialVehicleBean.sendType = type;
btn_send.setVisibility(type == SpecialVehicleBean.SEND_TYPE.ONE ? View.GONE : View.VISIBLE);
}
});
btn_send.setOnClickListener(onClickListener);
}
private void initListener() {
findViewById(R.id.btn_back).setOnClickListener(onClickListener);
findViewById(R.id.btn_minimality).setOnClickListener(onClickListener);
}
public void minimality() {
isMaximize = false;
btn_maximize.setVisibility(VISIBLE);
can_parent.setVisibility(GONE);
if (listener != null) {
listener.onMinimality();
}
}
public void maximize() {
isMaximize = true;
if (listener != null) {
listener.onMaximize();
}
btn_maximize.setVisibility(GONE);
can_parent.setVisibility(VISIBLE);
}
private final OnClickListener onClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.btn_back) {
if (listener != null) {
listener.onBack();
}
} else if (id == R.id.btn_minimality) {
minimality();
} else if (id == R.id.btn_send) {
String cmd = specialVehicleBean.sendCmd(-1);
updateText(0, cmd);
}
}
};
private void initBtnRecyclerView() {
layout_btn = new LinearLayout(getContext());
btn_list.addView(layout_btn);
layout_btn.setOrientation(LinearLayout.HORIZONTAL);
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) layout_btn.getLayoutParams();
lp.gravity = Gravity.CENTER_VERTICAL;
for (int i = 0; i < specialVehicleBean.options.size(); i++) {
SpecialVehicleOption bean = specialVehicleBean.options.get(i);
View view = LayoutInflater.from(getContext()).inflate(R.layout.item_special_vehicle, layout_btn, false);
TextView name = view.findViewById(R.id.name);
RadioGroup radioGroup = view.findViewById(R.id.item_group);
name.setText(bean.name);
String[] value = bean.value;
for (int j = 0; j < value.length; j++) {
RadioButton button = LayoutInflater.from(getContext()).inflate(R.layout.item_special_vehicle_option_radio_btn, radioGroup, false)
.findViewById(R.id.r_btn);
button.setText(value[j]);
button.setId(j);
if (i == 1 || i == 2 || i == 3 || i == 4) {
ViewGroup.LayoutParams layoutParams = button.getLayoutParams();
layoutParams.width = 202;
}
radioGroup.addView(button);
}
radioGroup.setTag(bean.tag);
radioGroup.setOnCheckedChangeListener(onCheckedChangeListener);
radioGroup.check(bean.checkPos);
layout_btn.addView(view);
}
}
private final RadioGroup.OnCheckedChangeListener onCheckedChangeListener = new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
View checkView = group.findViewById(checkedId);
if (checkView == null || !checkView.isPressed()) {
return;
}
int tag = (int) group.getTag();
SpecialVehicleOption bean = specialVehicleBean.options.get(tag);
if (specialVehicleBean.sendType != SpecialVehicleBean.SEND_TYPE.MORE) {
bean.checkPos = checkedId;
String cmd = specialVehicleBean.sendCmd(tag);
updateText(0, cmd);
} else {
bean.moreCheckPos = checkedId;
}
}
};
/**
* 更新文本
*
* @param tag 0--发送 1--接收
* @param data 数据
*/
private void updateText(int tag, String data) {
Message msg = Message.obtain();
msg.what = WHAT_UPDATE_DATA;
msg.obj = data;
msg.arg1 = tag;
getHandler().sendMessage(msg);
}
/**
* 初始化一个Handler如果需要使用Handler先调用此方法
* 然后可以使用postRunnable(Runnable runnable)
* sendMessage在handleMessageMessage msg中接收msg
*/
public void initHandler() {
mBaseHandler = new BaseHandler(this);
}
/**
* 返回Handler在此之前确定已经调用initHandler
*
* @return Handler
*/
public Handler getHandler() {
return mBaseHandler;
}
/**
* 同Handler的postRunnable
* 在此之前确定已经调用initHandler
*/
protected void postRunnable(Runnable runnable) {
postRunnableDelayed(runnable, 0);
}
/**
* 同Handler的postRunnableDelayed
* 在此之前确定已经调用initHandler
*/
protected void postRunnableDelayed(Runnable runnable, long delayMillis) {
if (mBaseHandler == null) initHandler();
mBaseHandler.postDelayed(runnable, delayMillis);
}
/**
* 同Handler 的 handleMessage
* getHandler.sendMessage,发送的Message在此接收
* 在此之前确定已经调用initHandler
*
* @param msg
*/
protected void handleMessage(Message msg) {
switch (msg.what) {
case WHAT_UPDATE_DATA:
if (msg.arg1 == 0) {
text.setTextColor(Color.parseColor("#FFFFFF"));
} else {
text.setTextColor(Color.parseColor("#FF0000"));
}
String str = (String) msg.obj;
if (str.length() < 100) {
text.setTextSize(14);
} else {
text.setTextSize(10);
}
text.setText(str);
break;
}
}
protected static class BaseHandler extends Handler {
private final WeakReference<SpecialVehicleFloatWindow> mObjects;
public BaseHandler(SpecialVehicleFloatWindow mPresenter) {
mObjects = new WeakReference<SpecialVehicleFloatWindow>(mPresenter);
}
@Override
public void handleMessage(Message msg) {
SpecialVehicleFloatWindow mPresenter = mObjects.get();
if (mPresenter != null)
mPresenter.handleMessage(msg);
}
}
}

View File

@@ -0,0 +1,94 @@
package com.zhidao.adas.client.ui.special;
import android.content.Context;
import android.graphics.PixelFormat;
import android.view.Gravity;
import android.view.WindowManager;
import com.zhidao.adas.client.bean.SpecialVehicleBean;
public class SpecialVehicleFloatWindowManager implements SpecialVehicleFloatWindow.OnFloatWindowListener {
private final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
private SpecialVehicleFloatWindow floatWindow = null;
private WindowManager wm = null;
private final Context context;
private final SpecialVehicleBean specialVehicleBean;
public SpecialVehicleFloatWindowManager(Context context, SpecialVehicleBean specialVehicleBean) {
this.context = context;
this.specialVehicleBean = specialVehicleBean;
}
public void show() {
if (!createFloatWindow()) {
if (floatWindow.isMaximize()) {
floatWindow.minimality();
} else {
floatWindow.maximize();
}
}
}
private boolean createFloatWindow() {
if (floatWindow == null) {
wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
layoutParams.format = PixelFormat.RGBA_8888;
layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;//| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
layoutParams.gravity = Gravity.START | Gravity.TOP;
layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
layoutParams.alpha = 0.9f;
floatWindow = new SpecialVehicleFloatWindow(context, specialVehicleBean);
floatWindow.setWmParams(layoutParams);
floatWindow.setOnFloatWindowListener(this);
layoutParams.x = specialVehicleBean.getFloatWindowLocationMaxX(context);
layoutParams.y = specialVehicleBean.getFloatWindowLocationMaxY(context);
wm.addView(floatWindow, layoutParams);
return true;
}
return false;
}
private void removeFloatWindow() {
if (floatWindow != null) {
wm.removeView(floatWindow);
floatWindow = null;
wm = null;
}
}
@Override
public void onBack() {
removeFloatWindow();
}
@Override
public void onMinimality() {
layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
layoutParams.x = specialVehicleBean.getFloatWindowLocationMinX(context);
layoutParams.y = specialVehicleBean.getFloatWindowLocationMinY(context);
layoutParams.alpha = 1f;
if (floatWindow != null) {
floatWindow.updateViewLayout();
}
}
@Override
public void onMaximize() {
layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
layoutParams.x = specialVehicleBean.getFloatWindowLocationMaxX(context);
layoutParams.y = specialVehicleBean.getFloatWindowLocationMaxY(context);
layoutParams.alpha = 0.9f;
if (floatWindow != null) {
floatWindow.updateViewLayout();
}
}
}

View File

@@ -173,6 +173,7 @@ public class Constants {
String SEND_SET_AUTOPILOT_MODE_REQ = "自动驾驶模式";
String SEND_GLOBAL_PATH_REQ = "自动驾驶路径查询";
String SEND_SPECIAL_VEHICLE_TASK_CMD = "特种车辆";
String SEND_STATUS_QUERY_REQ = "状态查询";
String SEND_BASIC_INFO_RESP = "下发SN";
String SEND_RECORD_DATA_5 = "数据采集5秒";

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true">
<shape android:shape="rectangle">
<padding android:bottom="4dp" android:left="6dp" android:right="6dp" android:top="4dp" />
<!-- 圆角深红色按钮 -->
<solid android:color="#990033" />
<corners android:radius="8dip" />
<stroke android:width=".5dp" android:color="#ffffff" />
</shape>
</item>
<item android:state_checked="false">
<shape android:shape="rectangle">
<padding android:bottom="4dp" android:left="6dp" android:right="6dp" android:top="4dp" />
<!-- 圆角红色按钮 -->
<solid android:color="@color/colorPrimary" />
<corners android:radius="8dip" />
<stroke android:width=".5dp" android:color="#ffffff" android:dashWidth="3dp" android:dashGap="3dp" />
</shape>
</item>
</selector>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 圆角红色按钮 -->
<solid android:color="#E0000000" />
<corners android:radius="8dp" />
</shape>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#F5F5F5" android:state_pressed="true" />
<item android:color="#F5F5F5" android:state_checked="true" />
<item android:color="#F5F5F5" android:state_selected="true" />
<item android:color="#000000" />
</selector>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval"
android:useLevel="false">
<solid android:color="#90D3D3D3" />
<size
android:width="100dp"
android:height="100dp" />
<stroke
android:width=".3dp"
android:color="#90FF0033" />
</shape>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="30dp"
android:height="30dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="#FFFFFF"
android:pathData="M823.04,840.32 L524.16,540.16l296.32,-294.4c12.8,-12.8 12.8,-33.28 0,-45.44 -12.8,-12.8 -33.28,-12.8 -46.08,0L478.08,494.08 184.96,200.32c-12.8,-12.8 -33.28,-12.8 -45.44,0s-12.8,33.28 0,45.44l292.48,293.76 -302.72,300.8c-12.8,12.8 -12.8,33.28 0,45.44 12.8,12.8 33.28,12.8 46.08,0l302.72,-300.16 299.52,300.16c12.8,12.8 33.28,12.8 45.44,0C835.2,873.6 835.2,853.12 823.04,840.32z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="30dp"
android:height="30dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="#99FFFFFF"
android:pathData="M823.04,840.32 L524.16,540.16l296.32,-294.4c12.8,-12.8 12.8,-33.28 0,-45.44 -12.8,-12.8 -33.28,-12.8 -46.08,0L478.08,494.08 184.96,200.32c-12.8,-12.8 -33.28,-12.8 -45.44,0s-12.8,33.28 0,45.44l292.48,293.76 -302.72,300.8c-12.8,12.8 -12.8,33.28 0,45.44 12.8,12.8 33.28,12.8 46.08,0l302.72,-300.16 299.52,300.16c12.8,12.8 33.28,12.8 45.44,0C835.2,873.6 835.2,853.12 823.04,840.32z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="30dp"
android:height="30dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="#FFFFFF"
android:pathData="M449.92,543.36C449.92,520.96 431.36,512 410.24,512L97.92,512c-17.92,0 -32,14.08 -32,32 0,17.92 14.08,32 32,32l242.56,0 -267.52,267.52c-12.16,12.16 -12.16,31.36 0,43.52 12.16,12.16 31.36,12.16 43.52,0l269.44,-269.44 0,246.4c0,17.92 14.08,32 32,32 17.92,0 32,-14.08 32,-32l0,-320M865.92,384 L622.72,384l267.52,-267.52c12.16,-12.16 12.16,-31.36 0,-43.52 -12.16,-12.16 -31.36,-12.16 -43.52,0L577.92,342.4 577.92,96C577.92,78.08 563.2,64 545.92,64c-17.92,0 -32,14.08 -32,32l0,320c0,0.64 0.64,1.28 0.64,1.92 0,8.32 2.56,16.64 8.96,22.4C531.2,448.64 542.72,451.2 552.96,448l312.32,0c17.92,0 32,-14.08 32,-32C897.92,398.08 883.2,384 865.92,384z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="30dp"
android:height="30dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="#99FFFFFF"
android:pathData="M449.92,543.36C449.92,520.96 431.36,512 410.24,512L97.92,512c-17.92,0 -32,14.08 -32,32 0,17.92 14.08,32 32,32l242.56,0 -267.52,267.52c-12.16,12.16 -12.16,31.36 0,43.52 12.16,12.16 31.36,12.16 43.52,0l269.44,-269.44 0,246.4c0,17.92 14.08,32 32,32 17.92,0 32,-14.08 32,-32l0,-320M865.92,384 L622.72,384l267.52,-267.52c12.16,-12.16 12.16,-31.36 0,-43.52 -12.16,-12.16 -31.36,-12.16 -43.52,0L577.92,342.4 577.92,96C577.92,78.08 563.2,64 545.92,64c-17.92,0 -32,14.08 -32,32l0,320c0,0.64 0.64,1.28 0.64,1.92 0,8.32 2.56,16.64 8.96,22.4C531.2,448.64 542.72,451.2 552.96,448l312.32,0c17.92,0 32,-14.08 32,-32C897.92,398.08 883.2,384 865.92,384z"/>
</vector>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true">
<shape>
<padding android:bottom="3dp" android:left="5dp" android:right="5dp" android:top="3dp" />
<solid android:color="#6bb5af" />
<corners android:radius="5dp" />
</shape>
</item>
<item android:state_checked="false">
<shape>
<padding android:bottom="3dp" android:left="5dp" android:right="5dp" android:top="3dp" />
<solid android:color="#C0C0C0" />
<corners android:radius="5dp" />
</shape>
</item>
</selector>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_special_vehicle_back_true" android:state_pressed="true" />
<item android:drawable="@drawable/ic_special_vehicle_back" />
</selector>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_special_vehicle_minimality_true" android:state_pressed="true" />
<item android:drawable="@drawable/ic_special_vehicle_minimality" />
</selector>

View File

@@ -0,0 +1,161 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/bg"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/can_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_special_vehicle_float"
android:minWidth="400dp"
android:orientation="vertical">
<ImageButton
android:id="@+id/btn_back"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_gravity="center"
android:layout_marginStart="5dp"
android:background="@null"
android:padding="5dp"
android:src="@drawable/selector_special_vehicle_back"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/btn_minimality"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_gravity="center"
android:layout_marginStart="5dp"
android:background="@null"
android:padding="5dp"
android:src="@drawable/selector_special_vehicle_minimality"
app:layout_constraintStart_toEndOf="@id/btn_back"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/btn_minimality"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/btn_minimality" />
<RadioGroup
android:id="@+id/rg_send_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="@id/btn_minimality"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/btn_minimality">
<RadioButton
android:id="@+id/btn_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_radio_button"
android:button="@null"
android:text="单条"
android:textColor="#fff" />
<RadioButton
android:id="@+id/btn_more"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:background="@drawable/bg_radio_button"
android:button="@null"
android:text="多条"
android:textColor="#fff" />
<RadioButton
android:id="@+id/btn_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:background="@drawable/bg_radio_button"
android:button="@null"
android:text="同时"
android:textColor="#fff" />
</RadioGroup>
<TextView
android:id="@+id/hint_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="2dp"
android:gravity="center"
android:text="发送方式:"
android:textColor="#fff"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="@id/rg_send_type"
app:layout_constraintEnd_toStartOf="@id/rg_send_type"
app:layout_constraintTop_toTopOf="@id/rg_send_type" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btn_send"
android:layout_width="50dp"
android:layout_height="30dp"
android:layout_marginEnd="10dp"
android:background="@drawable/btn_bg"
android:gravity="center"
android:text="发送"
android:textColor="@color/colorWhile"
android:textSize="16sp"
android:textStyle="bold"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_back" />
<TextView
android:id="@+id/text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:minHeight="30dp"
android:textColor="#ffffff"
app:layout_constraintEnd_toStartOf="@id/btn_send"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_back" />
<HorizontalScrollView
android:id="@+id/btn_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="15dp"
android:layout_marginTop="5dp"
android:layout_marginRight="15dp"
android:layout_marginBottom="2dp"
android:scrollbars="none"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/text" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/btn_maximize"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:background="@drawable/btn_special_vehicle_small_bg"
android:gravity="center"
android:textColor="@drawable/btn_maximize_text_color"
android:textSize="14sp"
android:visibility="gone" />
</merge>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:paddingStart="5dp"
android:paddingEnd="5dp">
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:textSize="14.5sp" />
<RadioGroup
android:id="@+id/item_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"/>
</LinearLayout>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<RadioButton xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/r_btn"
style="@style/RadioBtnStyle"
android:text="0-未知" />

View File

@@ -31,4 +31,15 @@
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
<style name="RadioBtnStyle">
<item name="android:button">@null</item>
<item name="android:layout_marginTop">4dp</item>
<item name="android:layout_marginBottom">4dp</item>
<item name="android:textSize">22sp</item>
<item name="android:textColor">#fff</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">35dp</item>
<item name="android:background">@drawable/radio_btn_bg</item>
</style>
</resources>