Fragment.getActivity().getCurrentFocus = null解决办法

本文介绍了一种在FragmentActivity关闭时确保DialogFragment中的焦点控件键盘被正确关闭的方法。通过覆盖onPause方法并利用while循环多次尝试关闭软键盘,解决了因控件获取焦点而导致的问题。

需求场景:
FragmentActivity上显示DialogFragment,当关闭FragmentActivity的时候,如果DialogFragment有控件获得焦点并且键盘弹出,希望可以关掉键盘。

网上最多的办法:

InputMethodManager manager = (InputMethodManager) actv.getSystemService(Context.INPUT_METHOD_SERVICE);
manager.hideSoftInputFromWindow(actv.getCurrentFocus().getWindowToken(), 0);

因为获得焦点的控件在DialogFragment上,FragmentActivity上没有任何控件获取焦点,所以使用上面方法的时候,会发现抛出了空指针,因为actv.getCurrentFocus()的时候返回了null。
但是如果获取焦点的控件在FragmentActivity上,而不是在DialogFragment上,则上述方法成立。

可以采用如下方法:

@Override
public void onPause() {
    hideSoftInput(((ViewGroup) getView()).getFocusedChild());
    super.onPause();
}

void hideSoftInput(View view) {
    if (getActivity() == null || view == null) {
        return;
    }
    int times = 0;
    boolean isClosed = false;
    InputMethodManager manager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
    while (!isClosed && times <= 5) {
        times++;
        isClosed = manager.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }
}

可以通过((ViewGroup) getView()).getFocusedChild()这种方法获取DialogFragment的焦点控件,然后调用hideSoftInputFromWindow,为什么这里用了while循环,是担心怕一次关不掉(每次关键盘总觉得好多坑,就多关闭几次),这里还需要设置次数,不能超过五次,免得死循环,导致不能执行后面的语句。

同理。MapFragment代码如下:package com.example.bus.ui.map; import com.amap.api.maps.model.LatLng; import com.amap.api.services.core.LatLonPoint; import com.amap.api.services.core.AMapException; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; 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.services.poisearch.PoiResult; import com.amap.api.services.poisearch.PoiSearch; import com.example.bus.R; import com.example.bus.RoutePlanActivity; import com.example.bus.databinding.FragmentMapBinding; import com.amap.api.services.core.PoiItem; public class MapFragment extends Fragment { private FragmentMapBinding binding; private MapView mapView; private AMap aMap; @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { binding = FragmentMapBinding.inflate(inflater, container, false); View root = binding.getRoot(); mapView = root.findViewById(R.id.map_view); mapView.onCreate(savedInstanceState); initMap(); // 设置搜索按钮点击事件 binding.mapSearch.setOnClickListener(v -> { if (aMap == null) { Toast.makeText(requireContext(), "地图未加载完成", Toast.LENGTH_SHORT).show(); return; } String startKeyword = binding.mapInput1.getText().toString().trim(); // 起点 String endKeyword = binding.mapInput2.getText().toString().trim(); // 终点 if (startKeyword.isEmpty()) { Toast.makeText(requireContext(), "请输入起点", Toast.LENGTH_SHORT).show(); return; } if (endKeyword.isEmpty()) { Toast.makeText(requireContext(), "请输入终点", Toast.LENGTH_SHORT).show(); return; } // 🔁 第一步:搜索起点 PoiSearch.Query queryStart = new PoiSearch.Query(startKeyword, "", "全国"); queryStart.setPageSize(1); PoiSearch searchStart; try { searchStart = new PoiSearch(requireContext(), queryStart); } catch (AMapException e) { e.printStackTrace(); Toast.makeText(requireContext(), "POI搜索初始化失败,请检查参数", Toast.LENGTH_SHORT).show(); return; } searchStart.setOnPoiSearchListener(new PoiSearch.OnPoiSearchListener() { @Override public void onPoiSearched(PoiResult result, int rCode) { requireActivity().runOnUiThread(() -> { if (rCode == 1000 && result != null && !result.getPois().isEmpty()) { PoiItem startItem = result.getPois().get(0); LatLonPoint startPoint = startItem.getLatLonPoint(); Log.d("MapFragment", "✅ 起点解析成功: " + startItem.getTitle() + " -> " + startPoint.getLatitude() + "," + startPoint.getLongitude()); // ✅ 起点成功 → 搜索终点 searchEndAndLaunchRoute(endKeyword, startPoint); } else { handlePoiSearchError(rCode, "起点"); } }); } @Override public void onPoiItemSearched(PoiItem item, int rCode) {} }); searchStart.searchPOIAsyn(); }); return root; } // 搜索终点并启动路线规划 private void searchEndAndLaunchRoute(String endKeyword, LatLonPoint startPoint) { PoiSearch.Query queryEnd = new PoiSearch.Query(endKeyword, "", "全国"); queryEnd.setPageSize(1); PoiSearch searchEnd; try { searchEnd = new PoiSearch(requireContext(), queryEnd); } catch (AMapException e) { e.printStackTrace(); Toast.makeText(requireContext(), "终点搜索初始化失败", Toast.LENGTH_SHORT).show(); return; } searchEnd.setOnPoiSearchListener(new PoiSearch.OnPoiSearchListener() { @Override public void onPoiSearched(PoiResult result, int rCode) { requireActivity().runOnUiThread(() -> { if (rCode == 1000 && result != null && !result.getPois().isEmpty()) { PoiItem endItem = result.getPois().get(0); LatLonPoint targetPoint = endItem.getLatLonPoint(); Log.d("MapFragment", "✅ 终点解析成功: " + endItem.getTitle() + " -> " + targetPoint.getLatitude() + "," + targetPoint.getLongitude()); // 启动路线规划 Intent intent = new Intent(requireContext(), RoutePlanActivity.class); intent.putExtra(RoutePlanActivity.EXTRA_SOURCE, RoutePlanActivity.SOURCE_FROM_MAP_DIRECT); intent.putExtra("start_lat", startPoint.getLatitude()); intent.putExtra("start_lng", startPoint.getLongitude()); intent.putExtra("target_lat", targetPoint.getLatitude()); intent.putExtra("target_lng", targetPoint.getLongitude()); intent.putExtra("target_title", endItem.getTitle()); Log.d("MapFragment", "📤 已发送路线请求:从 '" + binding.mapInput1.getText().toString() + "' 到 '" + endItem.getTitle() + "'"); startActivity(intent); } else { handlePoiSearchError(rCode, "终点"); } }); } @Override public void onPoiItemSearched(PoiItem item, int rCode) {} }); searchEnd.searchPOIAsyn(); } private void handlePoiSearchError(int rCode, String type) { String errorMsg; switch (rCode) { case 1101: errorMsg = "网络连接异常"; break; case 1102: errorMsg = "网络响应超时"; break; case 1103: errorMsg = "解析异常"; break; case 1104: errorMsg = "请求参数非法"; break; case 1200: errorMsg = "API Key 不存在"; break; case 1202: errorMsg = "签名验证失败"; break; case 1206: errorMsg = "权限不足"; break; default: errorMsg = "未知错误: " + rCode; break; } Toast.makeText(requireContext(), type + "搜索失败: " + errorMsg, Toast.LENGTH_LONG).show(); } // 错误处理重载(兼容旧调用) private void handlePoiSearchError(int rCode) { handlePoiSearchError(rCode, "搜索"); } private void initMap() { if (aMap == null) { aMap = mapView.getMap(); UiSettings uiSettings = aMap.getUiSettings(); uiSettings.setZoomControlsEnabled(true); uiSettings.setCompassEnabled(true); uiSettings.setMyLocationButtonEnabled(false); } // 初始定位到中国中心(备用) LatLng defaultLoc = new LatLng(39.909186, 116.397411); aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(defaultLoc, 12f)); } @Override public void onResume() { super.onResume(); mapView.onResume(); if (aMap != null) { aMap.setMyLocationEnabled(true); } } @Override public void onPause() { super.onPause(); mapView.onPause(); } @Override public void onDestroyView() { super.onDestroyView(); if (mapView != null) { mapView.onDestroy(); } binding = null; } @Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); mapView.onSaveInstanceState(outState); } }我也需要这个功能,注意代码原有框架和原有功能不改变,只做最小量修改,跟刚刚一样,给我提供完整代码
最新发布
11-18
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值