还是比较简单的,然后进入到MapWeatherActivity
ImageView ivSearch;//搜索图标
@BindView(R.id.ed_search)
EditText edSearch;//搜索输入框
@BindView(R.id.iv_close)
ImageView ivClose;//关闭图标
@BindView(R.id.lay_search)
RelativeLayout laySearch;//搜索布局
定义一个控制变量
private AutoTransition autoTransition;//过渡动画
private Animation bigShowAnim;//放大显示
private Animation smallHideAnim;//缩小隐藏
private int width;//屏幕宽度
private boolean isOpen = false;//顶部搜索布局的状态
然后在点击方法中增加需求点击的控件id
因为展开之后是不能设置固定的宽度,所以需要获取屏幕的宽度,在initView方法中写入
//获取屏幕宽高
WindowManager manager = getWindowManager();
DisplayMetrics metrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(metrics);
width = metrics.widthPixels; //获取屏幕的宽度 像素
而屏幕的宽度是px又需要转换为dip,所以要写转换的方法;
// dp 转成 px
private int dip2px(float dpVale) {
final float scale = getResources().getDisplayMetrics().density;
return (int) (dpVale * scale + 0.5f);
}
// px 转成 dp
private int px2dip(float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
然后写一个过渡动画的方法,会在展开和收缩的方法中调用
//过渡动画
@TargetApi(Build.VERSION_CODES.KITKAT)
private void beginDelayedTransition(ViewGroup view) {
autoTransition = new AutoTransition();
autoTransition.setDuration(500);
TransitionManager.beginDelayedTransition(view,autoTransition);
}
现在可以来写具体的关于点击展开和收缩的方法了。
/**
- 展开
*/
public void initExpand() {
isOpen = true;
edSearch.setVisibility(View.VISIBLE);//显示输入框
ivClose.setVisibility(View.VISIBLE);//显示关闭按钮
LinearLayout.LayoutParams LayoutParams = (LinearLayout.LayoutParams) laySearch.getLayoutParams();
LayoutParams.width = dip2px(px2dip(width) - 24);//设置展开的宽度
LayoutParams.setMargins(dip2px(0), dip2px(0), dip2px(0), dip2px(0));
laySearch.setPadding(14, 0, 14, 0);
laySearch.setLayoutParams(LayoutParams);
//开始动画
beginDelayedTransition(laySearch);
if (markerLatitude != 0) {//手动定位时
btnAutoLocation.hide();//隐藏自动定位按钮
}
}
这里做一下简单的说明LayoutParams.width = dip2px(px2dip(width) - 24);//设置展开的宽度这里我先将屏幕的宽由px转dp,然后剪去24,24就是屏幕左右各12的边距,然后再转成px赋值给LayoutParams.width,这样LayoutParams就知道我这个控件到时候要展开多大了。而我在开始动画的时候也加了一个对于定位按钮的判断,因为这个控件和定位按钮在同一水平线上,又因为底层的布局用的是FrameLayout,所以会出现覆盖的情况,这并不是我想要的,所以我加了一个控制,如果展开的时候处于手动定位则隐藏自动定位按钮,当然我也在收缩的方法里面做了相应的处理,下面来看收缩的方法。
/**
- 收缩
*/
private void initClose() {
isOpen = false;
edSearch.setVisibility(View.GONE);
edSearch.setText(“”);
ivClose.setVisibility(View.GONE);
LinearLayout.LayoutParams LayoutParams = (LinearLayout.LayoutParams) laySearch.getLayoutParams();
LayoutParams.width = dip2px(48);
LayoutParams.height = dip2px(48);
LayoutParams.setMargins(dip2px(0), dip2px(0), dip2px(0), dip2px(0));
laySearch.setLayoutParams(LayoutParams);
//隐藏键盘
InputMethodManager inputMethodManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(this.getWindow().getDecorView().getWindowToken(), 0);
//开始动画
beginDelayedTransition(laySearch);
if (markerLatitude != 0) {//自动定位
btnAutoLocation.show();//隐藏自动定位按钮
}
}
当然我们需要在点击的时候调用这两个方法
收缩的方法比较的简单一些,加了收缩时关闭键盘的动作。下面演示一下
重点注意看上边的效果。下面要对输入框做一下简单的控制,
在initView中增加
/**
- 输入法键盘的搜索监听
*/
edSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
String city = edSearch.getText().toString();
if (!TextUtils.isEmpty(city)) {
//得到输入的内容
} else {
ToastUtils.showShortToast(context, “请输入城市名称”);
}
}
return false;
}
});
这里其实就是对输入法简单的回车按钮的监听,这也是现在很多app的通用做法,不需要再自己去写一个搜索按钮来控制,而使用输入法的回车键作为搜索按钮,那么是怎么改的呢?通过布局
相信你已经知道了,好的,我在点击搜索的时候获取输入框的内容,为空则提示一下,不为空就获取内容,那么获取到的内容要怎么办呢?首先想一下获取到的是什么内容?当然是城市的名称了,可以是区/县、市。那么得到这个数据就去直接通过搜索城市拿到城市id,再通过城市id去请求天气数据吗?这样是可以的,但是忽略了地图,你不要忘记了,这个页面是地图天气,所以要和地图有联动才行啊。回想一下之前我通过定位获取到坐标,通过坐标拿到了城市的具体信息,那么反过来通过地址信息,拿到坐标,再把坐标渲染在地图上,通过定位到这个坐标,听起来是不是觉得比较难?实际上真的难吗?你只要想清楚逻辑,剩下的就是实现而已了。下面来看看怎么实现的吧。
通过这个做解析,不光是坐标转地址,也可以地址转坐标
在输入法搜索按钮点击后,获取到的内容不为空则进行地址的解析,new一个GeoCodeOpting(),传入城市和地址,这里可以传同样的值。那么解析的结果呢?
要知道我之前就给这个编码结果做了监听,当时只在onGetReverseGeoCodeResult中做了处理,因为这个返回是负责坐标转地址的。而onGetGeoCodeResult是负责地址转坐标的。很好,这正是我想要的。我在返回值中做了一些简单的处理,如果解析不到数据我们就认定你输入的城市名有问题,提示你一下并清空这个输入框让你重新输入,如果输入的内容没啥问题,我们就获取坐标,然后打印出地址和经纬度。你可以自己运行试一下绝对就是这样的,OK,既然现在拿到了坐标那就可以定位了对不对,先来看看之前的地图上手动定位绘制标点的代码
这里你还记得吗?在点击地图是重新绘制,然后标点,最后重新定位的,那么你同样可以把这一段代码复制过去那边,就可以了,不过为了不写重新代码,可以写一个方法两个地方使用,反正你只要传入一个坐标的对象就可以了,不是吗?方法如下:
/**
-
重新定位
-
@param latLng 坐标
*/
private void resetLocation(LatLng latLng) {
bitmap = BitmapDescriptorFactory.fromResource(R.mipmap.icon_marka);// 设置marker图标
//通过LatLng获取经纬度
markerLatitude = latLng.latitude;//获取纬度
markerLongitude = latLng.longitude;//获取经度
mBaiduMap.clear();//清除之前的图层
MarkerOptions options = new MarkerOptions()//创建标点marker设置对象
.position(latLng)//设置标点的定位
.icon(bitmap);//设置标点图标
marker = (Marker) mBaiduMap.addOverlay(options);//在地图上显示标点
//重新定位
initLocation();
}
调用
然后再回到之前通过位置获取到坐标的那个返回方法里调用即可
这里我还多加了一个关闭搜索布局的方法代码。来运行一下吧。
你以为这就完了吗?当然没有!我真是猜不透我自己啊!哈哈哈哈!
OK,我们还需要与这个底部控件做协调,比如我们之前有过这样一个操作就是当手动定位时,拖动底部布局到顶部然后隐藏这个按钮,回到底部时显示这个按钮,那么同理我是不是也应该对这个搜索布局做同样的事呢?当然了,当然了,裤衩着火,裆燃了。最近相声听得比较多,学到了这么一句俏皮话。
好的,继续往下看啊,因为我用的不是浮动按钮,所以就没有默认的动画了,那么就需要自己来写动画效果,这个其实也不难啊。
在mvplibrary中的anim包下新建两个动画xml文件
scale_big_expand.xml
<?xml version="1.0" encoding="utf-8"?><scale xmlns:android=“http://schemas.android.com/apk/res/android”
android:duration=“200”
android:fromXScale=“0”
android:fromYScale=“0”
android:pivotX=“50%”
android:pivotY=“50%”
android:toXScale=“1”
android:toYScale=“1” />
scale_small_close.xml
<?xml version="1.0" encoding="utf-8"?><scale xmlns:android=“http://schemas.android.com/apk/res/android”
android:duration=“200”
android:fromXScale=“1”
android:fromYScale=“1”
android:pivotX=“50%”
android:pivotY=“50%”
android:toXScale=“0”
android:toYScale=“0” />
然后回到MapWeatherActivity,在initView中增加
//放大
bigShowAnim = AnimationUtils.loadAnimation(context, R.anim.scale_big_expand);
//缩小
smallHideAnim = AnimationUtils.loadAnimation(context, R.anim.scale_small_close);
可以看到这里加了动画的xml,下面就要写一个方法用于控制显示和隐藏分别调用不用的动画,方法如下:
/**
-
缩放动画
-
@param view 需要缩放的控件
-
@param state 状态 显示或者隐藏
*/
private void scaleAnimation(View view,String state) {
switch (state){
case “show”:
view.startAnimation(bigShowAnim);
view.setVisibility(View.VISIBLE);
break;
case “hide”:
view.startAnimation(smallHideAnim);
smallHideAnim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
view.setVisibility(View.GONE);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
break;
文末
面试:如果不准备充分的面试,完全是浪费时间,更是对自己的不负责!
不管怎么样,不论是什么样的大小面试,要想不被面试官虐的不要不要的,只有刷爆面试题题做好全面的准备,当然除了这个还需要在平时把自己的基础打扎实,这样不论面试官怎么样一个知识点里往死里凿,你也能应付如流啊
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!