现在,我正在做一个公交查询系统,搜索功能这一块我想进一步修改。相关代码HomeFragment如下:package com.example.bus.ui.home;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.amap.api.services.core.AMapException;
import com.amap.api.services.help.Inputtips;
import com.amap.api.services.help.Tip;
import com.example.bus.MainActivity;
import com.example.bus.SearchResultActivity;
import com.example.bus.databinding.FragmentHomeBinding;
import java.util.List;
import android.widget.ArrayAdapter;
import android.text.TextWatcher;
import android.text.Editable;
public class HomeFragment extends Fragment {
private FragmentHomeBinding binding;
private Inputtips inputTips;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
HomeViewModel homeViewModel =
new ViewModelProvider(this).get(HomeViewModel.class);
binding = FragmentHomeBinding.inflate(inflater, container, false);
View root = binding.getRoot();
final TextView textView = binding.textHome;
homeViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
setupSearchSuggestion();
binding.homeSearch.setOnClickListener(v -> {
String keyword = binding.homeInput.getText().toString().trim();
if (keyword.isEmpty()) {
Toast.makeText(requireContext(), "请输入关键词", Toast.LENGTH_SHORT).show();
return;
}
// ✅ 请求权限,权限通过后再跳转 SearchResultActivity
MainActivity activity = (MainActivity) requireActivity();
activity.ensureFineLocationPermission(() -> {
Intent intent = new Intent(requireContext(), SearchResultActivity.class);
intent.putExtra("keyword", keyword);
startActivity(intent);
});
});
return root;
}
private void setupSearchSuggestion() {
try {
inputTips = new Inputtips(requireContext(), new Inputtips.InputtipsListener() {
@Override
public void onGetInputtips(List<Tip> tipList, int rCode) {
if (rCode == 1000 && tipList != null && !tipList.isEmpty()) {
String[] arr = new String[tipList.size()];
for (int i = 0; i < tipList.size(); i++) {
arr[i] = tipList.get(i).getName();
}
ArrayAdapter<String> adapter = new ArrayAdapter<>(
requireContext(),
android.R.layout.simple_dropdown_item_1line,
arr
);
binding.homeInput.setAdapter(adapter);
} else {
binding.homeInput.setAdapter(null);
handleSearchError(rCode);
}
}
});
} catch (AMapException e) {
throw new RuntimeException(e);
}
// 创建 Handler 用于防抖
Handler handler = new Handler(Looper.getMainLooper());
Runnable[] pendingRunnable = {null}; // 使用数组包装,绕过 effectively final 限制
binding.homeInput.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// 清除上一次的延迟任务
if (pendingRunnable[0] != null) {
handler.removeCallbacks(pendingRunnable[0]);
}
if (s.length() == 0) {
binding.homeInput.setAdapter(null);
return;
}
// 延迟执行请求,避免频繁调用
pendingRunnable[0] = () -> {
try {
inputTips.requestInputtips(s.toString(), "全国");
} catch (AMapException e) {
e.printStackTrace();
Toast.makeText(requireContext(), "输入提示请求失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
};
handler.postDelayed(pendingRunnable[0], 600); // 防抖 600ms
}
@Override
public void afterTextChanged(Editable s) {}
});
}
private void handleSearchError(int rCode) {
String msg;
switch (rCode) {
case 12:
msg = "API Key 错误,请检查 AndroidManifest.xml";
break;
case 27:
msg = "网络连接失败";
break;
case 30:
msg = "SHA1 或包名未正确配置";
break;
case 33:
msg = "请求过于频繁,请稍后再试";
break;
default:
msg = "搜索失败,错误码: " + rCode;
break;
}
Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show();
}
@Override
public void onDestroyView() {
super.onDestroyView();
inputTips = null;
binding = null;
}
}
fragment_home.xml代码如下:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.home.HomeFragment"
android:fitsSystemWindows="true"
android:layout_marginTop="?attr/actionBarSize">
<!-- 🔵 垂直指南线:5%、50%、95% -->
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline_05"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.05" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline_50"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.50" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline_95"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.95" />
<!-- 🔍 输入框 -->
<AutoCompleteTextView
android:id="@+id/home_input"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="请输入需要查询的公交线路或站点"
android:textColorHint="#777777"
android:completionThreshold="1"
android:textColor="@color/black"
android:background="@drawable/rounded_edittext"
android:minHeight="48dp"
android:textSize="14sp"
android:padding="12dp"
app:layout_constraintTop_toTopOf="@id/guideline_05"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/home_search"
app:layout_constraintHorizontal_chainStyle="packed"
android:layout_marginStart="16dp"
android:layout_marginEnd="8dp" />
<!-- 🔎 搜索按钮 -->
<Button
android:id="@+id/home_search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="搜索"
app:layout_constraintTop_toTopOf="@id/home_input"
app:layout_constraintBottom_toBottomOf="@id/home_input"
app:layout_constraintStart_toEndOf="@id/home_input"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="16dp" />
<!-- 🚌 图片:居中偏上 -->
<ImageView
android:id="@+id/image_bus"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:src="@drawable/bus"
app:layout_constraintTop_toTopOf="@id/guideline_50"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintWidth_percent="0.6"
android:scaleType="fitCenter" />
<!-- ℹ️ 底部说明文字 -->
<TextView
android:id="@+id/text_home"
android:textColor="#777777"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="11sp"
app:layout_constraintTop_toTopOf="@id/guideline_95"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
SearchResultActivity代码如下:package com.example.bus;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.widget.Button;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.MapView;
import com.amap.api.maps.UiSettings;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.core.PoiItem;
import com.amap.api.services.poisearch.PoiResult;
import com.amap.api.services.poisearch.PoiSearch;
// 👇 已有导入保持不变
import com.amap.api.services.help.Inputtips;
import com.amap.api.services.help.Tip;
import android.text.TextWatcher;
import android.text.Editable;
import android.widget.ArrayAdapter;
import com.amap.api.services.core.AMapException;
import java.util.ArrayList;
import java.util.List;
public class SearchResultActivity extends AppCompatActivity implements PoiSearch.OnPoiSearchListener {
private Button searchBtn, goToBtn;
private RecyclerView resultListView;
private List<PoiItem> poiList = new ArrayList<>();
private ResultAdapter adapter;
private PoiSearch poiSearch;
// 地图相关
private MapView mapView;
private AMap aMap;
private Marker selectedMarker;
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1001;
// 👇 新增:用于输入提示
private Inputtips inputTips;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_result);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle("搜索地点");
}
initViews();
setupMap(savedInstanceState);
setupSearch();
// ✅ 在地图初始化完成后尝试开启蓝点(会自动请求权限)
enableMyLocationLayer();
}
private void initViews() {
searchBtn = findViewById(R.id.search_btn);
resultListView = findViewById(R.id.result_list);
goToBtn = findViewById(R.id.btn_go_to);
goToBtn.setEnabled(false);
// ✅ 新增调用:设置搜索建议功能
setupSearchSuggestion();
}
/**
* 设置搜索输入建议(自动补全)
*/
private void setupSearchSuggestion() {
try {
inputTips = new Inputtips(this, new Inputtips.InputtipsListener() {
@Override
public void onGetInputtips(List<Tip> tipList, int rCode) {
if (rCode == 1000 && tipList != null && !tipList.isEmpty()) {
String[] arr = new String[tipList.size()];
for (int i = 0; i < tipList.size(); i++) {
arr[i] = tipList.get(i).getName();
}
ArrayAdapter<String> adapter = new ArrayAdapter<>(
SearchResultActivity.this,
android.R.layout.simple_dropdown_item_1line,
arr
);
((android.widget.AutoCompleteTextView) findViewById(R.id.search_input))
.setAdapter(adapter);
} else {
((android.widget.AutoCompleteTextView) findViewById(R.id.search_input))
.setAdapter(null);
handleSearchError(rCode);
}
}
});
} catch (AMapException e) {
e.printStackTrace();
Toast.makeText(this, "输入提示初始化失败", Toast.LENGTH_SHORT).show();
}
android.widget.AutoCompleteTextView inputView = findViewById(R.id.search_input);
// 创建 Handler 用于防抖
Handler handler = new Handler(Looper.getMainLooper());
Runnable[] pendingRunnable = {null}; // 使用数组包装,使其可变
inputView.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// 清除上一次延迟任务
if (pendingRunnable[0] != null) {
handler.removeCallbacks(pendingRunnable[0]);
}
if (s.length() == 0) {
inputView.setAdapter(null);
return;
}
// 构造新任务:延迟执行搜索建议请求
pendingRunnable[0] = () -> {
try {
inputTips.requestInputtips(s.toString(), "全国");
} catch (AMapException e) {
e.printStackTrace();
Toast.makeText(SearchResultActivity.this, "提示请求失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
};
handler.postDelayed(pendingRunnable[0], 600); // 防抖 600ms
}
@Override
public void afterTextChanged(Editable s) {}
});
}
/**
* 统一处理搜索错误码提示
*/
private void handleSearchError(int rCode) {
String msg;
switch (rCode) {
case 12:
msg = "API Key 错误,请检查 AndroidManifest.xml";
break;
case 27:
msg = "网络连接失败";
break;
case 30:
msg = "SHA1 或包名未正确配置";
break;
case 33:
msg = "请求过于频繁,请稍后再试";
break;
default:
msg = "搜索失败,错误码: " + rCode;
break;
}
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
private void setupMap(Bundle savedInstanceState) {
mapView = findViewById(R.id.map_view);
mapView.onCreate(savedInstanceState);
if (aMap == null) {
aMap = mapView.getMap();
UiSettings uiSettings = aMap.getUiSettings();
uiSettings.setZoomControlsEnabled(true);
uiSettings.setCompassEnabled(true);
uiSettings.setScrollGesturesEnabled(true);
// 设置地图点击事件:添加选中位置标记
aMap.setOnMapClickListener(latLng -> {
if (selectedMarker != null) {
selectedMarker.remove();
}
selectedMarker = aMap.addMarker(new MarkerOptions()
.position(latLng)
.title("选中位置"));
goToBtn.setEnabled(true);
});
// 默认视角为中国中心
aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(39.909186, 116.397411), 10f));
}
}
/**
* 开启地图蓝点(我的位置)
* 如果已有权限则直接启用,否则请求权限
* ✅ 修改:使用 MyLocationStyle 控制行为,避免自动跳转
*/
private void enableMyLocationLayer() {
if (aMap == null) return;
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
try {
// 👇 新增:自定义定位样式,只定位一次,不持续追踪
MyLocationStyle myLocationStyle = new MyLocationStyle();
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE); // 关键修改!
aMap.setMyLocationStyle(myLocationStyle); // 应用样式
aMap.setMyLocationEnabled(true); // 再开启图层
Toast.makeText(this, "已开启定位(单次居中)", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "无法开启定位图层", Toast.LENGTH_SHORT).show();
}
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
LOCATION_PERMISSION_REQUEST_CODE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (aMap != null) {
// 👇 同样需要重新设置样式
MyLocationStyle myLocationStyle = new MyLocationStyle();
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE);
aMap.setMyLocationStyle(myLocationStyle);
aMap.setMyLocationEnabled(true);
Toast.makeText(this, "已成功开启定位功能", Toast.LENGTH_SHORT).show();
}
} else {
boolean hasCoarse = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
== PackageManager.PERMISSION_GRANTED;
if (hasCoarse) {
Toast.makeText(this, "建议开启精确位置以获得更准确定位", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "定位权限被拒绝,部分功能受限", Toast.LENGTH_LONG).show();
}
}
}
}
private void setupSearch() {
String keyword = getIntent().getStringExtra("keyword");
if (keyword != null && !keyword.isEmpty()) {
performSearch(keyword);
}
searchBtn.setOnClickListener(v -> {
String text = ((android.widget.EditText) findViewById(R.id.search_input)).getText().toString().trim();
if (!text.isEmpty()) {
performSearch(text);
} else {
Toast.makeText(this, "请输入关键词", Toast.LENGTH_SHORT).show();
}
});
goToBtn.setOnClickListener(v -> {
LatLonPoint targetPoint = null;
String title = "选中位置";
if (selectedMarker != null) {
LatLng pos = selectedMarker.getPosition();
targetPoint = new LatLonPoint(pos.latitude, pos.longitude);
title = selectedMarker.getTitle();
} else if (!poiList.isEmpty()) {
PoiItem item = poiList.get(0);
targetPoint = item.getLatLonPoint();
title = item.getTitle();
}
if (targetPoint == null) {
Toast.makeText(this, "暂无目标位置", Toast.LENGTH_SHORT).show();
return;
}
Intent intent = new Intent(this, RoutePlanActivity.class);
intent.putExtra(RoutePlanActivity.EXTRA_SOURCE, RoutePlanActivity.SOURCE_FROM_HOME_SEARCH);
intent.putExtra("target_lat", targetPoint.getLatitude());
intent.putExtra("target_lng", targetPoint.getLongitude());
intent.putExtra("target_title", title);
startActivity(intent);
});
}
private void performSearch(String keyword) {
PoiSearch.Query query = isLikelyBusStop(keyword) ?
new PoiSearch.Query(keyword, "15", "全国") :
new PoiSearch.Query(keyword, "", "全国");
query.setPageSize(20);
query.setPageNum(0);
try {
poiSearch = new PoiSearch(this, query);
poiSearch.setOnPoiSearchListener(this);
poiSearch.searchPOIAsyn();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "搜索启动失败", Toast.LENGTH_SHORT).show();
}
}
private boolean isLikelyBusStop(String keyword) {
return keyword.contains("公交") || keyword.contains("地铁") ||
keyword.contains("BRT") || keyword.endsWith("站") || keyword.endsWith("场");
}
@Override
public void onPoiSearched(PoiResult result, int rCode) {
if (rCode == 1000 && result != null && result.getPois() != null) {
poiList.clear();
poiList.addAll(result.getPois());
if (adapter == null) {
adapter = new ResultAdapter(poiList, item -> {
if (selectedMarker != null) {
selectedMarker.remove();
}
LatLng latLng = new LatLng(item.getLatLonPoint().getLatitude(), item.getLatLonPoint().getLongitude());
selectedMarker = aMap.addMarker(new MarkerOptions().position(latLng).title(item.getTitle()));
aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 14f));
goToBtn.setEnabled(true);
});
resultListView.setLayoutManager(new LinearLayoutManager(this));
resultListView.setAdapter(adapter);
} else {
adapter.notifyDataSetChanged();
}
goToBtn.setEnabled(!poiList.isEmpty());
} else {
String msg = rCode == 17 ? "高德Key校验失败" : "搜索失败: 错误码=" + rCode;
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
}
@Override
public void onPoiItemSearched(PoiItem item, int rCode) {
// 不处理详情查询
}
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
if (aMap != null) {
aMap.setMyLocationEnabled(false); // 关闭蓝点
}
if (poiSearch != null) {
poiSearch.setOnPoiSearchListener(null);
}
mapView = null;
aMap = null;
poiSearch = null;
// ✅ 安全清理 inputTips:只置空
inputTips = null;
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
@Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
}
activity_search_result.xml代码如下:<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:layout_marginTop="?attr/actionBarSize">
<!-- ====== 指南线:用于精确百分比定位 ====== -->
<!-- 地图底部 -->
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline_60"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.60" />
<!-- 结果列表顶部留白结束位置 -->
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline_65"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.65" />
<!-- 按钮顶部位置 -->
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline_90"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.90" />
<!-- 🔍 输入框 -->
<AutoCompleteTextView
android:id="@+id/search_input"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="请输入需要查询的公交线路或站点"
android:textColorHint="#777777"
android:textColor="@color/black"
android:background="@drawable/rounded_edittext"
android:minHeight="48dp"
android:textSize="14sp"
android:padding="12dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/search_btn"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginStart="16dp"
android:layout_marginEnd="8dp" />
<!-- 🔎 搜索按钮 -->
<Button
android:id="@+id/search_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="搜索"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/search_input"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="16dp" />
<!-- 🗺️ 地图视图 -->
<com.amap.api.maps.MapView
android:id="@+id/map_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="20dp"
app:layout_constraintTop_toBottomOf="@id/search_input"
app:layout_constraintBottom_toTopOf="@id/guideline_60"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<!-- 🔲 固定高度容器:包裹 RecyclerView -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/container_result_list"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="@id/guideline_65"
app:layout_constraintBottom_toTopOf="@id/guideline_90"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginHorizontal="16dp">
<!-- 🔽 RecyclerView:内部可滚动 -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/result_list"
android:layout_width="0dp"
android:layout_height="0dp"
android:nestedScrollingEnabled="false"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:scrollbars="vertical"
android:scrollbarSize="6dp"
android:scrollbarThumbVertical="@drawable/custom_scrollbar_thumb"
android:scrollbarTrackVertical="@drawable/custom_scrollbar_track"/>
<!-- 空状态提示 -->
<TextView
android:id="@+id/empty_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="暂无搜索结果"
android:textColorHint="#777777"
android:textColor="@color/black"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- “到这去”按钮 -->
<Button
android:id="@+id/btn_go_to"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="到这去"
android:layout_margin="16dp"
app:layout_constraintTop_toTopOf="@id/guideline_90"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<!-- 🌀 加载进度条 -->
<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:elevation="10dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity代码如下:package com.example.bus;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.example.bus.databinding.ActivityMainBinding;
import com.google.android.material.bottomnavigation.BottomNavigationView;
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private static final String SAVED_NAV_ID = "saved_nav_id";
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1001;
// 删除 shouldNavigateToMap 标志位(它是罪魁祸首)
// 改为传入 Runnable 控制后续行为
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
BottomNavigationView navView = findViewById(R.id.nav_view);
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home,
R.id.navigation_map,
R.id.navigation_settings)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navView, navController);
// 设置 BottomNavigationView 的监听器
navView.setOnItemSelectedListener(item -> {
int itemId = item.getItemId();
if (itemId == R.id.navigation_map) {
// 只有点击地图 tab 才走权限 + 跳转逻辑
ensureFineLocationPermission(() -> {
if (navController.getCurrentDestination().getId() != R.id.navigation_map) {
navController.navigate(R.id.navigation_map);
}
});
} else {
navController.navigate(itemId);
}
return true;
});
if (savedInstanceState != null) {
int savedId = savedInstanceState.getInt(SAVED_NAV_ID, R.id.navigation_home);
navView.setSelectedItemId(savedId);
}
}
/**
* 统一权限请求方法,权限通过后执行 onGranted
*/
public void ensureFineLocationPermission(Runnable onGranted) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
onGranted.run();
} else {
requestLocationPermission(onGranted);
}
}
private void requestLocationPermission(Runnable onGranted) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
new AlertDialog.Builder(this)
.setTitle("需要精确定位权限")
.setMessage("为了提供更好的服务,我们需要获取您的精确位置。\n否则将无法使用地图相关功能。\n\n请务必选择【允许】或【仅限这一次】。")
.setPositiveButton("去允许", (d, w) -> startRequestPermission(onGranted))
.setNegativeButton("取消", null)
.show();
} else {
startRequestPermission(onGranted);
}
}
private void startRequestPermission(Runnable onGranted) {
// 使用成员变量保存回调
this.pendingRunnable = onGranted;
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
LOCATION_PERMISSION_REQUEST_CODE);
}
private Runnable pendingRunnable;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) {
boolean granted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
if (granted) {
Toast.makeText(this, "已获得精确定位权限", Toast.LENGTH_SHORT).show();
// 执行传进来的任务(可能是跳转 SearchResultActivity 或进入 MapFragment)
if (pendingRunnable != null) {
pendingRunnable.run();
pendingRunnable = null;
}
} else {
boolean hasCoarse = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
== PackageManager.PERMISSION_GRANTED;
if (hasCoarse) {
new AlertDialog.Builder(this)
.setTitle("需要精确位置")
.setMessage("检测到您使用的是【大致位置】,这会导致地图功能无法正常使用。\n\n" +
"请在设置中将定位权限修改为【精确位置】。")
.setPositiveButton("去设置", (d, w) -> openAppSettings())
.setNegativeButton("取消", null)
.show();
} else {
Toast.makeText(this, "定位权限未授予,部分功能受限", Toast.LENGTH_LONG).show();
}
pendingRunnable = null; // 清理
}
}
}
private void openAppSettings() {
Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
BottomNavigationView navView = findViewById(R.id.nav_view);
outState.putInt(SAVED_NAV_ID, navView.getSelectedItemId());
}
}
现在就是说,通过HomeFragment的搜索框会进入SearchResultActivity显示结果,但是在SearchResultActivity当中也有个搜索框,能不能做到在HomeFragment的搜索框点击搜索后数据也显示在SearchResultActivity的搜索框上,而不是让SearchResultActivity的搜索框内容是空的?其次,无论是在HomeFragment中点击搜索按钮还是在SearchResultActivity中点击搜索后,我想在SearchResultActivity中默认选中第一条item,如果可以的话请为代码做出最小量的修改,仅修改这部分内容,其它已有内容不做改变,为我提供修改后的完整代码
最新发布