先上图
前提:有百度地图账号并配置了相关环境,可以参考百度地图开发者文档并下载so和jar
代码有相对应的注释,关键的就是百度地图移动版开发密钥、正确填写SHA1 和 程序包名,这将影响百度地图的功能使用
主要功能(参照微信发送定位):
1.定位所在位置并且展示周边POI(建筑物等信息);
2.拖拽地图完成,返回中心覆盖物所处位置周边的POI信息;
3.支持关键词等搜索,每次搜索完成,中央覆盖物移动到第一条POI信息的相应位置;
4.点击定位的图标,中央覆盖物回到所定位的位置;
5.点击下边列表的某条数据,将中央覆盖物移至该条数据对应的位置;
6.发送定位时,有相应的地图位置截图和地址信息.
————————————————
核心代码
//点击地图的监听,并显示所点击位置周围的poi信息
mBaiduMap.setOnMapClickListener(new BaiduMap.OnMapClickListener() {
@Override
public void onMapClick(LatLng latLng) {
mBaiduMap.clear();
adapter.changeSelected(0);
mJARecyclerView.smoothScrollToPosition(0);
MapStatusUpdate u = MapStatusUpdateFactory
.newLatLng(latLng);
mBaiduMap.animateMapStatus(u);
isUseGeoCoder = true;
}
@Override
public boolean onMapPoiClick(MapPoi mapPoi) {
LatLng position = mapPoi.getPosition();
mBaiduMap.clear();
MapStatusUpdate u = MapStatusUpdateFactory
.newLatLng(position);
mBaiduMap.animateMapStatus(u);
isUseGeoCoder = true;
return true;
}
});
//移动地图的监听,并显示所点击位置周围的poi信息
mBaiduMap.setOnMapTouchListener(new BaiduMap.OnMapTouchListener() {
@Override
public void onTouch(MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
isUseGeoCoder = true;
isNeedAnimation = true;
}
}
});
//地图状态发生改变的监听,不管是点击还是移动地图,都会触发状态改变的监听,处理位置居中显示,开启动画,反地理编码(根据坐标获取位置名称、地址等信息)
mBaiduMap.setOnMapStatusChangeListener(new BaiduMap.OnMapStatusChangeListener() {
@Override
public void onMapStatusChangeStart(MapStatus mapStatus) {
}
@Override
public void onMapStatusChangeStart(MapStatus mapStatus, int i) {
}
@Override
public void onMapStatusChange(MapStatus mapStatus) {
}
@Override
public void onMapStatusChangeFinish(MapStatus mapStatus) {
mBaiduMap.clear();
if (isNeedAnimation) {
centerImage.startAnimation(centerAnimation);
}
LatLng target = mapStatus.target;
if (isUseGeoCoder) {
showLoading(true);
mGeoCoder.reverseGeoCode((new ReverseGeoCodeOption())
.location(target));
adapter.changeSelected(0);
mJARecyclerView.smoothScrollToPosition(0);
}
}
});
完整代码:
SelectAddressActivity.class
package com.lyw.myproject.baidumap.cityselect;
import android.content.Context;
import android.graphics.Point;
import android.os.Bundle;
import android.text.Editable;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextWatcher;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.MapPoi;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MyLocationConfiguration;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.map.offline.MKOLSearchRecord;
import com.baidu.mapapi.map.offline.MKOfflineMap;
import com.baidu.mapapi.map.offline.MKOfflineMapListener;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.core.PoiInfo;
import com.baidu.mapapi.search.core.SearchResult;
import com.baidu.mapapi.search.geocode.GeoCodeResult;
import com.baidu.mapapi.search.geocode.GeoCoder;
import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult;
import com.baidu.mapapi.search.sug.OnGetSuggestionResultListener;
import com.baidu.mapapi.search.sug.SuggestionResult;
import com.baidu.mapapi.search.sug.SuggestionSearch;
import com.baidu.mapapi.search.sug.SuggestionSearchOption;
import com.lyw.myproject.BaseActivity;
import com.lyw.myproject.BuildConfig;
import com.lyw.myproject.R;
import com.lyw.myproject.adapter.AddressSelectAdapter;
import com.lyw.myproject.utils.PermissionUtil;
import com.lyw.myproject.utils.StatusBarUtils;
import com.lyw.myproject.widget.DefaultItemDecoration;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
/**
* 功能描述:地址选择
* Created on 2020/6/17.
* @author lyw
*/
public class SelectAddressActivity extends BaseActivity implements AddressSelectAdapter.OnAddressSelectItemClickListener{
private RecyclerView mJARecyclerView;
private TextView cancleTv,searchAddressTv,confirmTv,searchNoDataTv;
private MapView mBmapView;
private EditText mSearchAddressEt;
private LinearLayout searchNoDataLayout,searchNonmalLayout,searchEditLayout;
private ImageView centerImage,locationIv,clearInputIv,mCheckTipIv;
private BaiduMap mBaiduMap;
private LocationClient mLocationClient;
//是否首次定位
boolean isFirstLoc = true;
private AddressSelectAdapter adapter;
private List<PoiInfo> mFilterList = new ArrayList<>();
//选择的位置信息
private PoiInfo selPoiDetailInfo;
// 当前经纬度
double mLantitude;
double mLongtitude;
LatLng mLoactionLatLng;
// MapView中央对于的屏幕坐标
Point mCenterPoint = null;
// 地理编码
GeoCoder mGeoCoder = null;
List<PoiInfo> mInfoList;
PoiInfo mCurentInfo;
MyBDLocationListner mListner = null;
private Animation centerAnimation;
//是否使用反地理编码
private boolean isUseGeoCoder = true;
//是否需要动画
private boolean isNeedAnimation = true;
private InputMethodManager inputMethodManager;
private SuggestionSearch mSuggestionSearch;
private String changeContent;
private MKOfflineMap mOffline;
//选中的CityCode
private String selectCityCode;
private ArrayList<MKOLSearchRecord> mkolSearchRecords;
private RotateAnimation mAnimation;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity_address_select_layout);
FullscreenInputWorkaroundUtil.assistActivity(this);
//设置状态栏透明
StatusBarUtils.makeStatusBarTransparent(SelectAddressActivity.this);
//请求位置权限
if (!PermissionUtil.isHasLocationPermission(this)) {
PermissionUtil.requestLocationPermission(this);
}
initView();
initEvent();
inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
//得到城市code
mOffline = new MKOfflineMap();
mOffline.init(new MKOfflineMapListener() {
@Override
public void onGetOfflineMapState(int i, int i1) {
}
});
}
@Override
public void onResume() {
super.onResume();
if (mBmapView != null) {
mBmapView.onResume();
}
}
@Override
protected void onPause() {
super.onPause();
if (mBmapView != null) {
mBmapView.onPause();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mBmapView != null) {
mBmapView.onDestroy();
}
mBaiduMap.setMyLocationEnabled(false);
if (mLocationClient != null) {
mLocationClient.stop();
}
if (mGeoCoder != null) {
mGeoCoder.destroy();
}
if (mSuggestionSearch != null) {
mSuggestionSearch.destroy();
}
if (mOffline != null) {
mOffline.destroy();
}
}
private void initView() {
mJARecyclerView = (RecyclerView)findViewById(R.id.recyclerview);
cancleTv = (TextView)findViewById(R.id.cancle_tv);
searchAddressTv = (TextView)findViewById(R.id.search_address_tv);
confirmTv = (TextView)findViewById(R.id.confirm_tv);
mBmapView = (MapView)findViewById(R.id.bmapView);
mSearchAddressEt = (EditText)findViewById(R.id.search_address_et);
searchNoDataTv = (TextView)findViewById(R.id.search_no_data_tv);
searchNoDataLayout = (LinearLayout)findViewById(R.id.search_no_data_layout);
searchNonmalLayout = (LinearLayout)findViewById(R.id.search_nonmal_layout);
searchEditLayout = (LinearLayout)findViewById(R.id.search_edit_layout);
centerImage = (ImageView)findViewById(R.id.center_image);
locationIv = (ImageView)findViewById(R.id.location_iv);
clearInputIv = (ImageView)findViewById(R.id.clear_input_iv);
mCheckTipIv = (ImageView)findViewById(R.id.check_tip_iv);
}
private void initEvent() {
mBaiduMap = mBmapView.getMap();
adapter = new AddressSelectAdapter(this);
adapter.setOnAddressSelectItemClickListener(this);
mJARecyclerView.setLayoutManager(new LinearLayoutManager(this));
mJARecyclerView.addItemDecoration(new DefaultItemDecoration(this, R.dimen.common_utils_divider_height, R.color.src_line_c9));
mJARecyclerView.setAdapter(adapter);
mSearchAddressEt.setHint("搜索地点");
searchAddressTv.setText("搜索地点");
mSearchAddressEt.addTextChangedListener(new SearchDevicesTextWatcher());
cancleTv.setText("取消");
confirmTv.setText("确定");
//加载动画
mAnimation = new RotateAnimation(0, 359, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
mAnimation.setDuration(1000);
mAnimation.setRepeatCount(-1);
mAnimation.setInterpolator(new LinearInterpolator());
mCheckTipIv.setColorFilter(getResources().getColor(R.color.src_c1));
mCheckTipIv.setImageResource(R.mipmap.icon_login_loading);
centerAnimation = AnimationUtils.loadAnimation(this, R.anim.center_anim);
initMyLocation();
mBaiduMap.setCompassEnable(false);
searchNonmalLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
searchNonmalLayout.setVisibility(View.GONE);
searchEditLayout.setVisibility(View.VISIBLE);
showInput(mSearchAddressEt);
}
});
clearInputIv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
searchNonmalLayout.setVisibility(View.VISIBLE);
searchEditLayout.setVisibility(View.GONE);
mSearchAddressEt.setText("");
mSearchAddressEt.clearFocus();
hideSoftInputWindow(v);
mFilterList.clear();
if (mLoactionLatLng != null) {
MapStatus.Builder builder = new MapStatus.Builder();
builder.target(mLoactionLatLng).zoom(17.0f);
mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus
(builder.build()));
isUseGeoCoder = true;
isNeedAnimation = false;
} else {
}
}
});
locationIv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mLoactionLatLng != null) {
MapStatus.Builder builder = new MapStatus.Builder();
builder.target(mLoactionLatLng).zoom(17.0f);
mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus
(builder.build()));
isUseGeoCoder = true;
isNeedAnimation = true;
} else {
}
}
});
}
/**
* 隐藏键盘
*/
private void hideSoftInputWindow(View view) {
if (inputMethodManager.isActive()) {
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
/**
* 显示键盘
* @param et 输入焦点
*/
public void showInput(final EditText et) {
et.requestFocus();
if (inputMethodManager.isActive()) {
inputMethodManager.showSoftInput(et, InputMethodManager.SHOW_IMPLICIT);
}
}
/**
* 获取我的定位
*/
private void initMyLocation() {
// 初始化地图
mBmapView.showZoomControls(false);
MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(17.0f);
mBaiduMap.setMapStatus(msu);
mInfoList = new ArrayList<PoiInfo>();
mCenterPoint = mBaiduMap.getMapStatus().targetScreen;
mLoactionLatLng = mBaiduMap.getMapStatus().target;
// 定位
mBaiduMap.setMyLocationEnabled(true);
mLocationClient = new LocationClient(this);
mListner = new MyBDLocationListner();
mLocationClient.registerLocationListener(mListner);
LocationClientOption option = new LocationClientOption();
option.setCoorType("bd09ll");
mLocationClient.setLocOption(option);
mLocationClient.start();
// 地理编码
mGeoCoder = GeoCoder.newInstance();
mGeoCoder.setOnGetGeoCodeResultListener(mGeoListener);
showLoading(true);
mBaiduMap.setOnMapClickListener(new BaiduMap.OnMapClickListener() {
@Override
public void onMapClick(LatLng latLng) {
mBaiduMap.clear();
adapter.changeSelected(0);
mJARecyclerView.smoothScrollToPosition(0);
MapStatusUpdate u = MapStatusUpdateFactory
.newLatLng(latLng);
mBaiduMap.animateMapStatus(u);
isUseGeoCoder = true;
}
@Override
public boolean onMapPoiClick(MapPoi mapPoi) {
LatLng position = mapPoi.getPosition();
mBaiduMap.clear();
MapStatusUpdate u = MapStatusUpdateFactory
.newLatLng(position);
mBaiduMap.animateMapStatus(u);
isUseGeoCoder = true;
return true;
}
});
mBaiduMap.setOnMapTouchListener(new BaiduMap.OnMapTouchListener() {
@Override
public void onTouch(MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
isUseGeoCoder = true;
isNeedAnimation = true;
}
}
});
mBaiduMap.setOnMapStatusChangeListener(new BaiduMap.OnMapStatusChangeListener() {
@Override
public void onMapStatusChangeStart(MapStatus mapStatus) {
}
@Override
public void onMapStatusChangeStart(MapStatus mapStatus, int i) {
}
@Override
public void onMapStatusChange(MapStatus mapStatus) {
}
@Override
public void onMapStatusChangeFinish(MapStatus mapStatus) {
mBaiduMap.clear();
if (isNeedAnimation) {
centerImage.startAnimation(centerAnimation);
}
LatLng target = mapStatus.target;
if (isUseGeoCoder) {
showLoading(true);
mGeoCoder.reverseGeoCode((new ReverseGeoCodeOption())
.location(target));
adapter.changeSelected(0);
mJARecyclerView.smoothScrollToPosition(0);
}
}
});
mSuggestionSearch = SuggestionSearch.newInstance();
mSuggestionSearch.setOnGetSuggestionResultListener(listener);
}
OnGetSuggestionResultListener listener = new OnGetSuggestionResultListener() {
@Override
public void onGetSuggestionResult(SuggestionResult suggestionResult) {
//处理sug检索结果
List<SuggestionResult.SuggestionInfo> allSuggestions = suggestionResult.getAllSuggestions();
mInfoList.clear();
if (allSuggestions == null) {
}else {
for (SuggestionResult.SuggestionInfo suggestionInfo : allSuggestions) {
if (suggestionInfo == null) {
continue;
}
PoiInfo info = new PoiInfo();
info.address = suggestionInfo.getKey();
LatLng pt = suggestionInfo.pt;
info.location = pt;
info.city = suggestionInfo.city;
info.name = suggestionInfo.getKey();
mInfoList.add(info);
}
selPoiDetailInfo = mInfoList.get(0);
mkolSearchRecords = mOffline.searchCity(selPoiDetailInfo.getCity());
selectCityCode = String.valueOf(mkolSearchRecords.get(0).cityID);
}
handleRelativeAddressResult(mInfoList, changeContent);
}
};
@Override
public void onAddressSelectItemClick(PoiInfo info, int position) {
isUseGeoCoder = false;
isNeedAnimation = true;
mBaiduMap.clear();
LatLng la = info.location;
MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(la);
mBaiduMap.animateMapStatus(u);
selPoiDetailInfo = info;
adapter.changeSelected(position);
if (position != 0) {
mkolSearchRecords = mOffline.searchCity(selPoiDetailInfo.getCity());
selectCityCode = String.valueOf(mkolSearchRecords.get(0).cityID);
}
if (BuildConfig.DEBUG) {
Log.d("lyw", "onAddressSelectItemClick-cityCode->" + info.city+selectCityCode);
}
}
// 定位监听器
private class MyBDLocationListner implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
if (location == null || mBmapView == null){
return;
}
if (isFirstLoc) {
MyLocationData data = new MyLocationData.Builder()
.accuracy(location.getRadius())
.latitude(location.getLatitude())
.longitude(location.getLongitude())
.build();
mBaiduMap.setMyLocationData(data);
MyLocationConfiguration config = new MyLocationConfiguration(
MyLocationConfiguration.LocationMode.NORMAL, false, null);
mBaiduMap.setMyLocationConfigeration(config);
mLantitude = location.getLatitude();
mLongtitude = location.getLongitude();
LatLng currentLatLng = new LatLng(mLantitude, mLongtitude);
mLoactionLatLng = new LatLng(mLantitude, mLongtitude);
isFirstLoc = false;
MapStatusUpdate u = MapStatusUpdateFactory
.newLatLng(currentLatLng);
mBaiduMap.animateMapStatus(u);
mGeoCoder.reverseGeoCode((new ReverseGeoCodeOption())
.location(currentLatLng));
}
}
}
/**
* 地理编码监听器
*/
OnGetGeoCoderResultListener mGeoListener = new OnGetGeoCoderResultListener() {
@Override
public void onGetGeoCodeResult(GeoCodeResult result) {
}
@Override
public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
if (BuildConfig.DEBUG) {
Log.d("lyw","result.error-->" + result.error);
}
if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
if (result.error == SearchResult.ERRORNO.NETWORK_ERROR) {
showLoading(false);
Toast.makeText(SelectAddressActivity.this,"网络异常",Toast.LENGTH_SHORT).show();
}
} else {
showLoading(false);
mCurentInfo = new PoiInfo();
mCurentInfo.address = result.getAddress();
mCurentInfo.location = result.getLocation();
mCurentInfo.name = result.getAddress();
mCurentInfo.city = String.valueOf(result.getCityCode());
selectCityCode = String.valueOf(result.getCityCode());
mInfoList.clear();
mInfoList.add(mCurentInfo);
if (result.getPoiList() != null) {
mInfoList.addAll(result.getPoiList());
}
adapter.setPoiAddrList(mInfoList);
adapter.notifyDataSetChanged();
selPoiDetailInfo = mInfoList.get(0);
}
}
};
class SearchDevicesTextWatcher implements TextWatcher {
@Override
public void beforeTextChanged(CharSequence charSequence, int start, int count, int before) {
}
@Override
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
changeContent = charSequence.toString();
if (changeContent != null && !changeContent.isEmpty() || !"".equals(changeContent)) {
mSuggestionSearch.requestSuggestion(new SuggestionSearchOption().city("中国").keyword(changeContent));
}else {
if (mLoactionLatLng != null) {
MapStatus.Builder builder = new MapStatus.Builder();
builder.target(mLoactionLatLng).zoom(17.0f);
mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus
(builder.build()));
isUseGeoCoder = true;
isNeedAnimation = false;
} else {
}
}
}
@Override
public void afterTextChanged(Editable editable) {
}
}
/**
* 处理搜索地点结果
*
* @param mInfoList
*/
private void handleRelativeAddressResult(List<PoiInfo> mInfoList, String content) {
mJARecyclerView.setAdapter(adapter);
adapter.setPoiAddrList(mInfoList);
if (mInfoList.size() == 0) {
searchNoDataLayout.setVisibility(View.VISIBLE);
String formatContent = String.format("没有找到“%1$s”相关内容", content);
SpannableStringBuilder builder = new SpannableStringBuilder(formatContent);
ForegroundColorSpan blueSpan = new ForegroundColorSpan(getResources().getColor(R.color.src_text_c16));
int start = formatContent.indexOf(content);
int end = start + content.length();
builder.setSpan(blueSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
searchNoDataTv.setText(builder);
} else {
searchNoDataLayout.setVisibility(View.GONE);
}
}
/**
* Loading的显示
* @param isShowLoading
*/
private void showLoading(final boolean isShowLoading){
runOnUiThread(new Runnable() {
@Override
public void run() {
if (isShowLoading) {
mCheckTipIv.setVisibility(View.VISIBLE);
mCheckTipIv.setImageResource(R.mipmap.icon_login_loading);
mCheckTipIv.setAnimation(mAnimation);
mCheckTipIv.getAnimation().start();
}else {
mCheckTipIv.clearAnimation();
mCheckTipIv.setVisibility(View.GONE);
}
}
});
}
}
main_activity_address_select_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.baidu.mapapi.map.MapView
android:id="@+id/bmapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true" />
<ImageView
android:layout_gravity="center"
android:id="@+id/center_image"
android:layout_width="40dp"
android:layout_marginBottom="15dp"
android:layout_height="40dp"
android:src="@mipmap/icon_positioning" />
<ImageView
android:id="@+id/location_iv"
android:layout_gravity="center|end"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginEnd="10dp"
android:src="@mipmap/icon_map_locate" />
<RelativeLayout
android:background="@drawable/background_gradient"
android:paddingTop="35dp"
android:paddingBottom="40dp"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/cancle_tv"
android:textColor="@color/src_white"
android:gravity="center"
android:layout_width="60dp"
android:layout_height="30dp"/>
<TextView
android:id="@+id/confirm_tv"
android:layout_alignParentEnd="true"
android:background="@color/src_c46"
android:gravity="center"
android:textColor="@color/src_white"
android:layout_width="60dp"
android:layout_height="30dp"/>
</RelativeLayout>
<LinearLayout
android:orientation="vertical"
android:background="@color/common_utils_white"
android:layout_gravity="bottom"
android:layout_width="match_parent"
android:layout_height="250dp">
<LinearLayout
android:id="@+id/search_nonmal_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="15dp"
android:layout_marginEnd="15dp"
android:layout_marginBottom="6dp"
android:orientation="horizontal">
<LinearLayout
android:gravity="center"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/common_utils_shape_address_input_white_bg"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="horizontal"
android:paddingTop="7dp"
android:paddingBottom="7dp">
<ImageView
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="13dp"
android:src="@mipmap/icon_search_1"/>
<TextView
android:layout_marginStart="10dp"
android:id="@+id/search_address_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
</LinearLayout>
<!-- 搜索 -->
<LinearLayout
android:visibility="gone"
android:id="@+id/search_edit_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="15dp"
android:layout_marginBottom="6dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/common_utils_shape_address_input_white_bg"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="horizontal"
android:paddingTop="7dp"
android:paddingBottom="7dp">
<ImageView
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="13dp"
android:src="@mipmap/icon_search_1"/>
<EditText
android:id="@+id/search_address_et"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="17dp"
android:layout_weight="1"
android:background="@null"
android:maxLength="32"
android:maxLines="1"
android:singleLine="true"
android:textColor="@color/src_text_c1"
android:textColorHint="@color/src_text_c2"
android:textSize="@dimen/common_utils_font_14"/>
<ImageView
android:id="@+id/clear_input_iv"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="end|center_vertical"
android:layout_marginEnd="13dp"
android:src="@mipmap/icon_clear_enter_1"/>
</LinearLayout>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:layout_below="@+id/search_devices_layout"
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp" />
<LinearLayout
android:layout_below="@+id/search_devices_layout"
android:layout_gravity="center"
android:gravity="center"
android:id="@+id/search_no_data_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/common_utils_white"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:id="@+id/search_no_data_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:textColor="@color/src_text_c2"
android:textSize="14sp"/>
</LinearLayout>
</LinearLayout>
<ImageView
android:id="@+id/check_tip_iv"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginBottom="75dp"
android:layout_gravity="center|bottom"
android:src="@mipmap/icon_login_loading"
/>
</FrameLayout>
background_gradient.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!--实现应用背景颜色渐变-->
<gradient
android:startColor="@color/src_nvr"
android:endColor="@color/common_utils_transparent"
android:angle="270"/>
</shape>
common_utils_shape_address_input_white_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/baidu_serach_address_bg" />
<stroke
android:width="0.5dp"
android:color="@color/common_utils_black_30_transparent" />
<corners android:radius="5dp" />
</shape>
AddressSelectAdapter.class
package com.lyw.myproject.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.baidu.mapapi.search.core.PoiInfo;
import com.lyw.myproject.R;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
/**
* 功能描述:位置选择Adapter
* Created on 2020/4/27.
* @author lyw
*/
public class AddressSelectAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public Context mContext;
private List<PoiInfo> infoList;
private OnAddressSelectItemClickListener mItemClickListener;
private int selectedPosition = 0;// 选中的位置
public AddressSelectAdapter(Context context) {
mContext = context;
infoList = new ArrayList<>();
}
public void changeSelected(int positon){
if(positon != selectedPosition){
selectedPosition = positon;
notifyDataSetChanged();
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
return new MyViewHolder(LayoutInflater.from(mContext).inflate(R.layout.main_item_poi_address,viewGroup,false));
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
MyViewHolder hodler = (MyViewHolder) viewHolder;
PoiInfo info = infoList.get(i);
hodler.nameTv.setText(info.getName());
hodler.addressTv.setText(info.getAddress());
if (selectedPosition == i) {
hodler.checkImageIv.setImageResource(R.mipmap.icon_select_address);
}else {
hodler.checkImageIv.setImageResource(0);
}
}
@Override
public int getItemCount() {
return infoList.size();
}
class MyViewHolder extends RecyclerView.ViewHolder{
TextView nameTv;
TextView addressTv;
ImageView checkImageIv;
LinearLayout addressSelectItemLl;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
nameTv = (TextView)itemView.findViewById(R.id.name_tv);
addressTv = (TextView)itemView.findViewById(R.id.address_tv);
checkImageIv = (ImageView)itemView.findViewById(R.id.check_image_iv);
addressSelectItemLl = (LinearLayout)itemView.findViewById(R.id.address_select_item_ll);
addressSelectItemLl.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mItemClickListener != null) {
int posotion = getAdapterPosition();
mItemClickListener.onAddressSelectItemClick(infoList.get(posotion), posotion);
}
}
});
}
}
public void setPoiAddrList(List<PoiInfo> infos){
infoList = infos;
}
public void clearPoiAddrList(){
infoList.clear();
}
public interface OnAddressSelectItemClickListener{
void onAddressSelectItemClick(PoiInfo info, int position);
}
public void setOnAddressSelectItemClickListener(OnAddressSelectItemClickListener listener){
mItemClickListener = listener;
}
}
main_item_poi_address.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/address_select_item_ll"
android:layout_width="match_parent"
android:padding="10dp"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_marginStart="10dp"
android:orientation="vertical"
android:layout_width="0dp"
android:layout_weight="10"
android:layout_height="wrap_content">
<TextView
android:textSize="16sp"
android:id="@+id/name_tv"
android:textColor="@color/src_black"
android:layout_width="wrap_content"
android:layout_height="20dp"/>
<TextView
android:textSize="14sp"
android:id="@+id/address_tv"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
</LinearLayout>
<LinearLayout
android:layout_gravity="center"
android:layout_weight="1"
android:layout_margin="5dp"
android:layout_width="0dp"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/check_image_iv"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="20dp"/>
</LinearLayout>
</LinearLayout>
DefaultItemDecoration.class
package com.lyw.myproject.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;
import androidx.annotation.ColorRes;
import androidx.annotation.DimenRes;
import androidx.recyclerview.widget.RecyclerView;
/**
* Created on 2018/10/13.
*
* @author lyw
**/
public class DefaultItemDecoration extends RecyclerView.ItemDecoration {
private int mDivideHeight;
private int mPaddingLeft;
private int mPaddingRight;
private Paint paint;
public DefaultItemDecoration(Context context, @DimenRes int divideHeight, @ColorRes int divideColor) {
this(context, divideHeight, divideColor, 0, 0);
}
public DefaultItemDecoration(Context context, @DimenRes int divideHeight, @ColorRes int divideColor, @DimenRes int paddingLeft, @DimenRes int paddingRight) {
mDivideHeight = context.getResources().getDimensionPixelSize(divideHeight);
if (paddingRight != 0) {
mPaddingRight = context.getResources().getDimensionPixelSize(paddingRight);
}
if (paddingLeft != 0) {
mPaddingLeft = context.getResources().getDimensionPixelSize(paddingLeft);
}
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(context.getResources().getColor(divideColor));
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
int childCount = parent.getChildCount();
int width = parent.getWidth();
int top;
int bottom;
for (int i = 0; i < childCount; i++) {
View childAt = parent.getChildAt(i);
top = childAt.getBottom();
bottom = top + mDivideHeight;
c.drawRect(mPaddingLeft, top, width - mPaddingRight, bottom, paint);
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
outRect.bottom = mDivideHeight;
}
}
PermissionUtil.class
package com.lyw.myproject.utils;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import androidx.core.app.ActivityCompat;
/**
* Created by lyw on 2017/6/12.
*/
public class PermissionUtil {
/**
* 请求地理位置
*
* @param context
*/
public static void requestLocationPermission(Context context) {
if (Build.VERSION.SDK_INT >= 23) {
if (!isHasLocationPermission(context)) {
ActivityCompat.requestPermissions((Activity) context, PermissionManager.PERMISSION_LOCATION, PermissionManager.REQUEST_LOCATION);
}
}
}
/**
* 判断是否有地理位置
*
* @param context
* @return
*/
public static boolean isHasLocationPermission(Context context) {
return ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
}
PermissionManager.class
package com.lyw.myproject.utils;
import android.Manifest;
/**
* Created by lyw on 2017/5/17.
*/
public final class PermissionManager {
/**
* sd卡
*/
public static final int REQUEST_SD_WRITE = 101;
/**
* 地理位置
*/
public static final int REQUEST_LOCATION = 102;
/**
* 相机
*/
public static final int REQUEST_CAMERA = 103;
/**
* 录音
*/
public static final int REQUEST_RECORD = 104;
/**
* 读取手机
*/
public static final int REQUEST_READ_PHONE = 105;
/**
* 悬浮窗通知
*/
public static final int REQUEST_ALERT_WINDOW = 106;
/**
* 读取MEDIA权限
*/
public static final int REQUEST_READ_MEDIA = 107;
/**
* Android Q(10) 读取MEDIA权限
*/
public static final String[] PERMISSION_READ_MEDIA = new String[]{"android.permission.READ_MEDIA_IMAGES","android.permission.READ_MEDIA_VIDEO","android.permission.READ_MEDIA_AUDIO"};
public static final String[] PERMISSION_SD_WRITE = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
public static final String[] PERMISSION_LOCATION = new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION};
public static final String[] PERMISSION_CAMERA = new String[]{Manifest.permission.CAMERA};
public static final String[] PERMISSION_RECORD = new String[]{Manifest.permission.RECORD_AUDIO};
public static final String[] PERMISSION_READ_PHONE = new String[]{Manifest.permission.READ_PHONE_STATE};
}
StatusBarUtils.class
package com.lyw.myproject.utils;
import android.app.Activity;
import android.app.Dialog;
import android.graphics.Color;
import android.os.Build;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
/**
* Created by Administrator on 2017/7/6.
* 状态栏相关工具
*/
public class StatusBarUtils {
public static void setWindowStatusBarColor(Activity activity, int colorResId) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(activity.getResources().getColor(colorResId));
//底部导航栏
//window.setNavigationBarColor(activity.getResources().getColor(colorResId));
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void setWindowStatusBarColor(Dialog dialog, int colorResId) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = dialog.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(dialog.getContext().getResources().getColor(colorResId));
//底部导航栏
//window.setNavigationBarColor(activity.getResources().getColor(colorResId));
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void makeStatusBarTransparent(Activity activity) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
Window window = activity.getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
int option = window.getDecorView().getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
window.getDecorView().setSystemUiVisibility(option);
window.setStatusBarColor(Color.TRANSPARENT);
} else {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
}
center_anim.xml
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fillBefore="true"
android:fromXDelta="0"
android:fromYDelta="0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toXDelta="0"
android:toYDelta="-100">
</translate>
FullscreenInputWorkaroundUtil.class
package com.lyw.myproject.utils;
import android.app.Activity;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
/**
* 功能描述:解决状态栏沉浸式,软键盘遮住布局的问题
* Created on 2020/6/18.
*
* @author lyw
*/
public class FullscreenInputWorkaroundUtil {
public static void assistActivity(Activity activity) {
new FullscreenInputWorkaroundUtil(activity);
}
private View mChildOfContent;
private int usableHeightPrevious;
private FrameLayout.LayoutParams frameLayoutParams;
private FullscreenInputWorkaroundUtil(Activity activity) {
FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
mChildOfContent = content.getChildAt(0);
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
possiblyResizeChildOfContent();
}
});
frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
}
private void possiblyResizeChildOfContent() {
int usableHeightNow = computeUsableHeight();
if (usableHeightNow != usableHeightPrevious) {
int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
int heightDifference = usableHeightSansKeyboard - usableHeightNow;
if (heightDifference > (usableHeightSansKeyboard / 4)) {
frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
} else {
frameLayoutParams.height = usableHeightSansKeyboard;
}
mChildOfContent.requestLayout();
usableHeightPrevious = usableHeightNow;
}
}
private int computeUsableHeight() {
Rect r = new Rect();
mChildOfContent.getWindowVisibleDisplayFrame(r);
return (r.bottom - r.top);
}
}