2017-03-06 44 views
1

我设法实现了TabLayout。其中一个标签是Google Maps Fragment。我想要求访问用户位置的权限,然后在当前位置放置一个标记。截至目前,该对话框不显示,我不知道为什么。谁能帮我?如何使用TabLayout在ViewPager中的Google Maps Fragment中获取当前位置

public class MapsFragment extends Fragment implements OnMapReadyCallback{ 

    GoogleMap mGoogleMap; 
    MapView mMapView; 
    View mView; 
    LocationManager locationManager; 
    static final int REQUEST_LOCATION = 1; 

    public MapsFragment() { 
     // Required empty public constructor 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     // Inflate the layout for this fragment 
     mView = inflater.inflate(R.layout.fragment_maps,container,false); 
     return mView; 
    } 

    @Override 
    public void onViewCreated(View view, Bundle savedInstanceState){ 
     super.onViewCreated(view, savedInstanceState); 
     mMapView = (MapView) mView.findViewById(R.id.googleMap); 
     if(mMapView != null){ 
      mMapView.onCreate(null); 
      mMapView.onResume(); 
      mMapView.getMapAsync(this); 

     } 
    } 

    @Override 
    public void onMapReady(GoogleMap googleMap) { 
     mGoogleMap = googleMap; 
     googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); 
     //Initialize Google PLay Services 
     if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ 
      if(ContextCompat.checkSelfPermission(getContext(), 
        Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED){ 
       //Location Permission is gratned 
       MapsInitializer.initialize(getContext()); 
       mGoogleMap.setMyLocationEnabled(true); 
      } 
     } 
     googleMap.addMarker(new MarkerOptions().position(new LatLng(36.652527, -121.797277)).title("CSUMB")); 
     CameraPosition CSUMB = CameraPosition.builder().target(new LatLng(36.6538, -121.797277)).zoom(16).bearing(0).tilt(45).build(); 
     googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(CSUMB)); 
    } 

    void getLocation(){ 
     locationManager = (LocationManager)getActivity() 
       .getSystemService(Context.LOCATION_SERVICE); 
     getLocation(); 
     if(ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) 
       != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getContext(), 
       Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){ 

     }else{ 
      Location location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); 
      if(location!= null){ 
       double latti = location.getLatitude(); 
       double longi = location.getLongitude(); 
       Toast.makeText(getActivity(),"Location is " + String.valueOf(latti) + ", " + String.valueOf(longi),Toast.LENGTH_LONG); 
       Log.e("Maps Fragment", "Location is: " + String.valueOf(latti) + ", " + String.valueOf(longi)); 
      } 
      else{ 
       Log.e("Maps fragment", "Unable to find current location."); 
      } 
     } 
    } 
    @Override 
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 
     super.onRequestPermissionsResult(requestCode, permissions, grantResults); 

     switch (requestCode) { 
      case REQUEST_LOCATION: 
       getLocation(); 
       break; 
     } 
    } 
    @Override 
    public void onResume() { 
     super.onResume(); 
     mMapView.onResume(); 
    } 

    @Override 
    public void onPause() { 
     super.onPause(); 
     mMapView.onPause(); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     mMapView.onDestroy(); 
    } 

    @Override 
    public void onLowMemory() { 
     super.onLowMemory(); 
     mMapView.onLowMemory(); 
    } 
} 

回答

1

这是非常接近我的other answer here,但是,这个问题的答案没有解释如何使用带有TabLayout一个ViewPager做到这一点。

首先,将其与另一个答案区分开的片段,您需要使用instantiateItem()重写来保留对FragmentPagerAdapter中当前片段的引用。

另外,请注意,活动中需要onRequestPermissionsResult()方法才能将用户的权限请求响应路由到片段。

以下是完整的活动代码:

public class MainActivity extends AppCompatActivity { 

    ViewPager viewPager; 
    PagerAdapter pagerAdapter; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(toolbar); 

     // Get the ViewPager and set it's PagerAdapter so that it can display items 
     viewPager = (ViewPager) findViewById(R.id.viewpager); 
     pagerAdapter = new PagerAdapter(getSupportFragmentManager(), MainActivity.this); 
     viewPager.setAdapter(pagerAdapter); 

     // Give the TabLayout the ViewPager 
     TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout); 
     tabLayout.setupWithViewPager(viewPager); 

     // Iterate over all tabs and set the custom view 
     for (int i = 0; i < tabLayout.getTabCount(); i++) { 
      TabLayout.Tab tab = tabLayout.getTabAt(i); 
      tab.setCustomView(pagerAdapter.getTabView(i)); 
     } 
    } 

    class PagerAdapter extends FragmentPagerAdapter { 

     String tabTitles[] = new String[] { "Tab One", "Tab Two", "Tab Three", }; 
     public Fragment[] fragments = new Fragment[tabTitles.length]; 
     Context context; 

     public PagerAdapter(FragmentManager fm, Context context) { 
      super(fm); 
      this.context = context; 
     } 

     @Override 
     public int getCount() { 
      return tabTitles.length; 
     } 

     @Override 
     public Fragment getItem(int position) { 

      switch (position) { 
       case 0: 
        return new MapFragment(); 
       case 1: 
        return new BlankFragment(); 
       case 2: 
        return new BlankFragment(); 
      } 

      return null; 
     } 

     @Override 
     public CharSequence getPageTitle(int position) { 
      // Generate title based on item position 
      return tabTitles[position]; 
     } 

     public View getTabView(int position) { 
      View tab = LayoutInflater.from(MainActivity.this).inflate(R.layout.custom_tab, null); 
      TextView tv = (TextView) tab.findViewById(R.id.custom_text); 
      tv.setText(tabTitles[position]); 
      return tab; 
     } 

     //This populates your Fragment reference array: 
     @Override 
     public Object instantiateItem(ViewGroup container, int position) { 
      Fragment createdFragment = (Fragment) super.instantiateItem(container, position); 
      fragments[position] = createdFragment; 
      return createdFragment; 
     } 
    } 

    @Override 
    public void onRequestPermissionsResult(int requestCode, 
              String permissions[], int[] grantResults) { 
     if (requestCode == MapFragment.MY_PERMISSIONS_REQUEST_LOCATION){ 
      MapFragment mapFragment = (MapFragment) pagerAdapter.fragments[0]; 
      if (mapFragment != null) { 
       mapFragment.onRequestPermissionsResult(requestCode, permissions, grantResults); 
      } 
     } 
     else { 
      super.onRequestPermissionsResult(requestCode, permissions, grantResults); 
     } 
    } 
} 

activity_main.xml中:

<?xml version="1.0" encoding="utf-8"?> 
<android.support.design.widget.CoordinatorLayout 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" 
    android:fitsSystemWindows="true" 
    tools:context=".MainActivity"> 

    <android.support.design.widget.AppBarLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:theme="@style/AppTheme.AppBarOverlay" 
     android:elevation="6dp"> 

     <android.support.v7.widget.Toolbar 
      android:id="@+id/toolbar" 
      android:layout_width="match_parent" 
      android:layout_height="?attr/actionBarSize" 
      android:background="?attr/colorPrimary" 
      android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" 
      app:popupTheme="@style/ThemeOverlay.AppCompat.Light" 
      android:elevation="0dp" /> 

     <android.support.design.widget.TabLayout 
      android:id="@+id/tab_layout" 
      app:tabMode="fixed" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:layout_below="@+id/toolbar" 
      android:background="?attr/colorPrimary" 
      android:elevation="0dp" 
      app:tabTextColor="#d3d3d3" 
      app:tabSelectedTextColor="#ffffff" 
      app:tabIndicatorColor="#ff00ff" 
      android:minHeight="?attr/actionBarSize" 
      /> 

    </android.support.design.widget.AppBarLayout> 

    <android.support.v4.view.ViewPager 
     android:id="@+id/viewpager" 
     android:layout_width="match_parent" 
     android:layout_height="fill_parent" 
     app:layout_behavior="@string/appbar_scrolling_view_behavior" 
     /> 

</android.support.design.widget.CoordinatorLayout> 

custom_tab.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" android:layout_width="match_parent" 
    android:layout_height="match_parent"> 
    <TextView 
     android:id="@+id/custom_text" 
     android:layout_width="wrap_content" 
     android:layout_height="match_parent" 
     android:background="?attr/selectableItemBackground" 
     android:gravity="center" 
     android:textSize="16dip" 
     android:textColor="#ffffff" 
     android:maxLines="1" 
     /> 
</LinearLayout> 

对于地图碎片,本质上是相同的代码使用其他答案:

public class MapFragment extends SupportMapFragment 
     implements OnMapReadyCallback, 
     GoogleApiClient.ConnectionCallbacks, 
     GoogleApiClient.OnConnectionFailedListener, 
     LocationListener { 

    GoogleMap mGoogleMap; 
    LocationRequest mLocationRequest; 
    GoogleApiClient mGoogleApiClient; 
    Location mLastLocation; 
    Marker mCurrLocationMarker; 

    @Override 
    public void onResume() { 
     super.onResume(); 

     setUpMapIfNeeded(); 
    } 

    private void setUpMapIfNeeded() { 

     if (mGoogleMap == null) { 
      getMapAsync(this); 
     } 
    } 
    @Override 
    public void onPause() { 
     super.onPause(); 

     //stop location updates when Activity is no longer active 
     if (mGoogleApiClient != null) { 
      LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); 
     } 
    } 

    @Override 
    public void onMapReady(GoogleMap googleMap) 
    { 
     mGoogleMap=googleMap; 
     mGoogleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID); 

     //Initialize Google Play Services 
     if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
      if (ContextCompat.checkSelfPermission(getActivity(), 
        Manifest.permission.ACCESS_FINE_LOCATION) 
        == PackageManager.PERMISSION_GRANTED) { 
       //Location Permission already granted 
       buildGoogleApiClient(); 
       mGoogleMap.setMyLocationEnabled(true); 
      } else { 
       //Request Location Permission 
       checkLocationPermission(); 
      } 
     } 
     else { 
      buildGoogleApiClient(); 
      mGoogleMap.setMyLocationEnabled(true); 
     } 
    } 

    protected synchronized void buildGoogleApiClient() { 
     mGoogleApiClient = new GoogleApiClient.Builder(getActivity()) 
       .addConnectionCallbacks(this) 
       .addOnConnectionFailedListener(this) 
       .addApi(LocationServices.API) 
       .build(); 
     mGoogleApiClient.connect(); 
    } 

    @Override 
    public void onConnected(Bundle bundle) { 
     mLocationRequest = new LocationRequest(); 
     mLocationRequest.setInterval(1000); 
     mLocationRequest.setFastestInterval(1000); 
     mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); 
     if (ContextCompat.checkSelfPermission(getActivity(), 
       Manifest.permission.ACCESS_FINE_LOCATION) 
       == PackageManager.PERMISSION_GRANTED) { 
      LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); 
     } 
    } 

    @Override 
    public void onConnectionSuspended(int i) {} 

    @Override 
    public void onConnectionFailed(ConnectionResult connectionResult) {} 

    @Override 
    public void onLocationChanged(Location location) 
    { 
     mLastLocation = location; 
     if (mCurrLocationMarker != null) { 
      mCurrLocationMarker.remove(); 
     } 

     //Place current location marker 
     LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); 
     MarkerOptions markerOptions = new MarkerOptions(); 
     markerOptions.position(latLng); 
     markerOptions.title("Current Position"); 
     markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)); 
     mCurrLocationMarker = mGoogleMap.addMarker(markerOptions); 

     //move map camera 
     mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng)); 
     mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(11)); 

     //optionally, stop location updates if only current location is needed 
     if (mGoogleApiClient != null) { 
      LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); 
     } 
    } 

    public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99; 
    private void checkLocationPermission() { 
     if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) 
       != PackageManager.PERMISSION_GRANTED) { 

      // Should we show an explanation? 
      if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), 
        Manifest.permission.ACCESS_FINE_LOCATION)) { 

       // Show an explanation to the user *asynchronously* -- don't block 
       // this thread waiting for the user's response! After the user 
       // sees the explanation, try again to request the permission. 
       new AlertDialog.Builder(getActivity()) 
         .setTitle("Location Permission Needed") 
         .setMessage("This app needs the Location permission, please accept to use location functionality") 
         .setPositiveButton("OK", new DialogInterface.OnClickListener() { 
          @Override 
          public void onClick(DialogInterface dialogInterface, int i) { 
           //Prompt the user once explanation has been shown 
           ActivityCompat.requestPermissions(getActivity(), 
             new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 
             MY_PERMISSIONS_REQUEST_LOCATION); 
          } 
         }) 
         .create() 
         .show(); 


      } else { 
       // No explanation needed, we can request the permission. 
       ActivityCompat.requestPermissions(getActivity(), 
         new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 
         MY_PERMISSIONS_REQUEST_LOCATION); 
      } 
     } 
    } 

    @Override 
    public void onRequestPermissionsResult(int requestCode, 
              String permissions[], int[] grantResults) { 
     switch (requestCode) { 
      case MY_PERMISSIONS_REQUEST_LOCATION: { 
       // If request is cancelled, the result arrays are empty. 
       if (grantResults.length > 0 
         && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 

        // permission was granted, yay! Do the 
        // location-related task you need to do. 
        if (ContextCompat.checkSelfPermission(getActivity(), 
          Manifest.permission.ACCESS_FINE_LOCATION) 
          == PackageManager.PERMISSION_GRANTED) { 

         if (mGoogleApiClient == null) { 
          buildGoogleApiClient(); 
         } 
         mGoogleMap.setMyLocationEnabled(true); 
        } 

       } else { 

        // permission denied, boo! Disable the 
        // functionality that depends on this permission. 
        Toast.makeText(getActivity(), "permission denied", Toast.LENGTH_LONG).show(); 
       } 
       return; 
      } 

      // other 'case' lines to check for other 
      // permissions this app might request 
     } 
    } 

} 

结果

首先,位置的权限提示:

enter image description here

一旦用户接受运行时的权限,显示用户的当前位置:

enter image description here

+0

你能解释为什么我们需要一个片段引用ce阵列? – TheLearner

+0

@TheLearner通过调用'mapFragment.onRequestPermissionsResult()',将用户的权限选择从Activity下移到Fragment,这是必需的。请记住,ViewPager会在用户滑过时根据需要创建并重新创建碎片,并且默认情况下它将保持当前碎片以及任何一方的碎片存活。因此,为了获得对当前活动片段的引用,需要'instantiateItem()'覆盖。 –

+0

谢谢你的解释。我得到一个错误,出于某种原因:PagerAdapter.getTabView(int)'在空对象引用 在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2947) – TheLearner

相关问题