如何为 Android 制作自定义地点选择器

2024-01-13

据我所知,谷歌不允许开发人员自定义地点选择器布局,

所以我想制作一个如下图所示的地点选择器。

它来自 Deliveroo 应用程序,我使用了地图 api,但它并不完全像这张照片。

这个选择器的行为类似于地点选择器 api,它是定制的。

这是我的代码:

public class Map extends AppCompatActivity implements OnMapReadyCallback {

private GoogleMap mMap;
private LatLng markerLatLong;
private static final int REQUEST_CODE_LOCATION_ENABLE = 1;
private static final int PLACE_AUTOCOMPLETE_REQUEST_CODE = 2;
private static String TAG = Map.class.getSimpleName();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.map);
    setToolbar();
    setFragment();
}

public void setFragment() {
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
}

public void setToolbar() {

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    if (getSupportActionBar() != null) {
        getSupportActionBar().setDisplayShowTitleEnabled(false);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }
    onSearchPlacesClicked(toolbar);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE_LOCATION_ENABLE) {
        if (resultCode == RESULT_OK) {
            Log.e(TAG, "location enabled");
            setLocation();
        }
    }else if (requestCode == PLACE_AUTOCOMPLETE_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {
                Place place = PlaceAutocomplete.getPlace(this, data);
                Log.e(TAG, "Place: " + place.getName());
                setPlace(place.getLatLng());

            } else if (resultCode == PlaceAutocomplete.RESULT_ERROR) {
                Status status = PlaceAutocomplete.getStatus(this, data);
                // TODO: Handle the error.
                Log.i(TAG, status.getStatusMessage());

            } else if (resultCode == RESULT_CANCELED) {
                // The user canceled the operation.
            }
        }
}


/**
 * Manipulates the map once available.
 * This callback is triggered when the map is ready to be used.
 * This is where we can add markers or lines, add listeners or move the camera. In this case,
 * we just add a marker near Sydney, Australia.
 * If Google Play services is not installed on the device, the user will be prompted to install
 * it inside the SupportMapFragment. This method will only be triggered once the user has
 * installed Google Play services and returned to the app.
 */
@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    mMap.setMyLocationEnabled(true);
    mMap.getUiSettings().setMyLocationButtonEnabled(true);
    mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
        @Override
        public void onMapClick(LatLng latLng) {
            setPlace(latLng);
        }
    });
    Button b = (Button) findViewById(R.id.pick_place);
    b.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (markerLatLong != null) {
                addAddressToPref(-1, markerLatLong.latitude, markerLatLong.longitude);
                startActivity(new Intent(Map.this, StoreList.class));
                Map.this.finish();
            } else {
                Toast.makeText(Map.this, R.string.no_place_selected, Toast.LENGTH_SHORT).show();
            }
        }
    });
    setLocation();

}

public void addAddressToPref(long id, double latitude, double longitude) {
    Singleton.getInstance().setAddressPref(id, latitude, longitude);
}

public void setPlace(final LatLng latLng) {

    mMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {

        @Override
        public void onCameraChange(CameraPosition arg0) {
          mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15));

            // Remove listener to prevent position reset on camera move.
            mMap.setOnCameraChangeListener(null);
        }
    });
    markerLatLong = latLng;
    mMap.clear();
    mMap.addMarker(new MarkerOptions().position(latLng).title(getString(R.string.my_location)));



}

public void setLocation() {
    AppLocationService gps = new AppLocationService(this);

    // check if GPS enabled
    if (gps.canGetLocation()) {

        double latitude = gps.getLatitude();
        double longitude = gps.getLongitude();

        getLocation(latitude, longitude);
        // \n is for new line
    } else {
        // can't get location
        // GPS or Network is not enabled
        // Ask user to enable GPS/network in settings
        buildAlertMessageNoGps();
    }
}

public void getLocation(double latitude, double longitude) {
    final CoordinatorLayout rootLayout = (CoordinatorLayout) findViewById(R.id.root_view);
    if (latitude != 0 && longitude != 0) {
        LatLng latLng = new LatLng(latitude, longitude);
        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 15);
        mMap.animateCamera(cameraUpdate);
    } else {
        Snackbar.make(rootLayout, getResources().getString(R.string.location_problem),
                Snackbar.LENGTH_INDEFINITE).setAction("سعی دوباره", new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                setLocation();
            }
        }).show();
    }
}

private void buildAlertMessageNoGps() {
    final AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage(getString(R.string.turn_on_location_text))
            .setCancelable(false)
            .setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
                public void onClick(final DialogInterface dialog, final int id) {
                    Intent intent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                    startActivityForResult(intent, REQUEST_CODE_LOCATION_ENABLE);
                }
            })
            .setNegativeButton(getString(R.string.exit), new DialogInterface.OnClickListener() {
                public void onClick(final DialogInterface dialog, final int id) {
                    dialog.cancel();
                    Map.this.finish();
                }
            });
    final AlertDialog alert = builder.create();
    alert.show();

}

public void onSearchPlacesClicked(Toolbar toolbar) {
    ImageView searchPlace = (ImageView) toolbar.findViewById(R.id.search_place);
    searchPlace.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            autoCompleteMethod();
        }
    });
}

public void autoCompleteMethod() {
    try {
        Intent intent =
                new PlaceAutocomplete.IntentBuilder(PlaceAutocomplete.MODE_OVERLAY)
                        .build(this);
        startActivityForResult(intent, PLACE_AUTOCOMPLETE_REQUEST_CODE);
    } catch (GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException e) {
        // TODO: Handle the error.
    }
}

@Override
protected void onResume() {
    super.onResume();
    if (mMap != null) {
        setLocation();
    }
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {
        case android.R.id.home:
            onBackPressed();
            break;
    }
    return true;
}

@Override
public void onBackPressed() {
    startActivity(new Intent(Map.this, StoreList.class));
    Map.this.finish();
}
}

为地图创建活动并在您想要的位置调用该活动:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".Activity.InsertMapsActivity">

<Button
    android:layout_width="wrap_content"
    android:id="@+id/btn_set_garage_location"
    android:text="set location"
    android:layout_height="wrap_content"/>
<fragment
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

java代码:

public class InsertMapsActivity extends FragmentActivity implements LocationListener
{

private GoogleMap googleMap;
private LatLng garageLocation;
Button btnSetGarageLocation;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_insert_maps);
    btnSetGarageLocation = (Button) findViewById(R.id.btn_set_garage_location);
    int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getBaseContext());
    // Obtain the SupportMapFragment and get notified when the map is ready to be used.

    if (status != ConnectionResult.SUCCESS)
    { // Google Play Services are not available

        int requestCode = 10;
        Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status, this, requestCode);
        dialog.show();

    }
    else
    { // Google Play Services are available

        // Getting reference to the SupportMapFragment of activity_main.xml
        SupportMapFragment fm = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);

        // Getting GoogleMap object from the fragment
        googleMap = fm.getMap();

        // Enabling MyLocation Layer of Google Map
        googleMap.setMyLocationEnabled(true);

        // Getting LocationManager object from System Service LOCATION_SERVICE
        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

        // Creating a criteria object to retrieve provider
        Criteria criteria = new Criteria();

        // Getting the name of the best provider
        String provider = locationManager.getBestProvider(criteria, true);

        // Getting Current Location
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
        {
            // TODO: Consider calling

            return;
        }
        Location location = locationManager.getLastKnownLocation(provider);

        if(location!=null){
            onLocationChanged(location);
        }
        locationManager.requestLocationUpdates(provider, 100, 0, this);

        btnSetGarageLocation.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                Intent intent = getIntent();
                intent.putExtra("location_lat",garageLocation.latitude);
                intent.putExtra("location_lng",garageLocation.longitude);
                setResult(RESULT_OK,intent);
                finish();
            }
        });
    }

    googleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener()
    {
        @Override
        public void onMapClick(LatLng latLng)
        {
            googleMap.clear();
            googleMap.addMarker(new MarkerOptions().position(latLng).title("Custom location").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)));
            garageLocation = latLng;
        }
    });


}

@Override
public void onLocationChanged(Location location)
{

    // Getting latitude of the current location
    double latitude = location.getLatitude();

    // Getting longitude of the current location
    double longitude = location.getLongitude();

    // Creating a LatLng object for the current location
    LatLng latLng = new LatLng(latitude, longitude);

    // Showing the current location in Google Map
    googleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));

    // Zoom in the Google Map
    googleMap.animateCamera(CameraUpdateFactory.zoomTo(15));

    googleMap.getMaxZoomLevel();

    // Setting latitude and longitude in the TextView tv_location

}

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

}

@Override
public void onProviderEnabled(String provider)
{

}

@Override
public void onProviderDisabled(String provider)
{

}
}

活动中:

private int MAP = 2;

Intent intent = new Intent(getApplicationContext(),InsertMapsActivity.class);
                startActivityForResult(intent, MAP);

您的活动结束:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);

    ImageView garageImage = new ImageView(this);
    if (resultCode == Activity.RESULT_OK)
    {

    }

    if(requestCode == MAP)
    {
        double lat = (double) data.getExtras().get("location_lat");
        double lng = (double) data.getExtras().get("location_lng");


    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何为 Android 制作自定义地点选择器 的相关文章

随机推荐

  • 如何在 Pandas 数据框中堆叠行以获得一个“长行”?

    假设我有一个 4 行 3 列的数据框 我想水平堆叠行 这样我就得到一行 12 列 如何操作以及如何处理冲突的列名称 您可以通过以下方式实现这一目标stack计算框架以产生一系列所有值 然后我们希望使用以下方法将其转换回 dfto frame
  • 将二进制浮点“1101.11”转换为十进制(13.75)的正确算法?

    我用C编写了一个程序来转换浮点数以二进制表示 http kipirvine com asm workbook floating tut htm 1101 11 化为小数 13 75 但是 我似乎无法从算法中获得正确的值 将二进制浮点数转换为
  • JavaScript 中的“闭包”到底指的是什么?

    我理解闭包是什么 但我在理解这个术语到底是什么时遇到了一些困难closure指 我在许多网站上看到过这个术语 但很少有人就其实际定义达成一致 是保存在栈帧上的变量吗 是返回的函数吗 它是外部函数的范围吗 它是内部 返回 函数的范围吗 是不是
  • 如何在 Swift 3 中测试 URL 并获取状态代码?

    我正在使用最新版本的 Xcode 撰写本文时为 8 1 它使用 Swift 3 0 我想做的就是获取一个字符串 将其转换为 URL 并测试该 URL 看看它是否会给出 404 错误 我已经能够使用以下方法创建 URL 和 URLReques
  • Node.JS 内核模式线程

    我试图弄清楚 Node JS 其 Windows 版本 是如何在幕后工作的 我知道有用户模式和内核模式线程 并且我知道处理模型如下所示 我还知道从内核模式线程移动到用户模式线程被认为是上下文切换 Node JS C 非阻塞工作线程是内核模式
  • Angular2 在模板和变更检测中的功能

    我试图在服务中构建一种方法 检查是否应根据当前用户的权限向当前用户显示导航按钮 我知道这只是装饰性的 安全性 因此这是放置在模板内的按钮
  • 尾随返回类型中的占位符是否会覆盖初始占位符?

    g 似乎接受任意组合auto and decltype auto 作为初始和尾随返回类型 int a auto f return a int auto g gt auto return a int auto h gt decltype au
  • 关于 DSO 引用隐藏符号的警告究竟意味着什么?

    我在将某些共享库与 g 链接时遇到问题 它给了我这样的警告 hidden symbol XXX in YYY is referenced by DSO usr lib 我已经阅读了一些有关特定问题的相关问题 但我想从整体上理解它 这个警告是
  • 如何授予jnlp文件中依赖lib的所有权限?

    我在使用 Java Web Start 时遇到了一个严重的问题 我无法理解 情况如下 我有一个 JavaFX 应用程序 编写为 Java8 我想使用 Java WebStart 进行部署 直到最近 我还使用 HTTP 与服务器进行通信 一切
  • 仅在 Spring Data Rest 中为子资源级别启用存储库?

    我有 2 个 jpa 实体 Document 和 DispatchDetail 它们具有一对多关系 即一个文档可以有一个dispatchDetails 列表 我为每个实体创建了 2 个存储库 现在我要尝试文档 GET http localh
  • Django MakeMessages 在 Windows 中缺少 xgettext

    在 Windows 7 上运行 Django 我目前正在尝试使用 django 书籍第 19 章中的说明翻译几个 Django 模板 我已向模板添加了翻译标签 加载了 I18N 并修改了 django 设置 然后我运行 django adm
  • 快速地,为什么当协议有初始化器时我不能实例化它?

    据我所知 通常我无法实例化协议 但是 如果我在协议中包含一个初始化程序 那么编译器肯定知道当结构或类稍后使用该协议时 它将有一个可以使用的 init 吗 我的代码如下所示 protocol Solution var answer Strin
  • 无法连接到服务器:net/http:TLS 握手超时

    在 minikube for windows 上 我在 kubernetes 集群上创建了一个部署 然后尝试通过将副本从 1 更改为 2 来扩展它 之后 kubectl 挂起 我的磁盘使用率为 100 我的部署中只有一个容器 apiVers
  • 单击按钮后立即执行 SwiftUI 按钮操作,而不是单击释放时

    我想在 SwiftUI Button 中单击 点击按钮后立即调用该操作 我怎样才能实现这个 这是一种可能的方法 使用自定义ButtonStyle注入自定义触地动作 使用 Xcode 12 iOS 14 进行测试 struct Pressed
  • com.sun.ws.rs.ext.RuntimeDelegateImpl 错误

    请帮忙 目前我正在构建一个系统 允许一些Web服务 Axis2 调用restful jersey 1 12 场景是这样的 客户端 gt webservice Axis2 gt Restful services Jersey 1 12 在 t
  • 如何使用 SqlCommand 创建带有参数化数据库名称的数据库?

    简而言之 我有两个简单的助手 private SqlCommand CreateCommand string text SqlCommand cmd new SqlCommand cmd Connection connection cmd
  • Tinymce 4.x 扩展插件

    我正在寻找一些有关如何扩展现有的tinymce 4 x 插件的示例 例如 链接 插件 链接插件打开一个对话框窗口 我想做的是在对话框打开时添加一个事件并修改正文 插入一些带有单击事件的额外 HTML 做得好似乎是有问题的 我想避免一些 顶部
  • 生成两个相关的随机向量

    我想生成两个具有指定相关性的随机向量 第二个向量的每个元素必须与第一个向量的相应元素相关并且相互独立 我怎样才能在 MATLAB 中做到这一点 顺便说一句 第一个向量的元素不具有相同的分布 我的意思是第一个向量的每个元素应该具有不同的方差
  • Py_Finalize() 会导致 Python 3.9 出现分段错误,但不会导致 Python 2.7

    我正在开发一个使用 C matplotlib 包装器的项目matplotlibcpp h https github com lava matplotlib cpp 使用这个原始头文件的最小示例是 include matplotlibcpp
  • 如何为 Android 制作自定义地点选择器

    据我所知 谷歌不允许开发人员自定义地点选择器布局 所以我想制作一个如下图所示的地点选择器 它来自 Deliveroo 应用程序 我使用了地图 api 但它并不完全像这张照片 这个选择器的行为类似于地点选择器 api 它是定制的 这是我的代码