Как обновить фрагмент при первом щелчке элемента карты? - PullRequest
0 голосов
/ 29 августа 2018

Я использую карты Google, и добавляю маркеры и кластеры. Я хочу, чтобы, когда пользователь щелкает по одному элементу или кластеру, информация, содержащаяся в объекте mapItem, должна отображаться в окне просмотра в нижней части экрана. Я могу получить информацию там, но только по второму щелчку значка карты. Есть ли способ сделать это обновление с первого клика?

Я смотрю на При первом щелчке Textview становится пустым, но при втором щелчке обновляется , но это решение не помогло мне, поскольку информация статична для самого фрагмента.

вот код моей основной деятельности:

 package com.example.cpj.maptesting;

import android.Manifest;
import android.app.AlertDialog;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.provider.Settings;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.places.Place;
import com.google.android.gms.location.places.ui.PlaceAutocompleteFragment;
import com.google.android.gms.location.places.ui.PlaceSelectionListener;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.maps.android.clustering.Cluster;
import com.google.maps.android.clustering.ClusterManager;
import java.util.ArrayList;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, LocationListener{

    private GoogleMap mMap;
    private static ClusterManager<MapItem> itemClusterManager;
    private static ArrayList<MapItem> listOfMarkers = new ArrayList<>();
    private ArrayList<MapItem> listForFragments = new ArrayList<>();
    private LocationManager locationManager;
    PlaceAutocompleteFragment placeAutocompleteFragment;
    Marker marker;
    private Context context;
    Location location;
    ViewPager mViewpager;
    InfoPageAdapter mPagerAdapter;
    int counter = 0;
    SparseArray<Fragment> fragments = new SparseArray<>();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        gpsPermission();
                // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        placeAutocompleteFragment = (PlaceAutocompleteFragment) getFragmentManager().findFragmentById(R.id.place_autocomplete);
        context = getApplicationContext();
        setUpPagers();

        if(!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
            alertBuilder();
        }
        placeAutocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
            @Override
            public void onPlaceSelected(Place place) {
                if(marker != null){
                    marker.remove();
                }
                    moveCamera(place.getLatLng());
                    marker = mMap.addMarker(new MarkerOptions()
                            .position(place.getLatLng())
                            .title("" + place.getAddress())
                            .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)));
            }

            @Override
            public void onError(Status status) {
                Log.d("Error status: " , status.toString());

            }
        });
    }

    /**
     * Manipulates the map once available.
     * This callback is triggered when the map is ready to be used.
     * This is where we can add markers or lines, add listeners or move the camera. In this case,
     * we just add a marker near Sydney, Australia.
     * If Google Play services is not installed on the device, the user will be prompted to install
     * it inside the SupportMapFragment. This method will only be triggered once the user has
     * installed Google Play services and returned to the app.
     */
    @Override
    public void onMapReady(final GoogleMap googleMap) {
        mMap = googleMap;
        setUpMap();

        if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED){
            mMap.setMyLocationEnabled(true);
            location = locationManager.getLastKnownLocation(locationManager.getBestProvider(new Criteria(), false));

            if(location != null){
                moveCamera(new LatLng(location.getLatitude(), location.getLongitude()));
            }
        }
        mMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
            @Override
            public void onCameraMove() {
                new dynamicallyAddMarkersTask().execute(mMap.getProjection().getVisibleRegion().latLngBounds);
            }
        });
        mMap.setOnMyLocationButtonClickListener(new GoogleMap.OnMyLocationButtonClickListener() {
            @Override
            public boolean onMyLocationButtonClick() {
                if(!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
                    alertBuilder();
                }
                return false;
            }
        });
            setUpClusters();
    }

    @Override
    public void onBackPressed() {
        if (mViewpager.getCurrentItem() == 0) {
            // If the user is currently looking at the first step, allow the system to handle the
            // Back button. This calls finish() on this activity and pops the back stack.
            super.onBackPressed();
        } else {
            // Otherwise, select the previous step.
            mViewpager.setCurrentItem(mViewpager.getCurrentItem() - 1);
        }
    }

    private void setUpClusters(){
        itemClusterManager = new ClusterManager<>(this, getMap());
        itemClusterManager.setAnimation(false);
        itemClusterManager.clearItems();
        listOfMarkers.clear();

        getMap().setOnCameraIdleListener(itemClusterManager);
        getMap().setOnMarkerClickListener(itemClusterManager);

        itemClusterManager.setOnClusterClickListener(new ClusterManager.OnClusterClickListener<MapItem>() {
            @Override
            public boolean onClusterClick(Cluster<MapItem> cluster) {
                setupClusterClicked(cluster);
                listForFragments.addAll(cluster.getItems());
                mViewpager.setCurrentItem(0);
                infoPageFragment ipf = (infoPageFragment) mPagerAdapter.getFragments(0);
                if(ipf != null){
                    ipf.setAdresse("Adresse: " + cluster.getItems().iterator().next().getTitle());
                    ipf.setNummer(1 + "/" + listForFragments.size());
                }

                return false;
            }
        });

        itemClusterManager.setOnClusterItemClickListener(new ClusterManager.OnClusterItemClickListener<MapItem>() {
            @Override
            public boolean onClusterItemClick(MapItem mapItem) {
                setupClusterItem();
                mViewpager.setCurrentItem(0);
                int position = mViewpager.getCurrentItem();

                infoPageFragment ipf = (infoPageFragment) mPagerAdapter.getFragments(position);
                if(ipf != null){
                    ipf.setAdresse("Adresse: " + mapItem.getTitle());
                    ipf.setNummer("");
                }

                return false;
            }
        });

        mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
            @Override
            public void onMapClick(LatLng latLng) {
                mViewpager.setVisibility(View.GONE);
            }
        });
        itemClusterManager.setRenderer(new CustomIcon(this, mMap, itemClusterManager));

        addMapItem(new MapItem(56.162939, 10.203727, "Nabo", "Holde"));
        addMapItem(new MapItem(56.162939, 10.203921, "Harald", "Plads"));
        addMapItem(new MapItem(56.162939, 10.203921, "Jensen", "Plads1"));
        addMapItem(new MapItem(56.162939, 10.203921, "Mogens", "Plads2"));
        addMapItem(new MapItem(56.162939, 10.203921, "Jørgensen", "Plads3"));
        addMapItem(new MapItem(56.162939, 10.203921, "Hansen", "Plads4"));

        mViewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}

            @Override
            public void onPageSelected(int position) {
                infoPageFragment ipf;

                for(MapItem mapItem : listForFragments){
                    ipf = (infoPageFragment) mPagerAdapter.getFragments(position);

                    mapItem = listForFragments.get(position);
                    int increment = position+1;

                    if(ipf != null){
                        String text = increment + "/" + listForFragments.size();
                        ipf.setAdresse("Adresse: " + mapItem.getTitle());
                        ipf.setNummer(text);
                    }
                }
            }
            @Override
            public void onPageScrollStateChanged(int state) {}
        });
        mPagerAdapter.notifyDataSetChanged();
    }

    @Override
    public void onLocationChanged(Location location) {
        LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
        moveCamera(latLng);
        locationManager.removeUpdates(this);
    }

    @Override
    public void onStatusChanged(String s, int i, Bundle bundle) {}

    @Override
    public void onProviderEnabled(String s) {}

    @Override
    public void onProviderDisabled(String s) {}

    private GoogleMap getMap() {
        return mMap;
    }

    private void setUpMap(){
        mMap.getUiSettings().setTiltGesturesEnabled(false);
        mMap.getUiSettings().setRotateGesturesEnabled(false);
        mMap.getUiSettings().setMapToolbarEnabled(false);
    }

    private void gpsPermission(){
        ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
    }

    private void alertBuilder(){
        final AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);

        alertDialog.setTitle("GPS setting");
        alertDialog.setMessage("This app needs gps, to find the closet parking spots! \nGo to settings?");

        alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                context.startActivity(intent);
            }
        });
        alertDialog.setNegativeButton("Not now", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {}
        });

        AlertDialog alert = alertDialog.create();
        alert.show();
    }

    private void moveCamera(LatLng latLng){
        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 16);
        mMap.animateCamera(cameraUpdate);
    }

    private void addMapItem(MapItem item){
        listOfMarkers.add(item);
        itemClusterManager.addItem(item);
    }

    private void setupClusterItem(){
        counter = 1;
        mViewpager.setVisibility(View.VISIBLE);
        mPagerAdapter.notifyDataSetChanged();
    }

    private void setupClusterClicked(Cluster<MapItem> cluster){
        listForFragments.clear();
        mViewpager.setVisibility(View.VISIBLE);
        counter = cluster.getSize();
        mPagerAdapter.notifyDataSetChanged();
    }

    private void setUpPagers(){
        mViewpager = findViewById(R.id.viewPager);
        mPagerAdapter = new InfoPageAdapter(getSupportFragmentManager());
        mViewpager.setAdapter(mPagerAdapter);
    }

    private static class dynamicallyAddMarkersTask extends AsyncTask<LatLngBounds, Void, Void> {

        @Override
        protected Void doInBackground(LatLngBounds... bounds) {
            itemClusterManager.clearItems();

            for(MapItem mapItem: listOfMarkers){
                if(bounds[0].contains(mapItem.getPosition())){
                    itemClusterManager.addItem(mapItem);
                }
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void result){
            itemClusterManager.cluster();
        }
    }

    private class InfoPageAdapter extends FragmentStatePagerAdapter{

        public InfoPageAdapter(android.support.v4.app.FragmentManager fm){
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {

            return new infoPageFragment();
        }

        @Override
        public int getItemPosition(Object obj){
            return POSITION_NONE;
        }

        @Override
        public Object instantiateItem(ViewGroup viewGroup, int position){
            Fragment fragment = (Fragment) super.instantiateItem(viewGroup, position);
            fragments.put(position, fragment);

            return fragment;
        }

        @Override
        public void destroyItem(ViewGroup viewGroup, int position, Object object){
            fragments.remove(position);
            super.destroyItem(viewGroup, position, object);
        }

        public Fragment getFragments(int position){
            return fragments.get(position);
        }

        @Override
        public int getCount() {
            return counter;
        }
    }
}

Это фрагмент

package com.example.cpj.maptesting;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class infoPageFragment extends Fragment {
    TextView adresse, nummer;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        View rootView = inflater.inflate(R.layout.info_page, container, false);
        adresse = rootView.findViewById(R.id.adresse);
        nummer = rootView.findViewById(R.id.nummer);
        return rootView;
    }

    public void setAdresse(String value){
        adresse.setText(value);
    }

    public void setNummer(String value){
        nummer.setText(value);
    }
}

activity_maps.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:weightSum="10"
    tools:context=".MapsActivity">

    <fragment
        android:id="@+id/place_autocomplete"
        android:name="com.google.android.gms.location.places.ui.PlaceAutocompleteFragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="633dp" />

    <LinearLayout
        android:id="@+id/pagerLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:visibility="visible"
        android:weightSum="1"
        >

        <android.support.v4.view.ViewPager
            android:id="@+id/viewPager"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:visibility="gone"/>
    </LinearLayout>

</LinearLayout>

и info_page.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/info_page"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView style="?android:textAppearanceMedium"
        android:padding="16dp"
        android:id="@+id/adresse"
        android:lineSpacingMultiplier="1.2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Adresse: "/>

    <TextView style="?android:textAppearanceMedium"
        android:id="@+id/nummer"
        android:padding="16dp"
        android:lineSpacingMultiplier="1.2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="right"
        />

</LinearLayout>

Я понимаю, что это как-то связано с жизненным циклом фрагмента, но я просто не могу понять, какой последний бит мне не хватает.

Спасибо за ответы.

пс. Пожалуйста, потерпите меня из-за неаккуратного кода. Я все еще новичок, когда дело доходит до разработки Android :).

1 Ответ

0 голосов
/ 29 августа 2018

Итак, как вы можете видеть в первый раз, когда ваш массив фрагментов пуст при попытке получить данные. Чувствуется после получения запроса. Вам нужно убедиться, что instantiateItem() закончил свое обновление, как isViewFromObject, и сделайте свое getFragments(int position) после него. Посмотрите на документы - https://developer.android.com/reference/androidx/viewpager/widget/PagerAdapter.html#isViewFromObject(android.view.View,%20java.lang.Object)

...