自ViewPager,让孩子的GoogleMap控制水平滚动(Custom ViewPager to

2019-08-07 05:22发布

我使用的是ViewPager内部片段内的GoogleMap(V2 API)。 我在原来的问题是,ViewPager被捕获的所有水平滚动的姿势,所以如果用户在垂直或对角线方向开始了地图只能拖着​​。 所有水平拖动被抓获ViewPager 。 我发现,解决方案是创建派生ViewPager类并覆盖canScroll方法。 此视图拖传递给此方法,这样就可以使基于搜索的类型是一个决定。

就我而言,我的片段是一个SupportMapFragment (从com.google.android.gms.maps包),它给了我一个GoogleMap对象进行交互。 不过,我收到的ViewPager的实际控制canScroll方法类型的maps.jb 。 我与我的自定义ViewPager类中下面的代码解决了这一问题。 不过,我不觉得这个类的名字舒适的检查的时候,我不知道这件事。 什么是maps.jb? 这是在运行时动态创建的类? 是否有可能为类型的框架,以后的更新变化? 鉴于只有查看的对象,有没有检查该阻力是由地图控件发起的更强大的方法吗?

@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
    if(v.getClass().getName().equals("maps.j.b")) {
        return true;
    }
    return super.canScroll(v, checkV, dx, x, y);
}

Answer 1:

这是在运行时动态创建的类?

这可能是一个ProGuard的重命名的输出。

是否有可能为类型的框架,以后的更新变化?

据我所知,是的。 我不知道,ProGuard的保证了名字将留之间架起相同。

请注意,这将取决于库项目。 当你拿上库项目的新版本,类名可能会改变。 但是,因为这是绑在自己的应用程序,在紧要关头,你可以与名游戏棒,并且只需要当你在图书馆项目的新版本修复了名。

话虽这么说,我同意基于名称匹配的是恶心。

鉴于只有查看的对象,有没有检查该阻力是由地图控件发起的更强大的方法吗?

好了,因为这不是一个MapView ,我们无法知道正是一个什么方式maps.jb是。 我们知道这是不是一个MapView ,因为它没有命名MapView ,而谷歌(通过单独留在家中那名-keep在ProGuard的配置指令,想必),所以我们可以从我们的应用程序使用它。

你可以尝试创建自己的MapFragment用自己MapView ,看看是否有你得到一个MapView ,而不是maps.jb (这可能是内部的一些子类MapView所使用SupportMapFragment )。 如果获得通过实际MapView ,那么你可以做直接的平等检查是否传入的对象是你的MapFragmentMapView

或者,你可以看到,如果instanceof说一个maps.jb是一个MapView

无论这些都保证随着时间的推移可靠,无论是作为可以想象谷歌可能会改变的问题,使得MapView被包裹的东西。 然而,我的猜测是,它更可能比生成的类名稳定。

maps.jb继承自SurfaceView 。 因此,单程到半可靠地检测是否View传递到canScroll()是测试(v instanceof SurfaceView) 如果地图不V2别的东西后这失败(例如,扩展TextureView在API级别11+),或者如果您ViewPager网页有另一个SurfaceView (如VideoView )。

我已经申请上这个问题 ,试图让做出该决定加入地图API V2的一些稳定的手段。



Answer 2:

首先,@Rich感谢分享您的解决方案 - 这是我一直在寻找。 我有延长SupportMapfragment是其项目之一的片段查看传呼机。 在我的解决方案我有一个自定义XML布局文件,因为我需要一些额外的按钮添加到片段。 这里是我的解决方案:

public class MapFragmentScrollOverrideViewPager extends ViewPager {

public MapFragmentScrollOverrideViewPager(Context context) {
    super(context);
}

public MapFragmentScrollOverrideViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
    if(v instanceof MapHoldingRelativeLayout) {
        return true;
    }
    return super.canScroll(v, checkV, dx, x, y);
} }

public class MapHoldingRelativeLayout extends RelativeLayout {

public MapHoldingRelativeLayout(Context context) {
    super(context);
}

public MapHoldingRelativeLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public MapHoldingRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}  }

片段布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    xmlns:android="http://schemas.android.com/apk/res/android">

    <Button 
        android:id="@+id/switchNearbyOffersButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="XXXX"
        />

    <xxx.view.MapHoldingRelativeLayout
        android:id="@+id/mapLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/switchNearbyOffersButton"
         />

</RelativeLayout>

片段本身:

public final class NearbyOffersFragment extends SupportMapFragment {

    public static NearbyOffersFragment newInstance(String content) {
        NearbyOffersFragment fragment = new NearbyOffersFragment();
        return fragment;
    }

    private GoogleMap googleMap;

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

    private void setUpMapIfNeeded() {
        if (googleMap == null) {
            googleMap = getMap();
            if (googleMap != null) {
                setUpMap();
            }
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        final View rootView = inflater.inflate(R.layout.fragment_nearby_offers,
                container, false);
        final View mapFragmentLayout = super.onCreateView(inflater, container,
                savedInstanceState);
        MapHoldingRelativeLayout mapLayout = (MapHoldingRelativeLayout) rootView
                .findViewById(R.id.mapLayout);
        mapLayout.addView(mapFragmentLayout);
        return rootView;
    }
    @Override
    public void onResume() {
        super.onResume();
        setUpMapIfNeeded();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
    }

    private void setUpMap() {
        googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
        googleMap.getUiSettings().setZoomControlsEnabled(true);
        googleMap.getUiSettings().setAllGesturesEnabled(true);
        CameraPosition cameraPosition = new CameraPosition.Builder()
                .target(new LatLng(41.474856, -88.056928))
                .zoom(14.5f)
                .build();
        googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
    }
}

由于原SupportMapFragment的布局是我的自定义RelativeLyout你可以使用instanceof运算符,而不是直接引用maps.jb类的内...



Answer 3:

希望这有助于在一年后...在我的情况下,我忽略了查看对象解决了这个问题。 你可以做的是通知CustomViewPager使当前页面中包含的地图。

public class CustomViewPager extends ViewPager {
    @Override
    protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
        if (this.containsMap()) {
            return true;
        }
        return super.canScroll(v, checkV, dx, x, y);
    }
}

在我的情况containsMap()只检查当前页面对应于一个预定义的页面索引:

public boolean containsMap(){
    return getCurrentItem() == MAP_PAGE;
}

但它可能是更复杂的:添加一个名为setCanScrollIndex(INT指数,布尔canScroll)方法,以保持一个包含地图这些页面的引用。 从你的活动把它适当的时候。



文章来源: Custom ViewPager to allow child GoogleMap control to scroll horizontally