添加简单位置信息保存功能
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Mon Sep 29 18:46:38 HKT 2025
|
||||
#Mon Sep 29 12:02:00 GMT 2025
|
||||
stageCount=3
|
||||
libraryProject=
|
||||
baseVersion=15.0
|
||||
publishVersion=15.0.2
|
||||
buildCount=0
|
||||
buildCount=4
|
||||
baseBetaVersion=15.0.3
|
||||
|
||||
@@ -1,219 +1,306 @@
|
||||
package cc.winboll.studio.positions.activities;
|
||||
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
* @Date 2025/09/29 18:22
|
||||
* @Describe 当前位置实时显示
|
||||
*/
|
||||
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import cc.winboll.studio.positions.R;
|
||||
import com.google.android.gms.location.FusedLocationProviderClient;
|
||||
import com.google.android.gms.location.LocationCallback;
|
||||
import com.google.android.gms.location.LocationRequest;
|
||||
import com.google.android.gms.location.LocationResult;
|
||||
import com.google.android.gms.location.LocationServices;
|
||||
import com.google.android.gms.tasks.OnSuccessListener;
|
||||
import cc.winboll.studio.positions.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.widget.EditText;
|
||||
import android.text.InputType;
|
||||
import cc.winboll.studio.positions.models.PositionModel;
|
||||
|
||||
/**
|
||||
* 实时定位活动窗口:
|
||||
* 1. 申请定位必需权限(精确定位+粗略定位)
|
||||
* 1. 申请定位必需权限(精确定位)
|
||||
* 2. 初始化FusedLocationProviderClient(谷歌官方定位服务,兼容所有安卓版本)
|
||||
* 3. 实时监听位置变化,更新显示经度、纬度
|
||||
* 4. 右下角圆形悬浮按钮(含大写P字母,支持扩展功能)
|
||||
*/
|
||||
public class LocationActivity extends AppCompatActivity {
|
||||
|
||||
public static final String TAG = "LocationActivity";
|
||||
|
||||
// 1. 核心组件与常量定义
|
||||
private static final int REQUEST_LOCATION_PERMISSIONS = 1004; // 定位权限请求码
|
||||
private FusedLocationProviderClient fusedLocationClient; // 定位核心客户端
|
||||
private LocationCallback locationCallback; // 位置变化监听器
|
||||
private LocationRequest locationRequest; // 定位请求配置(频率、精度等)
|
||||
|
||||
// UI控件:用于显示经纬度(需在布局中定义对应ID)
|
||||
private TextView tvLongitude; // 经度显示
|
||||
private TextView tvLatitude; // 纬度显示
|
||||
public static final String TAG = "LocationActivity";
|
||||
|
||||
// 1. 核心组件与常量定义(Java 7不支持final修饰后未立即初始化的变量,移除不必要final)
|
||||
private static final int REQUEST_LOCATION_PERMISSIONS = 1004; // 定位权限请求码
|
||||
private FusedLocationProviderClient fusedLocationClient; // 定位核心客户端
|
||||
private LocationCallback locationCallback; // 位置变化监听器
|
||||
private LocationRequest locationRequest; // 定位请求配置(频率、精度等)
|
||||
|
||||
// UI控件:Java 7不支持变量声明后直接换行注释,调整注释位置
|
||||
private TextView tvLongitude; // 经度显示
|
||||
private TextView tvLatitude; // 纬度显示
|
||||
private Button fabPButton; // 右下角圆形悬浮按钮(P字母)
|
||||
ArrayList<PositionModel> mPositionList = new ArrayList<PositionModel>();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_location);
|
||||
|
||||
// 绑定UI控件(Java 7无语法差异,保持逻辑)
|
||||
tvLongitude = (TextView) findViewById(R.id.tv_longitude); // Java 7需显式强制转换
|
||||
tvLatitude = (TextView) findViewById(R.id.tv_latitude);
|
||||
fabPButton = (Button) findViewById(R.id.fab_p_button); // 绑定悬浮按钮
|
||||
|
||||
// 初始化定位相关组件
|
||||
initLocationConfig();
|
||||
// 初始化悬浮按钮(设置点击事件)
|
||||
initFabPButton();
|
||||
|
||||
// 检查并申请定位权限
|
||||
if (checkLocationPermissions()) {
|
||||
startRealTimeLocation();
|
||||
} else {
|
||||
requestLocationPermissions();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
// 2. 加载布局(需手动创建对应布局文件,见下方说明)
|
||||
setContentView(R.layout.activity_location);
|
||||
|
||||
// 3. 绑定UI控件(与布局文件中的TextView ID对应)
|
||||
tvLongitude = findViewById(R.id.tv_longitude);
|
||||
tvLatitude = findViewById(R.id.tv_latitude);
|
||||
|
||||
// 4. 初始化定位相关组件
|
||||
initLocationConfig();
|
||||
|
||||
// 5. 检查并申请定位权限(无权限则申请,有权限则直接启动定位)
|
||||
if (checkLocationPermissions()) {
|
||||
startRealTimeLocation(); // 权限已授予 → 启动实时定位
|
||||
} else {
|
||||
requestLocationPermissions(); // 权限未授予 → 申请权限
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化定位配置:设置定位精度、更新频率等
|
||||
*/
|
||||
private void initLocationConfig() {
|
||||
// 初始化定位客户端(谷歌官方推荐,替代旧的LocationManager)
|
||||
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
|
||||
|
||||
// 配置定位请求:实时更新(1秒请求一次,最小间隔500毫秒,最高精度)
|
||||
locationRequest = new LocationRequest.Builder(1000) // 定位更新间隔(毫秒)
|
||||
.setMinUpdateIntervalMillis(500) // 最小更新间隔(避免频繁更新耗电)
|
||||
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) // 高精度定位(优先GPS)
|
||||
.build();
|
||||
|
||||
// 初始化位置变化监听器:位置更新时触发(实时更新UI)
|
||||
locationCallback = new LocationCallback() {
|
||||
@Override
|
||||
public void onLocationResult(@NonNull LocationResult locationResult) {
|
||||
super.onLocationResult(locationResult);
|
||||
// 获取最新位置信息(locationResult包含最近一次或多次位置)
|
||||
Location latestLocation = locationResult.getLastLocation();
|
||||
if (latestLocation != null) {
|
||||
// 6. 提取经纬度并更新UI(实时显示)
|
||||
double longitude = latestLocation.getLongitude(); // 经度(东经为正,西经为负)
|
||||
double latitude = latestLocation.getLatitude(); // 纬度(北纬为正,南纬为负)
|
||||
|
||||
// 更新TextView显示(保留6位小数,精度足够日常使用)
|
||||
tvLongitude.setText(String.format("当前经度:%.6f", longitude));
|
||||
tvLatitude.setText(String.format("当前纬度:%.6f", latitude));
|
||||
/**
|
||||
* 初始化悬浮按钮(设置点击事件,Java 7不支持Lambda,改用匿名内部类)
|
||||
*/
|
||||
private void initFabPButton() {
|
||||
// 悬浮按钮点击事件:替换Lambda为View.OnClickListener匿名内部类
|
||||
fabPButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
showLocationRemarkDialog();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检查定位必需权限是否已授予(精确定位+粗略定位,覆盖所有安卓版本)
|
||||
*/
|
||||
private boolean checkLocationPermissions() {
|
||||
// 安卓12+(API31+)新增精确定位权限,需同时检查2个权限;低版本只需检查1个
|
||||
/*if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
|
||||
return ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
||||
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
|
||||
} else {*/
|
||||
return ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
|
||||
//}
|
||||
}
|
||||
/**
|
||||
* 初始化定位配置:Java 7不支持LocationRequest.Builder(适配旧API),调整定位请求创建方式
|
||||
*/
|
||||
private void initLocationConfig() {
|
||||
// 初始化定位客户端(Java 7语法无差异)
|
||||
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
|
||||
|
||||
// 关键修改:Java 7环境对应旧版Google Play Services,用LocationRequest.create()替代Builder
|
||||
locationRequest = LocationRequest.create();
|
||||
locationRequest.setInterval(1000); // 定位更新间隔(毫秒)- 替代Builder(1000)
|
||||
locationRequest.setFastestInterval(500); // 最小更新间隔 - 替代setMinUpdateIntervalMillis
|
||||
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); // 高精度定位(优先GPS)
|
||||
|
||||
// 初始化位置变化监听器:替换Lambda为LocationCallback匿名内部类(Java 7核心修改)
|
||||
locationCallback = new LocationCallback() {
|
||||
@Override
|
||||
public void onLocationResult(@NonNull LocationResult locationResult) {
|
||||
super.onLocationResult(locationResult);
|
||||
// 获取最新位置信息(逻辑不变,Java 7语法兼容)
|
||||
Location latestLocation = locationResult.getLastLocation();
|
||||
if (latestLocation != null) {
|
||||
double longitude = latestLocation.getLongitude(); // 经度
|
||||
double latitude = latestLocation.getLatitude(); // 纬度
|
||||
|
||||
// 更新UI:String.format兼容Java 7,逻辑不变
|
||||
tvLongitude.setText(String.format("当前经度:%.6f", longitude));
|
||||
tvLatitude.setText(String.format("当前纬度:%.6f", latitude));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 申请定位必需权限(弹系统授权弹窗)
|
||||
*/
|
||||
private void requestLocationPermissions() {
|
||||
/*if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
|
||||
// 安卓12+:同时申请精确定位+粗略定位
|
||||
ActivityCompat.requestPermissions(
|
||||
this,
|
||||
new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
|
||||
REQUEST_LOCATION_PERMISSIONS
|
||||
);
|
||||
} else {*/
|
||||
// 安卓12以下:仅申请精确定位(包含粗略定位能力)
|
||||
ActivityCompat.requestPermissions(
|
||||
this,
|
||||
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
|
||||
REQUEST_LOCATION_PERMISSIONS
|
||||
);
|
||||
//}
|
||||
}
|
||||
/**
|
||||
* 检查定位必需权限(逻辑不变,Java 7语法兼容)
|
||||
*/
|
||||
private boolean checkLocationPermissions() {
|
||||
// Java 7不支持多行条件判断的简洁换行,调整格式保持可读性
|
||||
return ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
== PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 启动实时定位:注册位置监听器,开始接收位置更新
|
||||
*/
|
||||
private void startRealTimeLocation() {
|
||||
// 权限兜底检查(避免异常)
|
||||
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||
Toast.makeText(this, "定位权限未授予,无法启动定位", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* 申请定位必需权限(逻辑不变,Java 7语法兼容)
|
||||
*/
|
||||
private void requestLocationPermissions() {
|
||||
// Java 7数组初始化语法无差异,保持原逻辑
|
||||
String[] permissions = new String[]{Manifest.permission.ACCESS_FINE_LOCATION};
|
||||
ActivityCompat.requestPermissions(
|
||||
this,
|
||||
permissions,
|
||||
REQUEST_LOCATION_PERMISSIONS
|
||||
);
|
||||
}
|
||||
|
||||
// 1. 先获取一次当前位置(快速显示初始经纬度)
|
||||
fusedLocationClient.getLastLocation()
|
||||
|
||||
/**
|
||||
* 启动实时定位:Java 7不支持Lambda,替换OnSuccessListener为匿名内部类
|
||||
*/
|
||||
private void startRealTimeLocation() {
|
||||
// 权限兜底检查(逻辑不变)
|
||||
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
Toast.makeText(this, "定位权限未授予,无法启动定位", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 先获取一次当前位置:替换Lambda为OnSuccessListener匿名内部类(Java 7核心修改)
|
||||
fusedLocationClient.getLastLocation()
|
||||
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
|
||||
@Override
|
||||
public void onSuccess(Location location) {
|
||||
// 成功获取位置后的逻辑(无语法差异)
|
||||
if (location != null) {
|
||||
// 显示初始经纬度
|
||||
tvLongitude.setText(String.format("当前经度:%.6f", location.getLongitude()));
|
||||
tvLatitude.setText(String.format("当前纬度:%.6f", location.getLatitude()));
|
||||
} else {
|
||||
// 无历史位置(如首次启动),提示“等待定位更新”
|
||||
tvLongitude.setText("当前经度:等待更新...");
|
||||
tvLatitude.setText("当前纬度:等待更新...");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 2. 注册监听器,接收实时位置更新(持续监听)
|
||||
fusedLocationClient.requestLocationUpdates(
|
||||
// 2. 注册监听器,接收实时位置更新(逻辑不变,Java 7语法兼容)
|
||||
fusedLocationClient.requestLocationUpdates(
|
||||
locationRequest,
|
||||
locationCallback,
|
||||
getMainLooper() // 在主线程更新UI(避免线程异常)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 处理权限申请结果(逻辑不变,Java 7语法兼容)
|
||||
*/
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (requestCode == REQUEST_LOCATION_PERMISSIONS) {
|
||||
boolean allGranted = true;
|
||||
// Java 7增强for循环语法无差异
|
||||
for (int result : grantResults) {
|
||||
if (result != PackageManager.PERMISSION_GRANTED) {
|
||||
allGranted = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allGranted) {
|
||||
startRealTimeLocation();
|
||||
} else {
|
||||
Toast.makeText(this, "定位权限被拒绝,无法显示位置信息", Toast.LENGTH_SHORT).show();
|
||||
tvLongitude.setText("当前经度:无权限");
|
||||
tvLatitude.setText("当前纬度:无权限");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 活动销毁时停止定位监听(逻辑不变,Java 7语法兼容)
|
||||
*/
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
// Java 7条件判断格式无差异,保持空指针防护
|
||||
if (fusedLocationClient != null && locationCallback != null) {
|
||||
fusedLocationClient.removeLocationUpdates(locationCallback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理权限申请结果(用户同意/拒绝后触发)
|
||||
*/
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (requestCode == REQUEST_LOCATION_PERMISSIONS) {
|
||||
// 检查是否所有必需权限都已授予
|
||||
boolean allGranted = true;
|
||||
for (int result : grantResults) {
|
||||
if (result != PackageManager.PERMISSION_GRANTED) {
|
||||
allGranted = false;
|
||||
break;
|
||||
* 弹出“当前位置备注”输入对话框:
|
||||
* 1. 显示带文本输入框的对话框(标题固定为“当前位置备注”)
|
||||
* 2. 点击确定→弹Toast显示输入的备注内容
|
||||
* 3. 点击取消/关闭对话框→不执行操作
|
||||
*/
|
||||
private void showLocationRemarkDialog() {
|
||||
// 1. 初始化对话框构建器(Java 7需显式指定Context为LocationActivity.this)
|
||||
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(LocationActivity.this);
|
||||
dialogBuilder.setTitle("当前位置备注"); // 设置对话框标题
|
||||
|
||||
// 2. 创建文本输入框(配置输入类型为普通文本,提示用户输入)
|
||||
final EditText remarkInput = new EditText(LocationActivity.this);
|
||||
remarkInput.setHint("请输入当前位置的备注(如:公司/家/学校)"); // 输入提示
|
||||
remarkInput.setInputType(InputType.TYPE_CLASS_TEXT); // 普通文本输入(禁止数字/密码等特殊类型)
|
||||
remarkInput.setPadding(
|
||||
dip2px(16), // 左内边距(16dp,适配不同屏幕)
|
||||
dip2px(8), // 上内边距
|
||||
dip2px(16), // 右内边距
|
||||
dip2px(8) // 下内边距
|
||||
);
|
||||
dialogBuilder.setView(remarkInput); // 将输入框添加到对话框
|
||||
|
||||
// 3. 设置“确定”按钮(点击后获取输入内容,弹Toast显示)
|
||||
dialogBuilder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// 获取输入框内容(trim()去除前后空格,避免空输入)
|
||||
String inputRemark = remarkInput.getText().toString().trim();
|
||||
|
||||
// 处理输入:空输入提示“未输入备注”,非空提示输入内容
|
||||
if (inputRemark.isEmpty()) {
|
||||
Toast.makeText(LocationActivity.this, "未输入位置备注", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Toast.makeText(LocationActivity.this, "当前位置备注:" + inputRemark, Toast.LENGTH_SHORT).show();
|
||||
|
||||
// 扩展建议:获取当前经纬度做操作(Java 7字符串处理逻辑不变)
|
||||
if (tvLongitude.getText().toString().contains(":")) {
|
||||
String szLongitude = tvLongitude.getText().toString().split(":")[1];
|
||||
double longitude = Double.parseDouble(szLongitude);
|
||||
String szLatitude = tvLatitude.getText().toString().split(":")[1];
|
||||
double latitude = Double.parseDouble(szLatitude);
|
||||
// saveCurrentLocation(longitude, latitude); // 自定义“保存位置”方法(如需使用需自己实现)
|
||||
mPositionList.add(new PositionModel(longitude, latitude, inputRemark));
|
||||
PositionModel.saveBeanList(LocationActivity.this, mPositionList, PositionModel.class);
|
||||
}
|
||||
}
|
||||
dialog.dismiss(); // 关闭对话框(避免残留)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (allGranted) {
|
||||
// 权限同意 → 启动实时定位
|
||||
startRealTimeLocation();
|
||||
} else {
|
||||
// 权限拒绝 → 提示用户(无法定位)
|
||||
Toast.makeText(this, "定位权限被拒绝,无法显示位置信息", Toast.LENGTH_SHORT).show();
|
||||
tvLongitude.setText("当前经度:无权限");
|
||||
tvLatitude.setText("当前纬度:无权限");
|
||||
}
|
||||
}
|
||||
}
|
||||
// 4. 设置“取消”按钮(点击仅关闭对话框,不做其他操作)
|
||||
dialogBuilder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss(); // 关闭对话框
|
||||
}
|
||||
});
|
||||
|
||||
// 5. 配置对话框其他属性(禁止点击外部关闭、禁止按返回键关闭)
|
||||
dialogBuilder.setCancelable(false); // 点击对话框外部不关闭
|
||||
AlertDialog remarkDialog = dialogBuilder.create(); // 创建对话框实例
|
||||
remarkDialog.setCanceledOnTouchOutside(false); // 再次确认“外部点击不关闭”(兼容部分机型)
|
||||
|
||||
/**
|
||||
* 活动销毁时:停止定位监听(避免内存泄漏、减少耗电)
|
||||
*/
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
// 移除定位监听器(核心:防止Activity销毁后仍在监听,导致内存泄漏)
|
||||
if (fusedLocationClient != null && locationCallback != null) {
|
||||
fusedLocationClient.removeLocationUpdates(locationCallback);
|
||||
}
|
||||
}
|
||||
// 6. 显示对话框
|
||||
remarkDialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 辅助工具:将dp转换为px(解决不同屏幕分辨率下输入框内边距不一致问题)
|
||||
* @param dpValue 要转换的dp值(如16dp)
|
||||
* @return 转换后的px值(适配当前设备屏幕密度)
|
||||
*/
|
||||
private int dip2px(float dpValue) {
|
||||
// 获取设备屏幕密度(density),dp转px公式:px = dp * density + 0.5f(+0.5f用于四舍五入)
|
||||
final float scale = getResources().getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
package cc.winboll.studio.positions.models;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
* @Date 2025/09/29 18:57
|
||||
* @Describe 位置数据模型
|
||||
*/
|
||||
import android.util.JsonReader;
|
||||
import android.util.JsonWriter;
|
||||
import cc.winboll.studio.libappbase.BaseBean;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PositionModel extends BaseBean {
|
||||
|
||||
public static final String TAG = "PositionModel";
|
||||
// 经度
|
||||
double longitude;
|
||||
// 纬度
|
||||
double latitude;
|
||||
// 位置信息备注
|
||||
String memo;
|
||||
|
||||
public PositionModel(double longitude, double latitude, String memo) {
|
||||
this.longitude = longitude;
|
||||
this.latitude = latitude;
|
||||
this.memo = memo;
|
||||
}
|
||||
|
||||
public PositionModel() {
|
||||
this.longitude = 0.0f;
|
||||
this.latitude = 0.0f;
|
||||
this.memo = "";
|
||||
}
|
||||
|
||||
public void setMemo(String memo) {
|
||||
this.memo = memo;
|
||||
}
|
||||
|
||||
public String getMemo() {
|
||||
return memo;
|
||||
}
|
||||
|
||||
public void setLongitude(double longitude) {
|
||||
this.longitude = longitude;
|
||||
}
|
||||
|
||||
public double getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
||||
public void setLatitude(double latitude) {
|
||||
this.latitude = latitude;
|
||||
}
|
||||
|
||||
public double getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return PositionModel.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
|
||||
super.writeThisToJsonWriter(jsonWriter);
|
||||
jsonWriter.name("longitude").value(getLongitude());
|
||||
jsonWriter.name("latitude").value(getLatitude());
|
||||
jsonWriter.name("memo").value(getMemo());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
|
||||
if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
|
||||
if (name.equals("longitude")) {
|
||||
setLongitude(jsonReader.nextDouble());
|
||||
} else if (name.equals("latitude")) {
|
||||
setLatitude(jsonReader.nextDouble());
|
||||
} else if (name.equals("memo")) {
|
||||
setMemo(jsonReader.nextString());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException {
|
||||
jsonReader.beginObject();
|
||||
while (jsonReader.hasNext()) {
|
||||
String name = jsonReader.nextName();
|
||||
if (!initObjectsFromJsonReader(jsonReader, name)) {
|
||||
jsonReader.skipValue();
|
||||
}
|
||||
}
|
||||
// 结束 JSON 对象
|
||||
jsonReader.endObject();
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
21
positions/src/main/res/drawable/circle_button_bg.xml
Normal file
21
positions/src/main/res/drawable/circle_button_bg.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 圆形按钮背景:默认青色,按压时深色 -->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- 按钮按压状态(深色,增强交互反馈) -->
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="oval"> <!-- oval=圆形 -->
|
||||
<solid android:color="#0F9D58"/> <!-- 按压时颜色:深青色(接近Google绿,美观且醒目) -->
|
||||
<stroke android:width="1dp" android:color="#0F9D58"/> <!-- 边框颜色与背景一致,避免白边 -->
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<!-- 按钮默认状态(青色) -->
|
||||
<item>
|
||||
<shape android:shape="oval">
|
||||
<solid android:color="#14C38E"/> <!-- 默认颜色:亮青色(视觉舒适,符合悬浮按钮风格) -->
|
||||
<stroke android:width="1dp" android:color="#14C38E"/>
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</selector>
|
||||
@@ -1,34 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<!-- 根布局改为RelativeLayout,支持悬浮按钮绝对定位(右下角) -->
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
<!-- 标题 -->
|
||||
<TextView
|
||||
<!-- 原有内容:经纬度显示区域(保持居中) -->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="实时位置信息"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold"/>
|
||||
android:layout_centerInParent="true"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_horizontal">
|
||||
|
||||
<!-- 经度显示(大字体,清晰可见) -->
|
||||
<TextView
|
||||
android:id="@+id/tv_longitude"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="当前经度:等待更新..."
|
||||
android:textSize="18sp"/>
|
||||
<!-- 标题 -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="实时位置信息"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<!-- 纬度显示(大字体,清晰可见) -->
|
||||
<TextView
|
||||
android:id="@+id/tv_latitude"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="当前纬度:等待更新..."
|
||||
android:textSize="18sp"/>
|
||||
<!-- 经度显示 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_longitude"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="当前经度:等待更新..."
|
||||
android:textSize="18sp"/>
|
||||
|
||||
</LinearLayout>
|
||||
<!-- 纬度显示 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_latitude"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="当前纬度:等待更新..."
|
||||
android:textSize="18sp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 新增:右下角圆形悬浮按钮(中间显示大写P字母) -->
|
||||
<Button
|
||||
android:id="@+id/fab_p_button"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_margin="20dp"
|
||||
android:background="@drawable/circle_button_bg"
|
||||
android:text="P"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="24sp"
|
||||
android:elevation="6dp"
|
||||
android:padding="0dp"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user