通过单击 Android Map Fragment 中的地图来隐藏 UI 元素

Posted

技术标签:

【中文标题】通过单击 Android Map Fragment 中的地图来隐藏 UI 元素【英文标题】:Hide a UI element by clicking on the map in Android MapsFragment 【发布时间】:2021-07-25 17:12:15 【问题描述】:

我正在尝试在 android 中创建一个如下所示的 MapType 选择器:

我能够隐藏和取消隐藏小地图选择器 UI 元素。我还想在元素可见的情况下单击地图时关闭 UI 元素,但只要我添加一个 setOnMapClickListener()onCreateView 我收到以下错误:

错误

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.wherecownow, PID: 5856
    java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.gms.maps.GoogleMap.setOnMapClickListener(com.google.android.gms.maps.GoogleMap$OnMapClickListener)' on a null object reference
        at com.example.wherecownow.ui.home.MapsFragment.onCreateView(MapsFragment.java:210)
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
        at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2625)
        at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2577)
        at androidx.fragment.app.Fragment.performActivityCreated(Fragment.java:2722)
        at androidx.fragment.app.FragmentStateManager.activityCreated(FragmentStateManager.java:346)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1188)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
        at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2625)
        at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2577)
        at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:247)
        at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:541)
        at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:210)
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1435)
        at android.app.Activity.performStart(Activity.java:8024)
        at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3475)
        at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
        at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
        at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

我了解地图尚未创建,因此引发了 Nullpointer 错误。 我尝试将setOnMapClickListener() 放入onMapReady(),但从这里我无法引用findViewbyID

非常感谢您的帮助。我在这里搜索了每一个类似的问题,但没有一个能解决我的具体问题。

地图片段

public class MapsFragment extends Fragment 

    private GoogleMap mMap;

    private OnMapReadyCallback callback = new OnMapReadyCallback() 



        @Override
        public void onMapReady(GoogleMap googleMap) 
            LatLng sydney = new LatLng(-34, 151);
            googleMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
            googleMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));

            mMap = googleMap;
            mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);

        
    ;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
                             @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) 
        View view = inflater.inflate(R.layout.fragment_maps, container, false);

        ConstraintLayout mConstraintLayout= (ConstraintLayout) view.findViewById(R.id.map_type_selection);
        FloatingActionButton maptype_fab = (FloatingActionButton) view.findViewById(R.id.map_type_FAB);

        maptype_fab.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 

                mConstraintLayout.setVisibility(View.VISIBLE);
                maptype_fab.setVisibility(View.INVISIBLE);

                if(mMap.getMapType() == GoogleMap.MAP_TYPE_NORMAL) 
                    map_def_back.setVisibility(View.VISIBLE);
                    map_text_def.setTextColor(Color.BLUE);
                    Log.d(TAG, "maptype: normal ");

                 else if (mMap.getMapType() == GoogleMap.MAP_TYPE_HYBRID)
                    map_sat_back.setVisibility(View.VISIBLE);
                    map_text_sat.setTextColor(Color.BLUE);
                    Log.d(TAG, "maptype: satellite ");

                 else 
                    map_ter_back.setVisibility(View.VISIBLE);
                    map_text_ter.setTextColor(Color.BLUE);
                    Log.d(TAG, "maptype: terrain ");
                

            
        );

        mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() 
            @Override
            public void onMapClick(LatLng latLng) 

                mConstraintLayout.setVisibility(View.INVISIBLE);
                maptype_fab.setVisibility(View.VISIBLE);

            
        );
    

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) 
        super.onViewCreated(view, savedInstanceState);
        SupportMapFragment mapFragment =
                (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
        if (mapFragment != null) 
            mapFragment.getMapAsync(callback);
        
    

【问题讨论】:

【参考方案1】:

你的mMap.setOnMapClickListener()public View onCreateView()中被调用,但是mMap对象在onMapReady()被调用之后才能得到。所以你需要定义

ConstraintLayout mConstraintLayout;
FloatingActionButton maptype_fab;

作为MapsFragment 字段和移动代码:

mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() 
    @Override
    public void onMapClick(LatLng latLng) 
        mConstraintLayout.setVisibility(View.INVISIBLE);
        maptype_fab.setVisibility(View.VISIBLE);
    
);

public void onMapReady()

【讨论】:

以上是关于通过单击 Android Map Fragment 中的地图来隐藏 UI 元素的主要内容,如果未能解决你的问题,请参考以下文章

Android espresso 无法导航到其他 Fragment?

android Fragment下的listview 怎么样可以设置单击事件和长按事件

Android 在fragment中实现返回键单击提醒 双击退出

[Android Studio]如何从Fragment中嵌套的Recycleview启动一个Activity?

调用onclick时Android从Fragment更改Tab

Android - android.view.InflateException: Binary XML file line #8: Error inflating class fragment