简体   繁体   中英

Android - SearchView not working in single fragment activity

Good morning everybody, I'm trying to implement search features in a single activity with search features by implementing SearchView . From UI-side, everything is working. But unlike almost of example I found, SearchView does not start another activity but is supposed so send request to the single running activity named HomeActivity .

Following some documentation I found on Android developers website and other sources, I try to do like below. Normally, I would supposed to handle search request in the event " onNewIntent " but it's never called. Click on the button after entering text has no effect (it just closes the keyboard).

I'm beginner in Android development and probably missed something simple. Can you please help me ?

HomeActivity

public class HomeActivity extends AppCompatActivity implements SearchView.OnQueryTextListener {

    private FrameLayout myFrameLayout;
    private Fragment fragmentContracts, fragmentHardware, fragmentMaps, fragmentUsers;

    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
        = new BottomNavigationView.OnNavigationItemSelectedListener() {

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        Fragment fragment = null;

        switch (item.getItemId()) {
            // Switch to fragment ...
        }
        return loadFragment(fragment);
    }
};

private void handleIntent(Intent intent) {

    Log.i("LOG_myapp", "Called new intent !!!");
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        String query = intent.getStringExtra(SearchManager.QUERY);
        //use the query to search your data somehow
        String msg = MessageFormat.format("Search query = {0}", query);
        Log.i("LOG_myapp", msg);
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(query)
                .setTitle("Search request");
        AlertDialog dialog = builder.create();
        dialog.show();
    }
}

@Override
protected void onNewIntent(Intent intent){
    // *** NEVER CALLED :( ***
    Log.i("LOG_myapp", "Event onNewIntent raised");
    handleIntent(intent);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);

    myFrameLayout = (FrameLayout)findViewById(R.id.MyFrameLayout);
    BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
    navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);

    Fragment defaultFragment = new places();
    defaultFragment.setRetainInstance(true);
    loadFragment(defaultFragment);

    Toolbar toolbar = (Toolbar)findViewById(R.id.activity_main_toolbar);
    setSupportActionBar(toolbar);

    handleIntent(getIntent());
}

@Override
public boolean onCreateOptionsMenu(Menu menu){
    getMenuInflater().inflate(R.menu.application, menu);

    // Associate searchable configuration with the SearchView
    SearchManager searchManager =
            (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    SearchView searchView =
            (SearchView) menu.findItem(R.id.MenuItemSearch).getActionView();
    searchView.setSubmitButtonEnabled(true);
    ComponentName componentName = new ComponentName(this, HomeActivity.class);
    searchView.setSearchableInfo(searchManager.getSearchableInfo(componentName));

    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item){
    switch (item.getItemId()) {
        case R.id.MenuItemSettings:
            Intent intent = new Intent(this, preferences.class);
            startActivity(intent);
            break;
    }
    return true;
}

@Override
public boolean onQueryTextChange(String s){
    Log.i("LOG_myapp","Search query: " + s);
    return true;
}

@Override
public boolean onQueryTextSubmit(String s){
    Log.i("LOG_myapp","Submitted search query: " + s);
    return true;
}

private boolean loadFragment(Fragment fragment) {
    //switching fragment
    if (fragment != null) {
        try {
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.MyFrameLayout, fragment);
            transaction.addToBackStack(null);
            transaction.commit();
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }
    return false;
}

}

Menus.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/MenuItemSearch"
        android:title="Search"
        android:icon="@drawable/baseline_search_white_18dp"
        app:showAsAction="collapseActionView|ifRoom"
        app:actionViewClass="android.support.v7.widget.SearchView"/>
    <item android:id="@+id/MenuItemSettings"
        android:icon="@drawable/baseline_settings_white_18dp"
        app:showAsAction="always"
        android:title="Settings"/>
</menu>  

AndroidManifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.vermilionenergy.myapp">

    <!--
         The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
         Google Maps Android API v2, but you must specify either coarse or fine
         location permissions for the 'MyLocation' functionality. 
    -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".HomeActivity"
            android:label="@string/app_name"
            android:launchMode="singleTop">
            <intent-filter>
                <!--action android:name="android.intent.action.MAIN" /-->
                <action android:name="android.intent.action.SEARCH"/>
                <category android:name="android.intent.category.DEFAULT" />
                <!-- category android:name="android.intent.category.LAUNCHER" / -->
            </intent-filter>
            <meta-data android:name="android.app.searchable" android:resource="@xml/searchable"/>
            <meta-data android:name="android.app.default_searchable" android:value=".HomeActivity" />
        </activity>
        <meta-data android:name="android.app.default_searchable" android:value=".HomeActivity" />
        <!--
             The API key for Google Maps-based APIs is defined as a string resource.
             (See the file "res/values/google_maps_api.xml").
             Note that the API key is linked to the encryption key used to sign the APK.
             You need a different API key for each encryption key, including the release key that is used to
             sign the APK for publishing.
             You can define the keys for the debug and release targets in src/debug/ and src/release/. 
        -->

        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key" />


        <activity
            android:name=".maps"
            android:label="@string/title_activity_maps" />
        <activity
            android:name=".preferences"
            android:label="Preferences" />
        <!-- activity android:name=".users" / -->

        <activity android:name=".SplashScreenActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".TextActivity"></activity>
    </application>

</manifest>

searchable.xml

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="myapp"
    android:hint="Search items"
    >
</searchable>

I finally found the solution myself. It looks like the direct strings in searchable.xml don't work. I replaced them by variable as below and it worked :)

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_title"
    android:hint="@string/search_hint"
    >
</searchable>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM