使用带有错误叠加问题的Umano / SlidingUpPanel

时间:2015-12-01 08:35:48

标签: android android-activity google-maps-android-api-2 android-maps-v2

我在我的应用程序中使用Umano / SlidingUpPanel lib,其中Map是主要内容。面板在地图上向上滑动。我将叠加属性设置为,因为我希望当面板上滑时主要内容向上移动(如WhatsApp聊天窗口)

  

我面临的问题是:我的主要内容即地图正在震动或可能   每次面板上下滑动时都要重新调整大小。

请参阅此链接以了解有关问题的更多信息:

https://www.dropbox.com/s/imjlso12xarzf57/Video%2001-12-15%2C%2012%2049%2058%20PM.mov?dl=0

  

当面板上下滑动时,地图会发抖。

activity_main:

<com.sothree.slidinguppanel.SlidingUpPanelLayout
    xmlns:sothree="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/sliding_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="bottom"
    sothree:umanoFadeColor="@android:color/transparent"
    sothree:umanoOverlay = "false"
    sothree:umanoDragView="@+id/dragView">


    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

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

</FrameLayout>
    <include layout="@layout/sliding_fragment_layout"
        android:background="#ffffff"
        android:id="@+id/dragView"/>
    <!--<FrameLayout-->
            <!--android:id="@+id/list_fragment_container"-->
            <!--android:layout_width="match_parent"-->
            <!--android:layout_height="match_parent"/>-->

</com.sothree.slidinguppanel.SlidingUpPanelLayout>   

Sliding_fragment_layout:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout
    android:id="@+id/verified"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="60dp"
    android:paddingLeft="10dp"
    android:background="#FFFF"
    android:paddingRight="10dp"
    android:paddingTop="10dp"
    xmlns:android="http://schemas.android.com/apk/res/android">
                <!--android:descendantFocusability="beforeDescendants"-->
                <!--android:focusableInTouchMode="true"-->

                <TableRow
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="1dp"
                    android:weightSum="1">

                        <TextView
                            android:layout_width="0dp"
                            android:layout_height="wrap_content"
                            android:id="@+id/employer_textView_id"
                            android:layout_weight=".4"
                            android:padding="5dp"
                            android:textSize="15sp"
                            android:textColor="@android:color/black"/>




                </TableRow>

                <TableRow
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="0.5dp"
                    android:weightSum="1">

                        <TextView
                            android:layout_width="100dp"
                            android:layout_height="wrap_content"
                            android:padding="2dp"
                            android:textSize="15sp"
                            android:layout_weight="1"
                            android:gravity="fill_horizontal"
                            android:id="@+id/address_textView_id"
                            android:textColor="@android:color/black"/>

                </TableRow>
                <View
                    android:layout_width="fill_parent"
                    android:layout_height="1dp"
                    android:background="#c0c0c0"/>

               <TextView
                   android:layout_width="match_parent"
                   android:layout_height="match_parent"
                   android:text="Hello"
                   android:id="@+id/text"/>
        </TableLayout>

MainActivity.java

public class MainActivity extends FragmentActivity implements LocationListener {

    private static final String LIST_FRAGMENT_TAG = "list_fragment";
    private static final String TAG = "DemoActivity";

    GoogleMap googleMap;
    double currentLat , currentLon;
    LocationManager locationManager;
    Location mlocation;
    double latitude;
    double longitude;
    LatLng latLng,points;
    Boolean flag = false;
    String mLastUpdateTime;
    CameraPosition INIT;
    private SlidingUpPanelLayout mLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (!isGooglePlayServiceAvailable()) {
            finish();
        }
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);


        googleMap = mapFragment.getMap();
        googleMap.setMyLocationEnabled(true);
        googleMap.getUiSettings().setCompassEnabled(false);

        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);


        Criteria criteria = new Criteria();
        String bestProvider = locationManager.getBestProvider(criteria, true);
        mlocation = locationManager.getLastKnownLocation(bestProvider);
        if (mlocation != null) {
            onLocationChanged(mlocation);
        }
        locationManager.requestLocationUpdates(bestProvider, 20000, 0, this);

        /*SlidingPanelUpLayout*/
        mLayout = (SlidingUpPanelLayout) findViewById(R.id.sliding_layout);
//        mLayout.setAnchorPoint(0.3f);
        mLayout.setPanelState(SlidingUpPanelLayout.PanelState.HIDDEN);
        mLayout.setPanelHeight(500);
//        mLayout.setParallaxOffset(10);
        mLayout.setPanelSlideListener(new SlidingUpPanelLayout.PanelSlideListener() {
            @Override
            public void onPanelSlide(View panel, float slideOffset) {
                Log.i(TAG, "onPanelSlide, offset " + slideOffset);
                googleMap.getUiSettings().setAllGesturesEnabled(true);
            }

            @Override
            public void onPanelExpanded(View panel) {
                Log.i(TAG, "onPanelExpanded");
                googleMap.getUiSettings().setAllGesturesEnabled(false);

            }

            @Override
            public void onPanelCollapsed(View panel) {
                flag=true;
                Log.i(TAG, "onPanelCollapsed");
                googleMap.getUiSettings().setAllGesturesEnabled(false);

            }

            @Override
            public void onPanelAnchored(View panel) {
                Log.i(TAG, "onPanelAnchored");

            }

            @Override
            public void onPanelHidden(View panel) {
                flag=false;
                Log.i(TAG, "onPanelHidden");
            }
        });
    }

    public Boolean isGooglePlayServiceAvailable() {
        int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (ConnectionResult.SUCCESS == status) {
            return true;
        } else {
            GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
            return false;
        }

    }


    @Override
    public void onLocationChanged(Location location) {
        mlocation = location;
        latitude = location.getLatitude();
        longitude = location.getLongitude();
        latLng = new LatLng(latitude, longitude);
        long atTime = mlocation.getTime();
        mLastUpdateTime = DateFormat.getTimeInstance().format(new Date(atTime));

//        mapView.setCenterCoordinate(latLng1);

        MarkerOptions options = new MarkerOptions();
        options.position(latLng).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE));
//        Marker marker = googleMap.addMarker(options);
        googleMap.addMarker(options.title(getAdress()));
        googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
//        View view = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.custom_marker_layout, null);

        INIT =
                new CameraPosition.Builder()
                        .target(latLng)
                        .zoom(17.5F)
                        .bearing(300F) // orientation
                        .tilt(50F) // viewing angle
                        .build();
        googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(INIT));
        googleMap.getUiSettings().setCompassEnabled(false);
//
//        googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 13));
        int Radius = 100;
        googleMap.addMarker(new MarkerOptions()
                .position(latLng)
//                .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE))
                .title(getAdress())
                .snippet("Radius: " + Radius))
                .showInfoWindow();

        googleMap.addMarker(new MarkerOptions().position(new LatLng(28.7494720, 77.0565330)));

        googleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {

            @Override
            public boolean onMarkerClick(Marker marker) {

//                flag = true;
                Log.i("Marker","Click");
                points = new LatLng(marker.getPosition().latitude,marker.getPosition().longitude);
                if(flag==false){
                if(mLayout!=null){

                        Log.i("Marker", "collapsed");
                    mLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
                    animateLatLngZoom(points, 0, -10, 10);

                }}else{
                    Log.i("Marker","Hidden");                        mLayout.setPanelState(SlidingUpPanelLayout.PanelState.HIDDEN);
                }


                return true;
            }

        });


//        //Instantiates a new CircleOptions object +  center/radius 28.6328° N, 77.2197°
//        CircleOptions circleOptions = new CircleOptions()
//                .center(new LatLng(latitude, longitude))
//                .radius(Radius)
//                .fillColor(0x40ff0000)
//                .strokeColor(Color.GREEN)
//                .strokeWidth(2);
//
//// Get back the mutable Circle
//        Circle circle = googleMap.addCircle(circleOptions);
//        Circle circle1 = googleMap.addCircle(new CircleOptions().center(new LatLng(28.633908, 77.221094))
//                .radius(100)
//                .fillColor(0x40ff0000)
//                .strokeColor(Color.BLUE)
//                .strokeWidth(5));
//// more operations on the circle...
//        // =
//
//
//        googleMap.animateCamera(CameraUpdateFactory.zoomTo(15));

    }

    private void animateLatLngZoom(LatLng latlng, int reqZoom, int offsetX, int offsetY) {
        /*calculate the offset's center in the required zoom from original's offset, and then animate the map's camera.
        For this, first move the map's camera to the desired zoom, calculate the offset for that zoom level, and then restore
        the original zoom.After calculating the new center we can make the animation with CameraUpdateFactory.newLatLngZoom.*/



        // Save current zoom
//      float originalZoom = googleMap.getCameraPosition().zoom;

        // Move temporarily camera zoom
//      googleMap.moveCamera(CameraUpdateFactory.zoomTo(reqZoom));

        Point pointInScreen = googleMap.getProjection().toScreenLocation(latlng);

        Point newPoint = new Point();
        newPoint.x = pointInScreen.x + offsetX;
        newPoint.y = pointInScreen.y + offsetY;

        LatLng newCenterLatLng = googleMap.getProjection().fromScreenLocation(newPoint);

        // Restore original zoom
//      googleMap.moveCamera(CameraUpdateFactory.zoomTo(originalZoom));

        // Animate a camera with new latlng center and required zoom.
//      googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(newCenterLatLng, reqZoom));
        googleMap.animateCamera(CameraUpdateFactory.newLatLng(newCenterLatLng));

    }

    public String getAdress() {

        Geocoder geocoder;
        String result = null;
        List<Address> addresses;
        geocoder = new Geocoder(this, Locale.getDefault());
        try {
            addresses = geocoder.getFromLocation(latitude, longitude, 1);

            if (addresses != null && addresses.size() > 0) {
                Address address = addresses.get(0);
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < address.getMaxAddressLineIndex(); i++) {
                    sb.append(address.getAddressLine(i)).append("\n");
                }
//                sb.append(address.getLocality()).append("\n");
//                sb.append(address.getPostalCode()).append("\n");
                sb.append(address.getCountryName().toUpperCase());
                result = sb.toString();
            }
        } catch (IOException e) {
            Log.e("Loaction Address", "Unable connect to Geocoder", e);
        }
        return result;

    }


    @Override
    public void onProviderEnabled(String provider) {

    }

    @Override
    public void onProviderDisabled(String provider) {

    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {

    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_show_list) {
//            toggleList();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

请帮我解决一下。谢谢

4 个答案:

答案 0 :(得分:2)

我不确定这个问题是否可以直接解决。但是,我可以想象两种可能的解决方法:

  1. 尝试在lite mode中显示地图。您还可以尝试使用2个地图:第一个在默认模式下工作,第二个在精简模式下工作,然后在需要显示sligin up面板时在它们之间切换。
  2. 您可以将PanelSlideListener附加到SligingUpPanel,将overlay属性设置为true,然后PanelSlideListener.onPanelSlide将更改应用于Camera使用moveCamera / animateCamera方法结合setPadding方法(也可以移动地图控件)的地图。这肯定会解决问题,因为地图视图无法调整大小,而是您手动控制Camera对象。然而,这种方法需要做更多的工作。
  3. 更新 Here's我建议的一个例子。希望我能以正确的方式理解你的问题。您只需要创建一个空项目,添加提供Activity代码,它的布局和必要的依赖关系+创建具有必要权限的相应AndroidManifest

答案 1 :(得分:0)

您可以使用android-transition库将Y翻译应用于地图视图:

摇篮:

compile 'com.github.kaichunlin.transition:core:0.9.4'
compile 'com.github.kaichunlin.transition:slidinguppanel:0.9.1'

代码:

SlidingUpPanelLayoutAdapter adapter=new SlidingUpPanelLayoutAdapter();     
mLayout.setPanelSlideListener(adapter);         
adapter.addTransition(ViewTransitionBuilder.transit(findViewById(R.id.map)).interpolator(new LinearInterpolator()).translationY(-250));

请注意,为了使其正常工作,您必须将面板状态从HIDDEN更改为COLLAPSED,并将面板高度设置为0:

mLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
mLayout.setPanelHeight(0);

将面板状态设置为EXPANDED而不是COLLAPSED:

mLayout.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED);

并且还在sliding_fragment_layout.xml中将TableLayout的layout_height设置为500px(应该更改为使用dp,但使用px足以用于演示目的)

效果演示:https://www.dropbox.com/s/gcozdrol8ed8zcc/test.mp4?dl=0

答案 2 :(得分:0)

我认为最好的解决方案是使用视差效果。

您应该设置umanoOverlay =“true”以确保地图保持其大小。然后,给出一个锚点(例如:umanoAnchorPoint =“0.60”)和视差效果(例如:umanoParalaxOffset =“250dp”)向上滑动面板。单击标记时,将相机设置为此标记的动画,以确保它位于地图的中间。您还应该给umanoPanelHeight =“0dp”,因为如果我得到它,您只想点击标记来显示面板。

所以它会像

    sothree:umanoAnchorPoint="0.60"
    sothree:umanoDragView="@+id/dragView"
    sothree:umanoParalaxOffset="250dp"
    sothree:umanoPanelHeight="0dp"
    sothree:umanoShadowHeight="0dp"
    sothree:umanoFadeColor="@android:color/transparent"
    sothree:umanoOverlay="true"
标记单击侦听器

中的

@Override
public boolean onMarkerClick(Marker marker) {

    points = new LatLng(marker.getPosition().latitude,marker.getPosition().longitude);

    // if panel is collapsed
    if (mLayout.getPanelState().equals(
            SlidingUpPanelLayout.PanelState.COLLAPSED)) {
            // then show the panel content
            mLayout.setPanelState(SlidingUpPanelLayout.PanelState.ANCHORED);
            // animate your camera somehow
            animateLatLngZoom(points, 0, -10, 10);
        } else { // if panel is anchored or expanded
            // collapse it
            mLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
        }

    return true;
}

答案 3 :(得分:0)

我认为使用sothree:umanoOverlay="false"摆脱这种不受欢迎的影响是非常有问题的,因为将该选项设置为false需要Android在每次更改表格高度时布置地图。

因此,可能的解决方案是让您的滑动面板叠加并上下跟踪它的移动,相应地调整地图的翻译。

这是一个简短的例子:

@Override
public void onPanelSlide(View panel, float slidingOffset) {
    adjustViews(slidingOffset, false);
}

@Override
public void onPanelCollapsed(View panel) {
}

@Override
public void onPanelExpanded(View panel) {
}

@Override
public void onPanelAnchored(View panel) {
    adjustViews(mSlidingPanelLayout.getAnchorPoint(), true);
}

@Override
public void onPanelHidden(View view) {
}

private void adjustViews(final float slideOffset, boolean anchor) {

    float height = mSlidingPanelLayout.getHeight();
    float panelHeight = mSlidingPanelLayout.getPanelHeight();   

    mMapFragment.setMapTranslationY(-(int) ((height - panelHeight) * slideOffset) - mSlidingPanelLayout.getCurrentParalaxOffset());
}

你需要做一些我认为的其他事情:在旋转过程中实现setMapTranslationY和保存/恢复状态。