试图从父母的方法访问Fragment的界面

时间:2015-01-29 13:34:22

标签: java android google-maps android-fragments

与Google的“我的跟踪”应用程序的工作方式类似,我有一个地图片段标签和统计信息标签。因此,我需要从父活动访问LocationListener等方法。用户的路线将在按下按钮时记录(来自父活动的布局。 如何从主活动中的方法访问这两个片段,以执行更新地图的UI(跟随用户)和使用运行的统计数据(例如用户的行进距离)更新Statistics片段?

NewRouteActivity.java

public class NewRouteActivity extends FragmentActivity implements
        ConnectionCallbacks, OnConnectionFailedListener, LocationListener {

    /**
     * The {@link android.support.v4.view.PagerAdapter} that will provide
     * fragments for each of the sections. We use a
     * {@link FragmentPagerAdapter} derivative, which will keep every
     * loaded fragment in memory. If this becomes too memory intensive, it
     * may be best to switch to a
     * {@link android.support.v4.app.FragmentStatePagerAdapter}.
     */
    SectionsPagerAdapter mSectionsPagerAdapter;

    /**
     * The {@link ViewPager} that will host the section contents.
     */
    ViewPager mViewPager;

    public static FragmentManager fragmentManager;

    /**
     * JSONParser that will parse data to send to server
     */
    JSONParser jsonParser = new JSONParser();
    Gson gson = new Gson();

    /**
     * Static Variables
     */
    protected static final String TAG_CONTEXT = "NewRouteActivity";
    protected static final String TAG_DIALOG_SAVE_ROUTE = "Do you wish to save this route?";
    protected static final String TAG_DIALOG_YES = "OK";
    protected static final String TAG_DIALOG_NO = "No thanks";

    // Desired interval for location updates
    public static final long UPDATE_INTERVAL_MS = 1000;
    // Fastest rate for location updates
    public static final long FASTEST_UPDATE_INTERVAL_MS = UPDATE_INTERVAL_MS / 2;


    // Google Map
    protected GoogleMap mMap;
    // Entry point to Play Services
    protected GoogleApiClient mGoogleApiClient;
    // Stores parameters for requests to FusedLocationProviderApi
    protected LocationRequest mLocationRequest;
    // Represents a Geographical location
    protected Location mLocation;
    protected double mLatitude; // current latitude
    protected double mLongitude; // current longitude
    // Tracks status of location updates request
    protected Boolean mRequestingLocationUpdates;
    // Tracks whether route should be recorded or not
    protected Boolean mRecordRoute;

    // Stores user's geographical points
    protected List<LatLng> mLatLngs = new ArrayList<>();
    // Displays user's geographical points
    protected Polyline line;

    // Tracks distance covered
    protected float mDistance;
    protected float mTotalDistance;

    // Tracks time elapsed
    protected Long mStartTime; // (milliseconds)
    protected Long mEndTime;
    protected Long mTimeDifference;

    // Calendar to track date created
    protected static Calendar mCalendar = Calendar.getInstance();

    /**
     * User Model properties (as needed)
     */
    protected User user = new User();
    protected int mId;

    /**
     * Route Model Properties
     */
    protected Grade routeGrade;
    protected Terrain routeTerrain;
    protected List<Double> routeLats = new ArrayList<>();
    protected List<Double> routeLngs = new ArrayList<>();
    protected float routeDistance;
    protected Date dateCreated;

    /**
     * Results Model Properties
     */
    protected int routeId;
    protected int mExperience;
    protected float mMaxSpeed;
    // protected float routeDistance;
    protected float avgSpeed;
    protected Date mTime;
    // protected Date dateCreated;

    /**
     * UI Widgets
     */
    // Buttons
    protected ImageView mButtonRecord;
    protected ImageView mButtonPause;
    protected ImageView mButtonStop;
    // TextViews


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_new_route);
        final ActionBar actionBar = getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        actionBar.setDisplayShowHomeEnabled(false);
        actionBar.setDisplayShowTitleEnabled(false);
        fragmentManager = getSupportFragmentManager();

        // Locate UI Widgets
        mButtonRecord = (ImageView) findViewById(R.id.btnRecord);
        mButtonStop = (ImageView) findViewById(R.id.btnStop);

        // Set Location Updates status to false
        mRequestingLocationUpdates = false;
        mRecordRoute = false;
        mTotalDistance = 0;

        // Create the adapter that will return a fragment for each of the three
        // primary sections of the activity.
        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        // Create a tab listener that is called when the user changes tabs.
        ActionBar.TabListener tabListener = new ActionBar.TabListener() {

            @Override
            public void onTabSelected(ActionBar.Tab tab, android.app.FragmentTransaction ft) {
                mViewPager.setCurrentItem(tab.getPosition());
            }

            @Override
            public void onTabUnselected(ActionBar.Tab tab, android.app.FragmentTransaction ft) {

            }

            @Override
            public void onTabReselected(ActionBar.Tab tab, android.app.FragmentTransaction ft) {

            }
        };

        mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                getActionBar().setSelectedNavigationItem(position);
            }
        });

        // Add 2 tabs
        for(int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
            actionBar.addTab(actionBar
                    .newTab()
                    .setText(mSectionsPagerAdapter.getPageTitle(i))
                    .setTabListener(tabListener));
        }

        // Create Listeners for Record/Stop buttons
        mButtonRecord.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i(TAG_CONTEXT, "Start Recording...");
                mStartTime = System.currentTimeMillis(); // start timer
                startUpdatesButtonHandler();
            }
        });
        mButtonStop.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i(TAG_CONTEXT, "Stop recording.");
                mEndTime = System.currentTimeMillis(); // end timer
                stopUpdatesButtonHandler();
            }
        });

        buildGoogleApiClient();

    }


    /**
     * Build entry point params for Play Services
     */
    protected synchronized void buildGoogleApiClient() {
        Log.i(TAG_CONTEXT, "Building GoogleApiClient...");
        mGoogleApiClient = new Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        createLocationRequest();
    }

    /**
     * Sets up location request boundaries
     */
    private void createLocationRequest() {
        mLocationRequest = new LocationRequest();

        // Sets desired interval for active location updates
        mLocationRequest.setInterval(UPDATE_INTERVAL_MS);

        // Sets fastest interval for location updates
        mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_MS);

        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

    /**
     * Handles the Start Updates button and requests start of location updates. Does nothing if
     * updates have already been requested.
     */
    private void startUpdatesButtonHandler() {
        if(!mRequestingLocationUpdates) {
            mRequestingLocationUpdates = true;
            setButtonsEnabledState();
            startLocationUpdates();
        }
    }

    /**
     * Handles the Stop Updates button, and requests removal of location updates. Does nothing if
     * updates were not previously requested.
     */
    public void stopUpdatesButtonHandler() {
        if (mRequestingLocationUpdates) {
            mRequestingLocationUpdates = false;
            setButtonsEnabledState();
            stopLocationUpdates();
        }
    }

    private void setButtonsEnabledState() {
        if (mRequestingLocationUpdates) {
            mButtonRecord.setEnabled(false);
            mButtonStop.setEnabled(true);
        } else {
            mButtonRecord.setEnabled(true);
            mButtonStop.setEnabled(false);
        }
    }

    /**
     * Removes location updates from the FusedLocationApi
     */
    private void stopLocationUpdates() {
        LocationServices.FusedLocationApi.
                removeLocationUpdates(mGoogleApiClient, this);
    }

    /**
     * Requests location updates from FusedLocationApi
     */
    protected void startLocationUpdates() {
        LocationServices.FusedLocationApi.requestLocationUpdates(
                mGoogleApiClient, mLocationRequest, this
        );
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_new_route, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onStart() {
        super.onStart();
        mGoogleApiClient.connect();
    }

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

        if(mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
            startLocationUpdates();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        // Stop location updates but don't disconnect the GoogleApiClient
        // stopLocationUpdates();
    }

    @Override
    protected void onStop() {
        super.onStop();
        /*
        if(mGoogleApiClient.isConnected()) {
            mGoogleApiClient.disconnect();
        }
        */
    }

    @Override
    public void onConnected(Bundle bundle) {
        Log.i(TAG_CONTEXT, "Connected to GoogleApiClient");

        if(mLocation == null) {
            mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        }

        // If user presses Start button before GoogleApiClient connects
        // set mRequestingLocationUpdates to true
        if(mRequestingLocationUpdates) {
            startLocationUpdates();
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
        // Connection to Play Services lost
        // Try to re-connect
        Log.i(TAG_CONTEXT, "Connection Suspended");
        mGoogleApiClient.connect();
    }

    @Override
    public void onLocationChanged(Location location) {
        mLocation = location;
        mLatitude = location.getLatitude();
        mLongitude = location.getLongitude();
        trackDistance();
        // trackSpeed();
        saveLocation();
        updateUI();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        stopLocationUpdates();
        Log.i(TAG_CONTEXT, "Connection failed: ConnectionResult.getErrorCode() = "
                + connectionResult.getErrorCode());
    }


    /**
     * Track total distance covered
     */
    private void trackDistance() {
        if(!mLatLngs.isEmpty()) {
            Location lastLocation = new Location("LastLocation");
            double x = mLatLngs.get(mLatLngs.size()-1).latitude; // previous latitude point in array
            double y = mLatLngs.get(mLatLngs.size()-1).longitude; // previous longitude point in array

            // set previous location parameters
            lastLocation.setLatitude(x);
            lastLocation.setLongitude(y);

            if(mLocation != lastLocation) {
                // find distance between two neighbouring points
                // add to total distance
                mDistance = lastLocation.distanceTo(mLocation); // metres
                mTotalDistance += mDistance; // total metres
                Log.i(TAG_CONTEXT, "Distance (m): " + mTotalDistance);
            }

        }
    }

    /**
     * Save location to array
     */
    private void saveLocation() {
        LatLng latLong = new LatLng(mLatitude, mLongitude);
        // save points to array
        Log.i(TAG_CONTEXT, "Saving points: " + latLong);
        mLatLngs.add(new LatLng(mLatitude, mLongitude));
        routeLats.add(mLatitude);
        routeLngs.add(mLongitude);
    }

    /**
     * Update UI in real-time
     * Follow User as they move
     * Show distance covered
     */
    private void updateUI() {
        LatLng latLng = new LatLng(mLatitude, mLongitude);
        // plot points on UI
        line = mMap.addPolyline(new PolylineOptions()
                .add(latLng)
                .width(6f)
                .color(Color.BLUE)
                .geodesic(true));

        // move camera to updated position on map
        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 16);
        mMap.animateCamera(cameraUpdate);

        /*
        if(mTotalDistance < 1000) {
            // display in metres
            mTextDistance.setText(String.format("%.1f (m)", mTotalDistance));
        }
        else {
            // display in kilometres
            mTextDistance.setText(String.format("%.2f (km)", mTotalDistance/1000));
        }
        */
    }


    /**
     * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
     * one of the sections/tabs/pages.
     */
    public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            // getItem is called to instantiate the fragment for the given page.
            // Return a PlaceholderFragment (defined as a static inner class below).
            switch (position) {
                case 0:
                    Fragment fragment = new MyMapFragment();
                    Bundle args = new Bundle();
                    fragment.setArguments(args);
                    return fragment;
                case 1:
                    return new StatisticsFragment();
            }
            return null;
        }

        @Override
        public int getCount() {
            // Show 2 total pages.
            return 2;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            Locale l = Locale.getDefault();
            switch (position) {
                default:
                    return getString(R.string.title_map).toUpperCase(l);
                case 1:
                    return getString(R.string.title_statistics).toUpperCase(l);
            }
        }
    }

    /**
     * A placeholder fragment containing map view.
     */
    public static class MyMapFragment extends Fragment {

        private GoogleMap mMap;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            initMap();
        }

        @Override
        public View onCreateView(LayoutInflater inflater,
                                 ViewGroup container, Bundle savedInstanceState) {
            // The last two arguments ensure LayoutParams are inflated
            // properly.
            View rootView = inflater.inflate(
                    R.layout.fragment_map, container, false);
            // Bundle args = getArguments();

            return rootView;
        }

        private GoogleMap initMap() {
            if(mMap == null && getActivity() != null
                    && getActivity().getSupportFragmentManager() != null) {
                SupportMapFragment smf = (SupportMapFragment)getActivity().
                        getSupportFragmentManager().findFragmentById(R.id.map);
                if(smf != null) {
                    mMap = smf.getMap();
                    mMap.setMyLocationEnabled(true);
                }
            }
            return mMap;
        }

        @Override
        public void onDestroyView() {
            super.onDestroyView();
        }
    }

    public static class StatisticsFragment extends Fragment {
        // public static final String ARG_OBJECT = "object";

        @Override
        public View onCreateView(LayoutInflater inflater,
                                 ViewGroup container, Bundle savedInstanceState) {
            // The last two arguments ensure LayoutParams are inflated
            // properly.
            View rootView = inflater.inflate(
                    R.layout.fragment_statistics, container, false);
            // Bundle args = getArguments();
            /*((TextView) rootView.findViewById(android.R.id.text1)).setText(
                    Integer.toString(args.getInt(ARG_OBJECT)));*/
            return rootView;
        }
    }
}

activity_new_route.xml

<RelativeLayout 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_centerHorizontal="true"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools" android:id="@+id/pager"
        android:layout_width="match_parent" android:layout_height="450dip"
        tools:context="apex.prj300.ie.apex.app.NewRouteActivity"
        android:layout_above="@+id/buttons" />

    <LinearLayout
        android:background="@color/apex_black"
        android:id="@+id/buttons"
        android:layout_width="fill_parent"
        android:layout_height="130dip"
        android:gravity="center"
        android:orientation="horizontal"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true">

    <ImageView
        android:background="@null"
        android:id="@+id/btnRecord"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_margin="0dip"
        android:src="@drawable/button_record" />

    <TextView
        android:layout_width="30dip"
        android:layout_height="match_parent" />

    <ImageView
        android:background="@null"
        android:id="@+id/btnStop"
        android:layout_width="100dip"
        android:layout_height="100dip"
        android:layout_margin="4dip"
        android:src="@drawable/button_stop" />

    </LinearLayout>

</RelativeLayout>

fragment_map.xml

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="340dp" android:id="@+id/map"
    tools:context="apex.prj300.ie.apex.app.RecordActivity"
    android:name="com.google.android.gms.maps.SupportMapFragment" />

1 个答案:

答案 0 :(得分:0)

您正在尝试将数据从一个片段传递到另一个片段,但Android中的Interfragment通信通过接口进行。您必须有三个单独的活动(主要活动,FragmentActivity1和FragmentActivity2)。有关编码规范,请阅读following document。请看this video

您的代码中没有问题,它只是没有遵循正确的数据交互顺序。 This example以及this也有viewpager&amp;将为您提供更好的想法,为片段创建单独的活动并在片段之间进行通信。