根据活动片段更改 activity 中的搜索功能
Changing search function in activity depending on active fragment
我有一个 activity
和一个 TabLayout
连接到 FragmentPagerAdapter
。每当用户更改选项卡时,都会加载另一个片段,但 Activity
保持不变。
activity
还包含搜索功能,即从网络服务器获取自动完成建议。我想执行不同的搜索操作 - 基本上,查询另一个 URL - 取决于当前在 FragmentPager
/TabLayout
中加载的片段。
到目前为止,我还没有找到任何方法来做到这一点。这是我尝试过的:
- 目前,搜索功能已连接到内容提供商(通过清单和 searchable.xml)。但是,我还没有找到将数据传递给此 ContentProvider 以让它知道选择了哪个选项卡的方法
- 使用多个内容提供者似乎是不可能的,因为任何给定的 Activity 只能有一个内容提供者,并且 Activity 在选择另一个选项卡时不应该改变
- 操纵 Activity 的 onQueryText* 方法不可行,因为我不想阻止 UI 线程获取数据
这里是情况的简要概述:Sketch
相关代码片段如下:
MainActivity.class
public class MainActivity extends AppCompatActivity {
private ViewPager mViewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager = (ViewPager) findViewById(R.id.viewpager);
mViewPager.setAdapter(new MainFragmentPagerAdapter(getSupportFragmentManager(),
MainActivity.this));
TabLayout tabs = (TabLayout) findViewById(R.id.sliding_tabs);
tabs.setupWithViewPager(mViewPager);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.action_search, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setOnQueryTextListener(this);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
searchView.setSearchableInfo(searchManager.getSearchableInfo(new ComponentName(this, MainActivity.class)));
searchView.setIconifiedByDefault(false);
return true;
}
/* ... */
}
menu/action_search.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/action_search"
android:title="Search"
android:icon="@android:drawable/ic_menu_search"
app:showAsAction="always"
app:actionViewClass="android.support.v7.widget.SearchView" />
</menu>
xml/searchable.xml
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:hint="hint"
android:label="@string/app_name"
android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"
android:searchSuggestAuthority="xyz.demo.search.datasuggestion"
android:searchSuggestIntentAction="android.intent.action.VIEW"
android:searchSuggestIntentData="content://xyz.demo.search.data"/>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xyz.demo.app">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<meta-data
android:name="android.app.default_searchable"
android:value=".MainActivity" />
<activity android:name=".MainActivity" android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.SEARCH" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
<provider
android:name=".SuggestionProvider"
android:authorities="xyz.demo.search.datasuggestion"
android:enabled="true"
android:exported="true"/>
</application>
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
SuggestionProvider.java
public class SuggestionProvider extends ContentProvider {
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(".../suggestions")
.build();
try {
Response response = client.newCall(request).execute();
String jsonString = response.body().string();
JSONArray jsonArray = new JSONArray(jsonString);
/* ... */
} catch (Exception e) {
e.printStackTrace();
}
/* ... eventually returns a MatrixCursor */
}
/* ... */
}
啊,好吧,我看到这是 Android 调用您的提供商的事情之一,您无法控制它的调用方式。
我也没有找到干净利落的方法。可搜索链接到 activity。您要么将屏幕基于 activity 而不是片段(更改设计),要么做一些糟糕的事情,例如在片段恢复时设置首选项,以便内容提供者知道哪个片段是 "active".
我有一个 activity
和一个 TabLayout
连接到 FragmentPagerAdapter
。每当用户更改选项卡时,都会加载另一个片段,但 Activity
保持不变。
activity
还包含搜索功能,即从网络服务器获取自动完成建议。我想执行不同的搜索操作 - 基本上,查询另一个 URL - 取决于当前在 FragmentPager
/TabLayout
中加载的片段。
到目前为止,我还没有找到任何方法来做到这一点。这是我尝试过的:
- 目前,搜索功能已连接到内容提供商(通过清单和 searchable.xml)。但是,我还没有找到将数据传递给此 ContentProvider 以让它知道选择了哪个选项卡的方法
- 使用多个内容提供者似乎是不可能的,因为任何给定的 Activity 只能有一个内容提供者,并且 Activity 在选择另一个选项卡时不应该改变
- 操纵 Activity 的 onQueryText* 方法不可行,因为我不想阻止 UI 线程获取数据
这里是情况的简要概述:Sketch
相关代码片段如下:
MainActivity.class
public class MainActivity extends AppCompatActivity {
private ViewPager mViewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager = (ViewPager) findViewById(R.id.viewpager);
mViewPager.setAdapter(new MainFragmentPagerAdapter(getSupportFragmentManager(),
MainActivity.this));
TabLayout tabs = (TabLayout) findViewById(R.id.sliding_tabs);
tabs.setupWithViewPager(mViewPager);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.action_search, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setOnQueryTextListener(this);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
searchView.setSearchableInfo(searchManager.getSearchableInfo(new ComponentName(this, MainActivity.class)));
searchView.setIconifiedByDefault(false);
return true;
}
/* ... */
}
menu/action_search.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/action_search"
android:title="Search"
android:icon="@android:drawable/ic_menu_search"
app:showAsAction="always"
app:actionViewClass="android.support.v7.widget.SearchView" />
</menu>
xml/searchable.xml
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:hint="hint"
android:label="@string/app_name"
android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"
android:searchSuggestAuthority="xyz.demo.search.datasuggestion"
android:searchSuggestIntentAction="android.intent.action.VIEW"
android:searchSuggestIntentData="content://xyz.demo.search.data"/>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xyz.demo.app">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<meta-data
android:name="android.app.default_searchable"
android:value=".MainActivity" />
<activity android:name=".MainActivity" android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.SEARCH" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
<provider
android:name=".SuggestionProvider"
android:authorities="xyz.demo.search.datasuggestion"
android:enabled="true"
android:exported="true"/>
</application>
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
SuggestionProvider.java
public class SuggestionProvider extends ContentProvider {
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(".../suggestions")
.build();
try {
Response response = client.newCall(request).execute();
String jsonString = response.body().string();
JSONArray jsonArray = new JSONArray(jsonString);
/* ... */
} catch (Exception e) {
e.printStackTrace();
}
/* ... eventually returns a MatrixCursor */
}
/* ... */
}
啊,好吧,我看到这是 Android 调用您的提供商的事情之一,您无法控制它的调用方式。
我也没有找到干净利落的方法。可搜索链接到 activity。您要么将屏幕基于 activity 而不是片段(更改设计),要么做一些糟糕的事情,例如在片段恢复时设置首选项,以便内容提供者知道哪个片段是 "active".