1. 涉及到的技术点
- RecyclerView列表控件的使用
- 使用网络请求库okgo调用搜索API
- RecyclerView+Adapter实现滑动列表
2. 代码实现过程
- 编写搜索布局页面activity_search.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".SearchActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/purple_200"
app:navigationIcon="@drawable/ic_baseline_arrow_back_ios_new_24"
app:title="搜索"
app:titleTextColor="@color/white" />
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_margin="10dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="10dp"
android:paddingRight="10dp">
<EditText
android:id="@+id/et_search_city"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toLeftOf="@id/btn_search"
android:background="@null"
android:drawableLeft="@drawable/ic_baseline_black_search_24"
android:hint="搜索城市"
android:textSize="14sp" />
<TextView
android:id="@+id/btn_search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:padding="10dp"
android:text="搜索" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/city_list_item"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/img_empty" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="空空如也~"
android:textColor="#999999" />
</androidx.appcompat.widget.LinearLayoutCompat>
</RelativeLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
- 搜索页面SearchActivity.java
public class SearchActivity extends AppCompatActivity {
private EditText et_search_city;
private RecyclerView recyclerView;
private LinearLayoutCompat ll_empty;
private SearchListAdapter mSearchListAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
initViews();
mSearchListAdapter = new SearchListAdapter();
recyclerView.setAdapter(mSearchListAdapter);
setListener();
}
private void initViews() {
et_search_city = findViewById(R.id.et_search_city);
recyclerView = findViewById(R.id.recyclerView);
ll_empty = findViewById(R.id.ll_empty);
}
private void setListener() {
findViewById(R.id.btn_search).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String cityName = et_search_city.getText().toString().trim();
if (cityName.isEmpty()) {
Toast.makeText(SearchActivity.this, "城市名不能为空", Toast.LENGTH_SHORT).show();
} else {
searchCity(cityName);
}
}
});
findViewById(R.id.toolbar).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
mSearchListAdapter.setOnItemClickListener(new SearchListAdapter.OnItemClickListener() {
@Override
public void onItemClick(CityLocationInfo.LocationDTO locationDTO) {
String cityName = locationDTO.getName();
Intent intent = new Intent();
intent.putExtra("cityName", cityName);
intent.putExtra("id", locationDTO.getId());
setResult(1000, intent);
finish();
}
});
}
private void searchCity(String cityName) {
OkGo.<String>get("https://geoapi.qweather.com/v2/city/lookup").params("location", cityName).params("key", ApiConstants.APP_KEY).execute(new StringCallback() {
@Override
public void onStart(Request<String, ? extends Request> request) {
super.onStart(request);
ProgressDialogUtils.showProgressDialog(SearchActivity.this);
}
@Override
public void onSuccess(Response<String> response) {
CityLocationInfo cityLocationInfo = new Gson().fromJson(response.body(), CityLocationInfo.class);
if (null != cityLocationInfo && cityLocationInfo.getCode().equals("200")) {
if (null != mSearchListAdapter) {
mSearchListAdapter.setCityLocationInfoList(cityLocationInfo.getLocation());
}
if (mSearchListAdapter.getItemCount() > 0) {
ll_empty.setVisibility(View.GONE);
} else {
ll_empty.setVisibility(View.VISIBLE);
}
} else {
Toast.makeText(SearchActivity.this, "未查询到该城市", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onError(Response<String> response) {
super.onError(response);
}
@Override
public void onFinish() {
super.onFinish();
ProgressDialogUtils.hideProgressDialog();
}
});
}
}
- 适配器SearchListAdapter.java
public class SearchListAdapter extends RecyclerView.Adapter<SearchListAdapter.MyHolder> {
private List<CityLocationInfo.LocationDTO> mCityLocationInfoList = new ArrayList<>();
public void setCityLocationInfoList(List<CityLocationInfo.LocationDTO> cityLocationInfoList) {
this.mCityLocationInfoList = cityLocationInfoList;
notifyDataSetChanged();
}
@NonNull
@Override
public MyHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.city_list_item, parent, false);
return new MyHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MyHolder holder, int position) {
CityLocationInfo.LocationDTO locationDTO = mCityLocationInfoList.get(position);
holder.tv_city_name.setText(locationDTO.getName() + "," + locationDTO.getAdm1() + "," + locationDTO.getCountry());
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (null != mOnItemClickListener) {
mOnItemClickListener.onItemClick(locationDTO);
}
}
});
}
@Override
public int getItemCount() {
return mCityLocationInfoList.size();
}
static class MyHolder extends RecyclerView.ViewHolder {
TextView tv_city_name;
public MyHolder(@NonNull View itemView) {
super(itemView);
tv_city_name = itemView.findViewById(R.id.tv_city_name);
}
}
private OnItemClickListener mOnItemClickListener;
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.mOnItemClickListener = onItemClickListener;
}
public interface OnItemClickListener {
void onItemClick(CityLocationInfo.LocationDTO locationDTO);
}
}
- 数据实体类CityLocationInfo.java
public class CityLocationInfo {
private String code;
private List<LocationDTO> location;
private ReferDTO refer;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public List<LocationDTO> getLocation() {
return location;
}
public void setLocation(List<LocationDTO> location) {
this.location = location;
}
public ReferDTO getRefer() {
return refer;
}
public void setRefer(ReferDTO refer) {
this.refer = refer;
}
public static class ReferDTO {
private List<String> sources;
private List<String> license;
public List<String> getSources() {
return sources;
}
public void setSources(List<String> sources) {
this.sources = sources;
}
public List<String> getLicense() {
return license;
}
public void setLicense(List<String> license) {
this.license = license;
}
}
public static class LocationDTO {
private String name;
private String id;
private String lat;
private String lon;
private String adm2;
private String adm1;
private String country;
private String tz;
private String utcOffset;
private String isDst;
private String type;
private String rank;
private String fxLink;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getLat() {
return lat;
}
public void setLat(String lat) {
this.lat = lat;
}
public String getLon() {
return lon;
}
public void setLon(String lon) {
this.lon = lon;
}
public String getAdm2() {
return adm2;
}
public void setAdm2(String adm2) {
this.adm2 = adm2;
}
public String getAdm1() {
return adm1;
}
public void setAdm1(String adm1) {
this.adm1 = adm1;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getTz() {
return tz;
}
public void setTz(String tz) {
this.tz = tz;
}
public String getUtcOffset() {
return utcOffset;
}
public void setUtcOffset(String utcOffset) {
this.utcOffset = utcOffset;
}
public String getIsDst() {
return isDst;
}
public void setIsDst(String isDst) {
this.isDst = isDst;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getRank() {
return rank;
}
public void setRank(String rank) {
this.rank = rank;
}
public String getFxLink() {
return fxLink;
}
public void setFxLink(String fxLink) {
this.fxLink = fxLink;
}
}
}
- 适配器所需要的布局文件 city_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<TextView
android:id="@+id/tv_city_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="北京市"
android:textColor="#333333"
android:textSize="16sp" />
</androidx.cardview.widget.CardView>
</androidx.appcompat.widget.LinearLayoutCompat>
3. 运行效果图
![请添加图片描述](https://i-blog.csdnimg.cn/direct/03add416369d47058c88c44794c96b1a.png)