添加简单位置信息保存功能
This commit is contained in:
		| @@ -1,8 +1,8 @@ | |||||||
| #Created by .winboll/winboll_app_build.gradle | #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 | stageCount=3 | ||||||
| libraryProject= | libraryProject= | ||||||
| baseVersion=15.0 | baseVersion=15.0 | ||||||
| publishVersion=15.0.2 | publishVersion=15.0.2 | ||||||
| buildCount=0 | buildCount=4 | ||||||
| baseBetaVersion=15.0.3 | baseBetaVersion=15.0.3 | ||||||
|   | |||||||
| @@ -1,100 +1,121 @@ | |||||||
| package cc.winboll.studio.positions.activities; | package cc.winboll.studio.positions.activities; | ||||||
|  |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @Author ZhanGSKen&豆包大模型<zhangsken@qq.com> |  * @Author ZhanGSKen&豆包大模型<zhangsken@qq.com> | ||||||
|  * @Date 2025/09/29 18:22 |  * @Date 2025/09/29 18:22 | ||||||
|  * @Describe 当前位置实时显示 |  * @Describe 当前位置实时显示 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
| import android.Manifest; | import android.Manifest; | ||||||
| import android.content.pm.PackageManager; | import android.content.pm.PackageManager; | ||||||
| import android.location.Location; | import android.location.Location; | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
|  | import android.view.View; | ||||||
|  | import android.widget.Button; | ||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
| import android.widget.Toast; | import android.widget.Toast; | ||||||
| import androidx.annotation.NonNull; | import androidx.annotation.NonNull; | ||||||
| import androidx.appcompat.app.AppCompatActivity; | import androidx.appcompat.app.AppCompatActivity; | ||||||
| import androidx.core.app.ActivityCompat; | import androidx.core.app.ActivityCompat; | ||||||
|  | import cc.winboll.studio.positions.R; | ||||||
| import com.google.android.gms.location.FusedLocationProviderClient; | import com.google.android.gms.location.FusedLocationProviderClient; | ||||||
| import com.google.android.gms.location.LocationCallback; | import com.google.android.gms.location.LocationCallback; | ||||||
| import com.google.android.gms.location.LocationRequest; | import com.google.android.gms.location.LocationRequest; | ||||||
| import com.google.android.gms.location.LocationResult; | import com.google.android.gms.location.LocationResult; | ||||||
| import com.google.android.gms.location.LocationServices; | import com.google.android.gms.location.LocationServices; | ||||||
| import com.google.android.gms.tasks.OnSuccessListener; | 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(谷歌官方定位服务,兼容所有安卓版本) |  * 2. 初始化FusedLocationProviderClient(谷歌官方定位服务,兼容所有安卓版本) | ||||||
|  * 3. 实时监听位置变化,更新显示经度、纬度 |  * 3. 实时监听位置变化,更新显示经度、纬度 | ||||||
|  |  * 4. 右下角圆形悬浮按钮(含大写P字母,支持扩展功能) | ||||||
|  */ |  */ | ||||||
| public class LocationActivity extends AppCompatActivity { | public class LocationActivity extends AppCompatActivity { | ||||||
|  |  | ||||||
|     public static final String TAG = "LocationActivity"; |     public static final String TAG = "LocationActivity"; | ||||||
|  |  | ||||||
| 	// 1. 核心组件与常量定义 |     // 1. 核心组件与常量定义(Java 7不支持final修饰后未立即初始化的变量,移除不必要final) | ||||||
|     private static final int REQUEST_LOCATION_PERMISSIONS = 1004; // 定位权限请求码 |     private static final int REQUEST_LOCATION_PERMISSIONS = 1004; // 定位权限请求码 | ||||||
|     private FusedLocationProviderClient fusedLocationClient; // 定位核心客户端 |     private FusedLocationProviderClient fusedLocationClient; // 定位核心客户端 | ||||||
|     private LocationCallback locationCallback; // 位置变化监听器 |     private LocationCallback locationCallback; // 位置变化监听器 | ||||||
|     private LocationRequest locationRequest; // 定位请求配置(频率、精度等) |     private LocationRequest locationRequest; // 定位请求配置(频率、精度等) | ||||||
|  |  | ||||||
| 	// UI控件:用于显示经纬度(需在布局中定义对应ID) |     // UI控件:Java 7不支持变量声明后直接换行注释,调整注释位置 | ||||||
|     private TextView tvLongitude; // 经度显示 |     private TextView tvLongitude; // 经度显示 | ||||||
|     private TextView tvLatitude;  // 纬度显示 |     private TextView tvLatitude;  // 纬度显示 | ||||||
|  |     private Button fabPButton;    // 右下角圆形悬浮按钮(P字母) | ||||||
|  | 	ArrayList<PositionModel> mPositionList = new ArrayList<PositionModel>(); | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     protected void onCreate(Bundle savedInstanceState) { |     protected void onCreate(Bundle savedInstanceState) { | ||||||
|         super.onCreate(savedInstanceState); |         super.onCreate(savedInstanceState); | ||||||
| 		// 2. 加载布局(需手动创建对应布局文件,见下方说明) |  | ||||||
|         setContentView(R.layout.activity_location); |         setContentView(R.layout.activity_location); | ||||||
|  |  | ||||||
| 		// 3. 绑定UI控件(与布局文件中的TextView ID对应) |         // 绑定UI控件(Java 7无语法差异,保持逻辑) | ||||||
| 		tvLongitude = findViewById(R.id.tv_longitude); |         tvLongitude = (TextView) findViewById(R.id.tv_longitude); // Java 7需显式强制转换 | ||||||
| 		tvLatitude = findViewById(R.id.tv_latitude); |         tvLatitude = (TextView) findViewById(R.id.tv_latitude); | ||||||
|  |         fabPButton = (Button) findViewById(R.id.fab_p_button); // 绑定悬浮按钮 | ||||||
|  |  | ||||||
| 		// 4. 初始化定位相关组件 |         // 初始化定位相关组件 | ||||||
|         initLocationConfig(); |         initLocationConfig(); | ||||||
|  |         // 初始化悬浮按钮(设置点击事件) | ||||||
|  |         initFabPButton(); | ||||||
|  |  | ||||||
| 		// 5. 检查并申请定位权限(无权限则申请,有权限则直接启动定位) |         // 检查并申请定位权限 | ||||||
|         if (checkLocationPermissions()) { |         if (checkLocationPermissions()) { | ||||||
| 			startRealTimeLocation(); // 权限已授予 → 启动实时定位 |             startRealTimeLocation(); | ||||||
|         } else { |         } else { | ||||||
| 			requestLocationPermissions(); // 权限未授予 → 申请权限 |             requestLocationPermissions(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| 	 * 初始化定位配置:设置定位精度、更新频率等 |      * 初始化悬浮按钮(设置点击事件,Java 7不支持Lambda,改用匿名内部类) | ||||||
|  |      */ | ||||||
|  |     private void initFabPButton() { | ||||||
|  |         // 悬浮按钮点击事件:替换Lambda为View.OnClickListener匿名内部类 | ||||||
|  |         fabPButton.setOnClickListener(new View.OnClickListener() { | ||||||
|  | 				@Override | ||||||
|  | 				public void onClick(View v) { | ||||||
|  | 					showLocationRemarkDialog(); | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 初始化定位配置:Java 7不支持LocationRequest.Builder(适配旧API),调整定位请求创建方式 | ||||||
|      */ |      */ | ||||||
|     private void initLocationConfig() { |     private void initLocationConfig() { | ||||||
| 		// 初始化定位客户端(谷歌官方推荐,替代旧的LocationManager) |         // 初始化定位客户端(Java 7语法无差异) | ||||||
|         fusedLocationClient = LocationServices.getFusedLocationProviderClient(this); |         fusedLocationClient = LocationServices.getFusedLocationProviderClient(this); | ||||||
|  |  | ||||||
| 		// 配置定位请求:实时更新(1秒请求一次,最小间隔500毫秒,最高精度) |         // 关键修改:Java 7环境对应旧版Google Play Services,用LocationRequest.create()替代Builder | ||||||
| 		locationRequest = new LocationRequest.Builder(1000) // 定位更新间隔(毫秒) |         locationRequest = LocationRequest.create(); | ||||||
| 			.setMinUpdateIntervalMillis(500) // 最小更新间隔(避免频繁更新耗电) |         locationRequest.setInterval(1000); // 定位更新间隔(毫秒)- 替代Builder(1000) | ||||||
| 			.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) // 高精度定位(优先GPS) |         locationRequest.setFastestInterval(500); // 最小更新间隔 - 替代setMinUpdateIntervalMillis | ||||||
| 			.build(); |         locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); // 高精度定位(优先GPS) | ||||||
|  |  | ||||||
| 		// 初始化位置变化监听器:位置更新时触发(实时更新UI) |         // 初始化位置变化监听器:替换Lambda为LocationCallback匿名内部类(Java 7核心修改) | ||||||
|         locationCallback = new LocationCallback() { |         locationCallback = new LocationCallback() { | ||||||
|             @Override |             @Override | ||||||
|             public void onLocationResult(@NonNull LocationResult locationResult) { |             public void onLocationResult(@NonNull LocationResult locationResult) { | ||||||
|                 super.onLocationResult(locationResult); |                 super.onLocationResult(locationResult); | ||||||
| 				// 获取最新位置信息(locationResult包含最近一次或多次位置) |                 // 获取最新位置信息(逻辑不变,Java 7语法兼容) | ||||||
|                 Location latestLocation = locationResult.getLastLocation(); |                 Location latestLocation = locationResult.getLastLocation(); | ||||||
|                 if (latestLocation != null) { |                 if (latestLocation != null) { | ||||||
| 					// 6. 提取经纬度并更新UI(实时显示) |                     double longitude = latestLocation.getLongitude(); // 经度 | ||||||
| 					double longitude = latestLocation.getLongitude(); // 经度(东经为正,西经为负) |                     double latitude = latestLocation.getLatitude();   // 纬度 | ||||||
| 					double latitude = latestLocation.getLatitude();   // 纬度(北纬为正,南纬为负) |  | ||||||
|  |  | ||||||
| 					// 更新TextView显示(保留6位小数,精度足够日常使用) |                     // 更新UI:String.format兼容Java 7,逻辑不变 | ||||||
|                     tvLongitude.setText(String.format("当前经度:%.6f", longitude)); |                     tvLongitude.setText(String.format("当前经度:%.6f", longitude)); | ||||||
|                     tvLatitude.setText(String.format("当前纬度:%.6f", latitude)); |                     tvLatitude.setText(String.format("当前纬度:%.6f", latitude)); | ||||||
|                 } |                 } | ||||||
| @@ -104,69 +125,57 @@ public class LocationActivity extends AppCompatActivity { | |||||||
|  |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| 	 * 检查定位必需权限是否已授予(精确定位+粗略定位,覆盖所有安卓版本) |      * 检查定位必需权限(逻辑不变,Java 7语法兼容) | ||||||
|      */ |      */ | ||||||
|     private boolean checkLocationPermissions() { |     private boolean checkLocationPermissions() { | ||||||
| 		// 安卓12+(API31+)新增精确定位权限,需同时检查2个权限;低版本只需检查1个 |         // Java 7不支持多行条件判断的简洁换行,调整格式保持可读性 | ||||||
| 		/*if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { |         return ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)  | ||||||
| 			return ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED | 			== 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语法兼容) | ||||||
|      */ |      */ | ||||||
|     private void requestLocationPermissions() { |     private void requestLocationPermissions() { | ||||||
| 		/*if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { |         // Java 7数组初始化语法无差异,保持原逻辑 | ||||||
| 			// 安卓12+:同时申请精确定位+粗略定位 |         String[] permissions = new String[]{Manifest.permission.ACCESS_FINE_LOCATION}; | ||||||
|         ActivityCompat.requestPermissions( |         ActivityCompat.requestPermissions( | ||||||
| 			this, | 			this, | ||||||
| 				new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, | 			permissions, | ||||||
| 			REQUEST_LOCATION_PERMISSIONS | 			REQUEST_LOCATION_PERMISSIONS | ||||||
|         ); |         ); | ||||||
| 		} else {*/ |  | ||||||
| 			// 安卓12以下:仅申请精确定位(包含粗略定位能力) |  | ||||||
| 			ActivityCompat.requestPermissions( |  | ||||||
| 				this, |  | ||||||
| 				new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, |  | ||||||
| 				REQUEST_LOCATION_PERMISSIONS |  | ||||||
| 			); |  | ||||||
| 		//} |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| 	 * 启动实时定位:注册位置监听器,开始接收位置更新 |      * 启动实时定位:Java 7不支持Lambda,替换OnSuccessListener为匿名内部类 | ||||||
|      */ |      */ | ||||||
|     private void startRealTimeLocation() { |     private void startRealTimeLocation() { | ||||||
| 		// 权限兜底检查(避免异常) |         // 权限兜底检查(逻辑不变) | ||||||
| 		if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { |         if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)  | ||||||
|  | 			!= PackageManager.PERMISSION_GRANTED) { | ||||||
|             Toast.makeText(this, "定位权限未授予,无法启动定位", Toast.LENGTH_SHORT).show(); |             Toast.makeText(this, "定位权限未授予,无法启动定位", Toast.LENGTH_SHORT).show(); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| 		// 1. 先获取一次当前位置(快速显示初始经纬度) |         // 1. 先获取一次当前位置:替换Lambda为OnSuccessListener匿名内部类(Java 7核心修改) | ||||||
|         fusedLocationClient.getLastLocation() |         fusedLocationClient.getLastLocation() | ||||||
| 			.addOnSuccessListener(this, new OnSuccessListener<Location>() { | 			.addOnSuccessListener(this, new OnSuccessListener<Location>() { | ||||||
| 				@Override | 				@Override | ||||||
| 				public void onSuccess(Location location) { | 				public void onSuccess(Location location) { | ||||||
|  | 					// 成功获取位置后的逻辑(无语法差异) | ||||||
| 					if (location != null) { | 					if (location != null) { | ||||||
| 						// 显示初始经纬度 |  | ||||||
| 						tvLongitude.setText(String.format("当前经度:%.6f", location.getLongitude())); | 						tvLongitude.setText(String.format("当前经度:%.6f", location.getLongitude())); | ||||||
| 						tvLatitude.setText(String.format("当前纬度:%.6f", location.getLatitude())); | 						tvLatitude.setText(String.format("当前纬度:%.6f", location.getLatitude())); | ||||||
| 					} else { | 					} else { | ||||||
| 						// 无历史位置(如首次启动),提示“等待定位更新” |  | ||||||
| 						tvLongitude.setText("当前经度:等待更新..."); | 						tvLongitude.setText("当前经度:等待更新..."); | ||||||
| 						tvLatitude.setText("当前纬度:等待更新..."); | 						tvLatitude.setText("当前纬度:等待更新..."); | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			}); | 			}); | ||||||
|  |  | ||||||
| 		// 2. 注册监听器,接收实时位置更新(持续监听) |         // 2. 注册监听器,接收实时位置更新(逻辑不变,Java 7语法兼容) | ||||||
|         fusedLocationClient.requestLocationUpdates( |         fusedLocationClient.requestLocationUpdates( | ||||||
| 			locationRequest, | 			locationRequest, | ||||||
| 			locationCallback, | 			locationCallback, | ||||||
| @@ -176,14 +185,14 @@ public class LocationActivity extends AppCompatActivity { | |||||||
|  |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| 	 * 处理权限申请结果(用户同意/拒绝后触发) |      * 处理权限申请结果(逻辑不变,Java 7语法兼容) | ||||||
|      */ |      */ | ||||||
|     @Override |     @Override | ||||||
|     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { |     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { | ||||||
|         super.onRequestPermissionsResult(requestCode, permissions, grantResults); |         super.onRequestPermissionsResult(requestCode, permissions, grantResults); | ||||||
|         if (requestCode == REQUEST_LOCATION_PERMISSIONS) { |         if (requestCode == REQUEST_LOCATION_PERMISSIONS) { | ||||||
| 			// 检查是否所有必需权限都已授予 |  | ||||||
|             boolean allGranted = true; |             boolean allGranted = true; | ||||||
|  |             // Java 7增强for循环语法无差异 | ||||||
|             for (int result : grantResults) { |             for (int result : grantResults) { | ||||||
|                 if (result != PackageManager.PERMISSION_GRANTED) { |                 if (result != PackageManager.PERMISSION_GRANTED) { | ||||||
|                     allGranted = false; |                     allGranted = false; | ||||||
| @@ -192,10 +201,8 @@ public class LocationActivity extends AppCompatActivity { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (allGranted) { |             if (allGranted) { | ||||||
| 				// 权限同意 → 启动实时定位 |  | ||||||
|                 startRealTimeLocation(); |                 startRealTimeLocation(); | ||||||
|             } else { |             } else { | ||||||
| 				// 权限拒绝 → 提示用户(无法定位) |  | ||||||
|                 Toast.makeText(this, "定位权限被拒绝,无法显示位置信息", Toast.LENGTH_SHORT).show(); |                 Toast.makeText(this, "定位权限被拒绝,无法显示位置信息", Toast.LENGTH_SHORT).show(); | ||||||
|                 tvLongitude.setText("当前经度:无权限"); |                 tvLongitude.setText("当前经度:无权限"); | ||||||
|                 tvLatitude.setText("当前纬度:无权限"); |                 tvLatitude.setText("当前纬度:无权限"); | ||||||
| @@ -205,15 +212,95 @@ public class LocationActivity extends AppCompatActivity { | |||||||
|  |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| 	 * 活动销毁时:停止定位监听(避免内存泄漏、减少耗电) |      * 活动销毁时停止定位监听(逻辑不变,Java 7语法兼容) | ||||||
|      */ |      */ | ||||||
|     @Override |     @Override | ||||||
|     protected void onDestroy() { |     protected void onDestroy() { | ||||||
|         super.onDestroy(); |         super.onDestroy(); | ||||||
| 		// 移除定位监听器(核心:防止Activity销毁后仍在监听,导致内存泄漏) |         // Java 7条件判断格式无差异,保持空指针防护 | ||||||
|         if (fusedLocationClient != null && locationCallback != null) { |         if (fusedLocationClient != null && locationCallback != null) { | ||||||
|             fusedLocationClient.removeLocationUpdates(locationCallback); |             fusedLocationClient.removeLocationUpdates(locationCallback); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 	 | ||||||
|  | 	/** | ||||||
|  |      * 弹出“当前位置备注”输入对话框: | ||||||
|  |      * 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(); // 关闭对话框(避免残留) | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  |  | ||||||
|  |         // 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); // 再次确认“外部点击不关闭”(兼容部分机型) | ||||||
|  |  | ||||||
|  |         // 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,11 +1,18 @@ | |||||||
| <?xml version="1.0" encoding="utf-8"?> | <?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_width="match_parent" | ||||||
|     android:layout_height="match_parent" |     android:layout_height="match_parent" | ||||||
|     android:gravity="center_horizontal|center_vertical" |  | ||||||
|     android:orientation="vertical" |  | ||||||
|     android:padding="20dp"> |     android:padding="20dp"> | ||||||
|  |  | ||||||
|  |     <!-- 原有内容:经纬度显示区域(保持居中) --> | ||||||
|  |     <LinearLayout | ||||||
|  |         android:layout_width="wrap_content" | ||||||
|  |         android:layout_height="wrap_content" | ||||||
|  |         android:layout_centerInParent="true" | ||||||
|  |         android:orientation="vertical" | ||||||
|  |         android:gravity="center_horizontal"> | ||||||
|  |  | ||||||
|         <!-- 标题 --> |         <!-- 标题 --> | ||||||
|         <TextView |         <TextView | ||||||
|             android:layout_width="wrap_content" |             android:layout_width="wrap_content" | ||||||
| @@ -14,7 +21,7 @@ | |||||||
|             android:textSize="22sp" |             android:textSize="22sp" | ||||||
|             android:textStyle="bold"/> |             android:textStyle="bold"/> | ||||||
|  |  | ||||||
|     <!-- 经度显示(大字体,清晰可见) --> |         <!-- 经度显示 --> | ||||||
|         <TextView |         <TextView | ||||||
|             android:id="@+id/tv_longitude" |             android:id="@+id/tv_longitude" | ||||||
|             android:layout_width="wrap_content" |             android:layout_width="wrap_content" | ||||||
| @@ -22,7 +29,7 @@ | |||||||
|             android:text="当前经度:等待更新..." |             android:text="当前经度:等待更新..." | ||||||
|             android:textSize="18sp"/> |             android:textSize="18sp"/> | ||||||
|  |  | ||||||
|     <!-- 纬度显示(大字体,清晰可见) --> |         <!-- 纬度显示 --> | ||||||
|         <TextView |         <TextView | ||||||
|             android:id="@+id/tv_latitude" |             android:id="@+id/tv_latitude" | ||||||
|             android:layout_width="wrap_content" |             android:layout_width="wrap_content" | ||||||
| @@ -32,3 +39,20 @@ | |||||||
|  |  | ||||||
|     </LinearLayout> |     </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
	 ZhanGSKen
					ZhanGSKen