5

ViewPager 内の Fragment 内で GoogleMap (v2 api) を使用しています。私が抱えていた最初の問題は、ViewPager がすべての水平スクロール ジェスチャをキャプチャしていたため、ユーザーが垂直方向または斜め方向に開始した場合にのみマップをドラッグできることでした。水平方向のドラッグはすべて によってキャプチャされましたViewPager。解決策は、派生ViewPagerクラスを作成してcanScrollメソッドをオーバーライドすることであることがわかりました。ドラッグされているビューはこのメソッドに渡されるため、ビューのタイプに基づいて決定を下すことができます。

私の場合、Fragment はSupportMapFragment(com.google.android.gms.mapsパッケージからの) であり、やり取りする GoogleMap オブジェクトを提供します。ただし、ViewPager のcanScrollメソッドで受け取る実際のコントロールの型はmaps.j.bです。カスタム ViewPager クラス内の次のコードの問題を修正しました。ただし、このクラス名について何も知らない場合、このクラス名を確認するのは気が進まない. maps.jb とは何ですか? これは実行時に動的に作成されるクラスですか? フレームワークの将来の更新でタイプが変更される可能性はありますか? View オブジェクトだけが与えられた場合、ドラッグがマップ コントロールによって開始されたことを確認するより確実な方法はありますか?

@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);
}
4

3 に答える 3

3

これは実行時に動的に作成されるクラスですか?

これはおそらく、ProGuard の名前変更の出力です。

フレームワークの将来の更新でタイプが変更される可能性はありますか?

私の知る限り、はい。名前がビルド間で同じままであることを ProGuard が保証していることを認識していません。

これは、ライブラリ プロジェクトに依存することに注意してください。ライブラリ プロジェクトの新版に取り組むと、クラス名が変更される場合があります。ただし、それは自分のアプリに関連付けられているため、ピンチの場合、名前のゲームに固執することができ、ライブラリ プロジェクトの新しい版に取り組むときに名前を修正するだけで済みます。

そうは言っても、名前に基づくマッチングは厄介だということに同意します。

View オブジェクトだけが与えられた場合、ドラッグがマップ コントロールによって開始されたことを確認するより確実な方法はありますか?

これは ではないので、MapView正確に a が何であるかを知る方法はありませんmaps.j.bMapView名前が付けられていないためMapView、Google はその名前をそのままにして (-keepおそらく ProGuard 構成のディレクティブを介して)、アプリから使用できるようにしました。

MapFragment独自のものを作成してみて、 a の代わりに aMapViewが得られるかどうかを確認できます(これは、によって使用されるの内部サブクラスである可能性があります)。実際の が渡された場合は、渡されたオブジェクトが自分のであるかどうかを確認するために直接等価性チェックを行うことができます。MapViewmaps.j.bMapViewSupportMapFragmentMapViewMapFragmentMapView

または、 aが ainstanceofであると言うかどうかを確認できます。maps.j.bMapView

MapViewおそらくGoogleは何かに包まれるような問題を変更する可能性があるため、どちらも長期的に信頼できるとは限りません. ただし、生成されたクラス名よりも安定している可能性が高いと思います。

maps.j.bから継承しSurfaceViewます。Viewしたがって、が渡されたかどうかを半確実に検出する 1 つの方法canScroll()は、 if をテストすることです(v instanceof SurfaceView)。これは、Maps V2 が後で別の処理を行う場合 (例: TextureViewAPI レベル 11+ での拡張)、またはViewPagerページに別のものがある場合SurfaceView(例: a VideoView) に失敗します。

この決定を行うための安定した手段を Maps V2 API に追加するために、これに関するイシューを提出しました。

于 2013-01-17T22:13:04.763 に答える
2

まず第一に、あなたのソリューションを共有してくれてありがとう@Rich - それは私が探していたものでした. SupportMapfragment を拡張するフラグメントがそのアイテムの 1 つである View Pager があります。私のソリューションでは、フラグメントにいくつかの追加のボタンを追加する必要があったため、カスタム 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 クラスを直接参照することはできません...

于 2013-02-28T18:58:57.530 に答える
2

これが1年後に役立つことを願っています...私の場合、Viewオブジェクトを無視することでこの問題を解決しました。できることは、現在のページにマップが含まれるように 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 index, boolean canScroll) というメソッドを追加して、マップを含むページの参照を保持します。必要に応じてアクティビティから呼び出します。

于 2014-03-21T11:11:17.780 に答える