如何自定义PlaceAutocomplete小部件对话框设计以列出地点

高贵的

我需要显示dropdown使用GoogleplaceAutocomplete窗口小部件的位置列表在这里,我得到一个对话框来根据我的查询显示位置,但是我需要像在Uber,Ola应用程序中那样为该搜索结果对话框提供自定义设计。在这里,我要像下面的图片一样设计。如果有人在此之前做过,请给我您的建议,谢谢。

在此处输入图片说明

阿努·夏尔马(Anuj Sharma)

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

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

您要在适配器中显示的自定义视图

<?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密钥

输出将如下所示:

在此处输入图片说明

我发现了一些有用的链接也可以为您提供帮助。

1.使用自定义适配器的Android Plat Places

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Android自定义对话框设计

来自分类Dev

如何更改打开对话框的图像以及如何自定义对话框?

来自分类Dev

如何从自定义对话框中删除标题?

来自分类Dev

如何自定义放置Jquery对话框

来自分类Dev

如何制作更好的自定义对话框?

来自分类Dev

如何制作自定义Cast MediaRouter对话框

来自分类Dev

如何自定义对话框的标题部分

来自分类Dev

WPF:如何使自定义模式对话框闪烁?

来自分类Dev

如何创建自定义材质对话框

来自分类Dev

DialogResult或如何创建自定义对话框

来自分类Dev

如何自定义对话框的标题部分

来自分类Dev

如何创建自定义对话框

来自分类Dev

如何从自定义对话框中删除标题?

来自分类Dev

如何从自定义对话框中删除标题?

来自分类Dev

如何自定义对话框宽度?

来自分类Dev

如何自定义警报对话框,以使按钮适合警报对话框

来自分类Dev

WXPYTHON自定义对话框

来自分类Dev

自定义对话框片段

来自分类Dev

自定义对话框太小

来自分类Dev

自定义进度对话框

来自分类Dev

自定义对话框错误

来自分类Dev

自定义引导对话框

来自分类Dev

自定义对话框的布局

来自分类Dev

是否可以在不使用自定义窗口小部件的情况下将单个对话框字段映射到多个JCR属性?

来自分类Dev

“插入函数”对话框中未列出 JS 自定义函数

来自分类Dev

如何在自定义对话框中设置自定义按钮?

来自分类Dev

如何在自定义对话框中设置自定义按钮?

来自分类Dev

Android设计可图标化的自定义对话框布局

来自分类Dev

如何自定义android小部件