我在我的应用程序中使用Umano/SlidingUpPanel库,其中Map是主要内容。一块面板在地图上向上滑动。我将覆盖属性设置为false,因为我希望面板向上滑动时主要内容向上移动(就像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);
}
请帮我解决这个问题。谢谢
我不确定这个问题能否直接解决。然而,我可以想象两种可能的解决方案:
- 尝试在lite模式下显示地图。你也可以尝试有两个地图:第一个在默认模式下工作,第二个在精简模式下工作。然后当你需要显示sligin up面板时,在它们之间切换
- 您可以将
PanelSlideListener
附加到SligingUpPanel
,将overlay
属性设置为true
,并在PanelSlideListener.onPanelSlide
中使用moveCamera
/animateCamera
方法和setPadding
方法将更改应用到映射的Camera
对象(也可以移动映射控件)。这肯定会解决问题,因为地图视图不会被调整大小,而是您将手动控制Camera
对象。然而,这种方法需要做更多的工作
UPDATE下面是我的建议示例。希望我能正确理解你的问题。你只需要创建一个空项目,添加那里提供的Activity
代码,它的布局和必要的依赖项+创建具有必要权限的适当AndroidManifest
。
您可以使用android转换库将Y翻译应用于地图View:
等级:
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
我认为最好的解决方案是使用视差效果。
您应该将umanoOverlay设置为"true"以确保地图保持其大小。然后,为向上滑动面板提供锚点(例如:umanoAnchorPoint="0.60")和视差效果(例如:humanoParalaxOffset="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;
}
我想用sothree:umanoOverlay="false"
来消除这种不必要的效果会很有问题,因为每次更改桌子的高度时,将该选项设置为false需要Android来布局地图。
所以,对你来说,可能的解决方案是让你的滑动面板被覆盖,并跟踪它的上下移动,相应地调整你的地图平移Y。
这里有一个简单的例子:
@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和在旋转期间保存/恢复状态。