簡體   English   中英

Android Place Autocomplete Fragment:無法設置文本

[英]Android Place Autocomplete Fragment: Unable to set text

谷歌最近更新了他們的安卓版 Places SDK,所以現在我也在更新我的代碼。 我正在嘗試使用AutocompleteSupportFragment來允許用戶設置他們的地址。

這是我的代碼:

mAddressEditText = (AutocompleteSupportFragment) getSupportFragmentManager().findFragmentById(R.id.address);
mAddressEditText.setPlaceFields(Arrays.asList(Place.Field.ADDRESS, Place.Field.LAT_LNG));
mAddressEditText.setHint("Address");
mAddressEditText.setText("Test1");                      // Works fine at the beginning, disappears after selecting a place and shows only the hint
mAddressEditText.setOnPlaceSelectedListener(new PlaceSelectionListener() {
    @Override
    public void onPlaceSelected(Place place) {
        Log.d(TAG, "Place Selected");
        // Other Stuff
        mAddressEditText.setText("Test2");              // Doesn't Work, all I can see is the hint
        mAddressEditText.setText(place.getAddress());   // Doesn't Work, all I can see is the hint
    }

    @Override
    public void onError(Status status) {
        Log.e(TAG, "An error occurred: " + status);
        invalidAddressDialog.show();
    }
});

在之前的 SDK 中,片段會自動將文本設置為所選地址。 這在新的 SDK 中不起作用(不確定這是否是故意的)。 所以我試圖手動設置它。 正如您在我的代碼的注釋中看到的那樣,在偵聽器之外使用setText工作正常。 在聽眾內部,他們沒有。

我做錯了什么還是這是一個錯誤?

編輯:這么長時間,我仍然無法解決這個問題。 完全清楚,我可以從片段中正確獲取地址,唯一不起作用的是setText

然而,由於一些答案表明他們沒有遇到同樣的問題,我開始認為這可能與我使用的庫版本有關?

這些是我在build.gradle中的庫:

api 'com.android.support:appcompat-v7:28.0.0'
api 'com.android.support:support-annotations:28.0.0'

api 'com.android.support:multidex:1.0.3'

api 'com.google.firebase:firebase-core:16.0.8'
api 'com.google.firebase:firebase-auth:16.2.1'
api 'com.google.firebase:firebase-firestore:18.2.0'
api 'com.google.firebase:firebase-storage:16.1.0'
api 'com.google.android.libraries.places:places:1.1.0'

setText 一直給我同樣的問題 - 我認為這一定是一個錯誤。 但是,我發現了一些提示。 在您的 onPlaceSelected 中,您可以輸入以下內容:

爪哇

EditText etPlace = (EditText) autocompleteFragment.getView().findViewById(R.id.places_autocomplete_search_input);
etPlace.setHint(place.getAddress())

科特林

val etPlace = autocompleteFragment.view?.findViewById(R.id.places_autocomplete_search_input) as EditText
etPlace.hint = place.address

這是我正在使用的代碼,它運行良好。

對 build.gradle(應用級別)進行一些更改

將此添加到 build.gradle:

android{
   ...
   ext {
        googlePlayServicesVersion = "15.0.1"
   }
}

添加這些依賴項:

dependencies {
    ...
    //Also if you're using any firebase dependencies make sure that the are up to date
    implementation 'com.google.android.gms:play-services-places:16.0.0'
    implementation 'com.google.android.libraries.places:places:1.1.0'
}
apply plugin: 'com.google.gms.google-services'

在 xml 布局中:

<fragment
                android:id="@+id/autocomplete_fragment"
                android:name="com.google.android.libraries.places.widget.AutocompleteSupportFragment"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

活動中的代碼:

private void initGooglePlacesApi() {
        // Initialize Places.
        Places.initialize(getApplicationContext(), "YOUR_API_KEY");
        // Create a new Places client instance.
        PlacesClient placesClient = Places.createClient(getApplicationContext());

        // Initialize the AutocompleteSupportFragment.
        AutocompleteSupportFragment autocompleteFragment = (AutocompleteSupportFragment)
                getSupportFragmentManager().findFragmentById(R.id.autocomplete_fragment);

        autocompleteFragment.setHint(getString(R.string.select_location_search_bar));
//        autocompleteFragment.setLocationRestriction(RectangularBounds.newInstance(
//                new LatLng(34.7006096, 19.2477876),
//                new LatLng(41.7488862, 29.7296986))); //Greece bounds
        autocompleteFragment.setCountry("gr");


        // Specify the types of place data to return.
        autocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ADDRESS, Place.Field.ADDRESS_COMPONENTS));
        autocompleteFragment.setTypeFilter(TypeFilter.ADDRESS);


        // Set up a PlaceSelectionListener to handle the response.
        autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
            @Override
            public void onPlaceSelected(Place place) {
                if(place.getAddressComponents().asList().get(0).getTypes().get(0).equalsIgnoreCase("route")){
                    binding.textViewLocation.setText(place.getAddress()); //Works well
                    location = place.getAddress();

                }else{ //If user does not choose a specific place.
                    AndroidUtils.vibratePhone(getApplication(), 200);
                    TastyToast.makeText(getApplicationContext(),
                            getString(R.string.choose_an_address), TastyToast.DEFAULT, TastyToast.CONFUSING);
                }

                Log.i(TAG, "Place: " + place.getAddressComponents().asList().get(0).getTypes().get(0) + ", " + place.getId() + ", " + place.getAddress());
            }

            @Override
            public void onError(Status status) {
                Log.i(TAG, "An error occurred: " + status);
            }
        });
    }

我找到了一個非常簡單的解決方案……只是在您在 EditText 中設置文本的那一刻延遲一點。 因此,在您的 PlaceSelectionListener 中,只需這樣做:

Handler().postDelayed({
    mAddressEditText.setText(place.getAddress());
}, 300)

PS:這是 kotlin 代碼,但它在 Java 中幾乎相似

我相信這是一個錯誤,因為讓它像這樣工作是沒有意義的。 有效的是設置其他自動完成的文本而不是它自己的文本。 這一定是個bug。

編輯:這是我更新的答案

# When you are using AutocompleteSupportFragment or AutocompleteActivity
# in Fragments, do this:
public class YourFragment extends Fragment {
/.../
@Override
public void onActivityResult (int requestCode,int resultCode,
 @Nullable Intent data){
 # AUTOCOMPLETE_REQUEST_CODE is just a unique constant, define it
 if (requestCode == AUTOCOMPLETE_REQUEST_CODE) {
   if (resultCode == AutocompleteActivity.RESULT_OK) {
    Place place = Autocomplete.getPlaceFromIntent(data);
    // when resultcode is RESULT_OK
    mAddressEditText.setText(place.getName());
    // Notice this line, update your editText up here
    }else if (resultCode == AutocompleteActivity.RESULT_ERROR) {
    Status status = Autocomplete.getStatusFromIntent(data);
    // Handle error
    } else if (resultCode == AutocompleteActivity.RESULT_CANCELED) {
    // Handle results if canceled
    }
  super.onActivityResult(requestCode, resultCode, data);
 }
}
/.../
}
# If you are extending AppCompatActivity, you might want to do this
# ONLY when you are already doing something in onActivityResult
public class YourActivity extends AppCompatActivity{
/.../
@Override
public void onActivityResult (int requestCode,int resultCode,@Nullable Intent data){
 # your logic here.
 /.../ 
  # if you are already overriding onActivityResult, 
  # do not forget to put this line
  super.onActivityResult(requestCode, resultCode, data);
 }
/.../
}

我也遇到了這個問題。 原來你不得不覆蓋這個反正實現它,無論是使用AutocompleteSupportFragmentAutocompleteActivity如果您在碎片工作。

如果你正在使用AppCompatActivity你不必實現它,但如果你已經覆蓋onActivityResult做某事,不要忘記調用基本方法super.onActivityResult

獲取 AutoCompleteFragment 的引用,然后將文本設置為自動完成片段,如

autoCompleteFragment.setText("Address")

作為參考,您可以查看文檔

https://developers.google.com/android/reference/com/google/android/gms/location/places/ui/PlaceAutocompleteFragment

我嘗試了CacheMeOutside 的解決方案,但它根本不起作用。 所以,我決定嘗試Matthias 的解決方案並且它確實有效,因為文本實際上設置然后由於某種原因立即刪除。 一個小的延遲修復它。 延遲可以小到 1 毫秒。

如果我的解決方案對您不起作用,您可以嘗試嘗試延遲。 它似乎也不會停止視圖渲染,因此您可以隨時設置。

private lateinit var autocomplete: AutocompleteSupportFragment

        override fun onPlaceSelected(place: Place) {
            Timer("SetAddress", false).schedule(1) {
                autocomplete.setText(place.address)
            }
        }

Kotlin 中的代碼片段。 如果您的代碼是 Java 語言,只需找一些工具將代碼執行延遲一段時間即可。

Matthias 的解決方案正在起作用,但它在 kotlin 中。 下面是 Java 中的相同實現

 @Override
 public void onPlaceSelected(Place place) {


                        String name =  place.getName()+", "+place.getAddress();
                      
                        new Handler().postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                autocompleteFragmentDestination.setText(name);
                            }
                        },300);

                    }

簡單的。 使用 Spannable 字符串設置顏色!

    val autocompleteFragment = childFragmentManager.findFragmentById(R.id.location_filter_autocomplete) as AutocompleteSupportFragment
    val text = SpannableString("Enter a location")
    text.setSpan(ForegroundColorSpan(Color.BLACK), 0, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
    autocompleteFragment.setHint(text)

在 onPlaceSelectedListener() 里面做同樣的事情

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM