gpt4 book ai didi

android - 如何自定义放置自动完成小部件对话框设计以列出位置

转载 作者:IT老高 更新时间:2023-10-28 22:02:11 24 4
gpt4 key购买 nike

我需要使用 google placeAutocomplete 小部件在 dropdown 中显示地点列表。在这里,我正在根据我的查询显示位置的对话框,但我需要为该搜索结果对话框提供自定义设计,如在 Uber、Ola 应用程序中。在这里,我想要一个如下图所示的设计。如果有人以前这样做过,请给我您的建议,提前谢谢。

enter image description here

最佳答案

您需要自定义适配器。我已经在我的项目中实现了这个功能。你可以按照这个。

activity_search.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/white">

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:id="@+id/search_layout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center_vertical"
android:layout_alignParentTop="true"
android:background="@drawable/searchbar_bg"
android:layout_marginLeft="@dimen/activity_margin_10"
android:layout_marginRight="@dimen/activity_margin_10"
android:layout_marginTop="@dimen/activity_margin_10"
android:orientation="vertical">

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/search_et"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:hint="Search"
android:singleLine="true"
android:layout_toLeftOf="@+id/clear"
android:imeOptions="actionSearch"
android:background="@null"
android:drawableLeft="@drawable/ic_action_search"
android:drawablePadding="@dimen/activity_margin_10"
android:paddingLeft="@dimen/activity_margin_10"
android:paddingRight="@dimen/activity_margin_10"/>
<ImageView
android:id="@+id/clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_clear"
android:layout_alignParentRight="true"
android:layout_gravity="right|center_vertical"
android:padding="@dimen/activity_margin_16"
android:visibility="gone"/>
</RelativeLayout>


</LinearLayout>


<android.support.v7.widget.RecyclerView
android:id="@+id/list_search"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/search_layout"
android:layout_above="@+id/powered_by_google"
android:background="@color/white"
android:layout_marginTop="@dimen/activity_margin_10"/>

<ImageView
android:id="@+id/powered_by_google"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:padding="@dimen/activity_margin_10"
android:layout_marginBottom="@dimen/activity_margin_10"
android:src="@drawable/powered_by_google_light"/>
</RelativeLayout>
</LinearLayout>

SearchActivity.java

package com.android.dezi.views.rider.Activities;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;

import com.android.dezi.BaseActivity;
import com.android.dezi.R;
import com.android.dezi.adapters.PlaceAutocompleteAdapter;
import com.android.dezi.adapters.PlaceAutocompleteAdapter.PlaceAutoCompleteInterface;
import com.android.dezi.adapters.PlaceSavedAdapter;
import com.android.dezi.adapters.PlaceSavedAdapter.SavedPlaceListener;
import com.android.dezi.beans.SavedAddress;
import com.android.dezi.views.rider.Fragments.SearchFragment;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.places.Place;
import com.google.android.gms.location.places.PlaceBuffer;
import com.google.android.gms.location.places.Places;
import com.google.android.gms.location.places.ui.PlaceAutocomplete;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;

import java.util.ArrayList;
import java.util.List;

/**
* Created by anuj.sharma on 4/6/2016.
*/
public class SearchActivity extends BaseActivity implements PlaceAutoCompleteInterface, GoogleApiClient.OnConnectionFailedListener,
GoogleApiClient.ConnectionCallbacks,OnClickListener,SavedPlaceListener {
Context mContext;
GoogleApiClient mGoogleApiClient;

LinearLayout mParent;
private RecyclerView mRecyclerView;
LinearLayoutManager llm;
PlaceAutocompleteAdapter mAdapter;
List<SavedAddress> mSavedAddressList;
PlaceSavedAdapter mSavedAdapter;
private static final LatLngBounds BOUNDS_INDIA = new LatLngBounds(
new LatLng(-0, 0), new LatLng(0, 0));

EditText mSearchEdittext;
ImageView mClear;

@Override
public void onStart() {
mGoogleApiClient.connect();
super.onStart();

}

@Override
public void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_search);
mContext = SearchActivity.this;

mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this, 0 /* clientId */, this)
.addApi(Places.GEO_DATA_API)
.build();

initViews();
}

/*
Initialize Views
*/
private void initViews(){
mRecyclerView = (RecyclerView)findViewById(R.id.list_search);
mRecyclerView.setHasFixedSize(true);
llm = new LinearLayoutManager(mContext);
mRecyclerView.setLayoutManager(llm);

mSearchEdittext = (EditText)findViewById(R.id.search_et);
mClear = (ImageView)findViewById(R.id.clear);
mClear.setOnClickListener(this);

mAdapter = new PlaceAutocompleteAdapter(this, R.layout.view_placesearch,
mGoogleApiClient, BOUNDS_INDIA, null);
mRecyclerView.setAdapter(mAdapter);

mSearchEdittext.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (count > 0) {
mClear.setVisibility(View.VISIBLE);
if (mAdapter != null) {
mRecyclerView.setAdapter(mAdapter);
}
} else {
mClear.setVisibility(View.GONE);
if (mSavedAdapter != null && mSavedAddressList.size() > 0) {
mRecyclerView.setAdapter(mSavedAdapter);
}
}
if (!s.toString().equals("") && mGoogleApiClient.isConnected()) {
mAdapter.getFilter().filter(s.toString());
} else if (!mGoogleApiClient.isConnected()) {
// Toast.makeText(getApplicationContext(), Constants.API_NOT_CONNECTED, Toast.LENGTH_SHORT).show();
Log.e("", "NOT CONNECTED");
}
}

@Override
public void afterTextChanged(Editable s) {

}
});

}

@Override
public void onClick(View v) {
if(v == mClear){
mSearchEdittext.setText("");
if(mAdapter!=null){
mAdapter.clearList();
}

}
}



@Override
public void onConnected(Bundle bundle) {

}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {

}

@Override
public void onPlaceClick(ArrayList<PlaceAutocompleteAdapter.PlaceAutocomplete> mResultList, int position) {
if(mResultList!=null){
try {
final String placeId = String.valueOf(mResultList.get(position).placeId);
/*
Issue a request to the Places Geo Data API to retrieve a Place object with additional details about the place.
*/

PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi
.getPlaceById(mGoogleApiClient, placeId);
placeResult.setResultCallback(new ResultCallback<PlaceBuffer>() {
@Override
public void onResult(PlaceBuffer places) {
if(places.getCount()==1){
//Do the things here on Click.....
Intent data = new Intent();
data.putExtra("lat",String.valueOf(places.get(0).getLatLng().latitude));
data.putExtra("lng", String.valueOf(places.get(0).getLatLng().longitude));
setResult(SearchActivity.RESULT_OK, data);
finish();
}else {
Toast.makeText(getApplicationContext(),"something went wrong",Toast.LENGTH_SHORT).show();
}
}
});
}
catch (Exception e){

}

}
}

@Override
public void onSavedPlaceClick(List<SavedAddress> mResponse, int position) {
if(mResponse!=null){
try {
Intent data = new Intent();
data.putExtra("lat",String.valueOf(mResponse.get(position).getLatitude()));
data.putExtra("lng", String.valueOf(mResponse.get(position).getLongitude()));
setResult(SearchActivity.RESULT_OK, data);
finish();
}
catch (Exception e){

}

}
}
}

PlaceAutocompleteAdapter.java

这是定制的适配器。所有重要的部分都在里面。

package com.android.dezi.adapters;

import android.content.Context;
import android.graphics.Typeface;
import android.support.v7.widget.RecyclerView;
import android.text.style.CharacterStyle;
import android.text.style.StyleSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.android.dezi.R;
import com.android.dezi.beans.TripHistoryBean;
import com.android.dezi.views.rider.Fragments.SearchFragment;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.common.data.DataBufferUtils;
import com.google.android.gms.location.places.AutocompleteFilter;
import com.google.android.gms.location.places.AutocompletePrediction;
import com.google.android.gms.location.places.AutocompletePredictionBuffer;
import com.google.android.gms.location.places.Places;
import com.google.android.gms.maps.model.LatLngBounds;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
* Created by anuj.sharma on 4/6/2016.
*/
public class PlaceAutocompleteAdapter extends RecyclerView.Adapter<PlaceAutocompleteAdapter.PlaceViewHolder> implements Filterable{

public interface PlaceAutoCompleteInterface{
public void onPlaceClick(ArrayList<PlaceAutocomplete> mResultList, int position);
}

Context mContext;
PlaceAutoCompleteInterface mListener;
private static final String TAG = "PlaceAutocompleteAdapter";
private static final CharacterStyle STYLE_BOLD = new StyleSpan(Typeface.BOLD);
ArrayList<PlaceAutocomplete> mResultList;

private GoogleApiClient mGoogleApiClient;

private LatLngBounds mBounds;

private int layout;

private AutocompleteFilter mPlaceFilter;


public PlaceAutocompleteAdapter(Context context, int resource, GoogleApiClient googleApiClient,
LatLngBounds bounds, AutocompleteFilter filter){
this.mContext = context;
layout = resource;
mGoogleApiClient = googleApiClient;
mBounds = bounds;
mPlaceFilter = filter;
this.mListener = (PlaceAutoCompleteInterface)mContext;
}

/*
Clear List items
*/
public void clearList(){
if(mResultList!=null && mResultList.size()>0){
mResultList.clear();
}
}


/**
* Sets the bounds for all subsequent queries.
*/
public void setBounds(LatLngBounds bounds) {
mBounds = bounds;
}

@Override
public Filter getFilter() {
Filter filter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
// Skip the autocomplete query if no constraints are given.
if (constraint != null) {
// Query the autocomplete API for the (constraint) search string.
mResultList = getAutocomplete(constraint);
if (mResultList != null) {
// The API successfully returned results.
results.values = mResultList;
results.count = mResultList.size();
}
}
return results;
}

@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
// The API returned at least one result, update the data.
notifyDataSetChanged();
} else {
// The API did not return any results, invalidate the data set.
//notifyDataSetInvalidated();
}
}
};
return filter;
}

private ArrayList<PlaceAutocomplete> getAutocomplete(CharSequence constraint) {
if (mGoogleApiClient.isConnected()) {
Log.i("", "Starting autocomplete query for: " + constraint);

// Submit the query to the autocomplete API and retrieve a PendingResult that will
// contain the results when the query completes.
PendingResult<AutocompletePredictionBuffer> results =
Places.GeoDataApi
.getAutocompletePredictions(mGoogleApiClient, constraint.toString(),
mBounds, mPlaceFilter);

// This method should have been called off the main UI thread. Block and wait for at most 60s
// for a result from the API.
AutocompletePredictionBuffer autocompletePredictions = results
.await(60, TimeUnit.SECONDS);

// Confirm that the query completed successfully, otherwise return null
final Status status = autocompletePredictions.getStatus();
if (!status.isSuccess()) {
// Toast.makeText(mContext, "Error contacting API: " + status.toString(),
// Toast.LENGTH_SHORT).show();
Log.e("", "Error getting autocomplete prediction API call: " + status.toString());
autocompletePredictions.release();
return null;
}

Log.i("", "Query completed. Received " + autocompletePredictions.getCount()
+ " predictions.");

// Copy the results into our own data structure, because we can't hold onto the buffer.
// AutocompletePrediction objects encapsulate the API response (place ID and description).

Iterator<AutocompletePrediction> iterator = autocompletePredictions.iterator();
ArrayList resultList = new ArrayList<>(autocompletePredictions.getCount());
while (iterator.hasNext()) {
AutocompletePrediction prediction = iterator.next();
// Get the details of this prediction and copy it into a new PlaceAutocomplete object.
resultList.add(new PlaceAutocomplete(prediction.getPlaceId(),
prediction.getDescription()));
}

// Release the buffer now that all data has been copied.
autocompletePredictions.release();

return resultList;
}
Log.e("", "Google API client is not connected for autocomplete query.");
return null;
}

@Override
public PlaceViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View convertView = layoutInflater.inflate(layout, viewGroup, false);
PlaceViewHolder mPredictionHolder = new PlaceViewHolder(convertView);
return mPredictionHolder;
}


@Override
public void onBindViewHolder(PlaceViewHolder mPredictionHolder, final int i) {
mPredictionHolder.mAddress.setText(mResultList.get(i).description);

mPredictionHolder.mParentLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mListener.onPlaceClick(mResultList,i);
}
});

}

@Override
public int getItemCount() {
if(mResultList != null)
return mResultList.size();
else
return 0;
}

public PlaceAutocomplete getItem(int position) {
return mResultList.get(position);
}

/*
View Holder For Trip History
*/
public class PlaceViewHolder extends RecyclerView.ViewHolder {
// CardView mCardView;
public RelativeLayout mParentLayout;
public TextView mAddress;

public PlaceViewHolder(View itemView) {
super(itemView);
mParentLayout = (RelativeLayout)itemView.findViewById(R.id.predictedRow);
mAddress = (TextView)itemView.findViewById(R.id.address);
}

}

/**
* Holder for Places Geo Data Autocomplete API results.
*/
public class PlaceAutocomplete {

public CharSequence placeId;
public CharSequence description;

PlaceAutocomplete(CharSequence placeId, CharSequence description) {
this.placeId = placeId;
this.description = description;
}

@Override
public String toString() {
return description.toString();
}
}
}

view_placesearch.xml

您想在适配器中显示的自定义 View

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/predictedRow"
android:layout_width="match_parent"
android:layout_height="65dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_centerVertical="true"
android:gravity="center_vertical">

<ImageView
android:id="@+id/image"
android:layout_width="22dp"
android:layout_height="22dp"
android:src="@drawable/ic_action_navigate"
android:layout_marginLeft="10dp"
android:layout_marginTop="20dp"
/>

<TextView
android:id="@+id/address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#000"
android:textSize="15sp"
android:layout_toRightOf="@+id/image"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/light_gray"
android:layout_alignParentBottom="true"/>
</RelativeLayout>

希望对你也有帮助。

注意:不要忘记在 manifest 文件中添加 API key 。

输出如下:

enter image description here

我找到了一些有用的链接,它们也可以帮助你。

1. Android Plat Places using custom Adapter

关于android - 如何自定义放置自动完成小部件对话框设计以列出位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36999647/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com