所以我正在尝试在我的应用中实现搜索功能。我已将SearchView添加到应用程序栏并配置我的清单以将意图指向正确的活动。但我有一个特殊的情况:我想在SearchView生成的意图中添加额外的信息以传递给我的SearchableActivity(在我的例子中是SearchEventsActivity类)。为此,我想让我的MainActivity类可以搜索,它用onNewIntent()来捕获意图,将额外的信息放在一个新的intent中并使用它来启动我的实际搜索活动。但出于某种原因,虽然我很确定我的清单是正确的,但是在MainActivity中永远不会调用onNewIntent()
的AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.joshuaindustries.FindFun">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.app.default_searchable"
android:value=".MainActivity"
android:resource="@xml/searchable" />
</activity>
<activity
android:name=".DetailsActivity"
android:label="@string/title_activity_details"
android:theme="@style/AppTheme.NoActionBar" ></activity>
<activity
android:name=".LoginActivity"
android:label="LoginActivity"
android:theme="@style/AppTheme.NoActionBar" ></activity>
<activity
android:name=".SearchEventsActivity" >
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
MainActivity.class
package com.joshuaindustries.FindFun;
import com.joshuaindustries.CustomFragments.ManageListFragment;
import com.joshuaindustries.CustomFragments.OverviewListFragment;
import com.joshuaindustries.netwerk.ManageEventsFetcher;
import com.joshuaindustries.netwerk.OverviewEventsFetcher;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.design.widget.TabLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.content.SharedPreferencesCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private final static String TAG = "MainActivity";
private OverviewEventsFetcher overviewEventsFetcher;
private ManageEventsFetcher manageEventsFetcher;
private String userEmailAddress;
private String userPassword;
private OverviewListFragment overviewTabFragment;
private ManageListFragment manageTabFragment;
/**
* The {@link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {@link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {@link android.support.v4.app.FragmentStatePagerAdapter}.
*/
private SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {@link ViewPager} that will host the section contents.
*/
private ViewPager mViewPager;
@Override
protected void onCreate ( Bundle savedInstanceState ) {
super.onCreate ( savedInstanceState );
setContentView ( R.layout.activity_main );
Intent activityIntent = getIntent ( );
Bundle passedData = getIntent ( ).getExtras ( );
/* Make sure we are ( still ) logged in
*/
SharedPreferences loginData = getSharedPreferences ( "com.joshuaindustries.FindFun.loginData", Context.MODE_PRIVATE );
userEmailAddress = loginData.getString ( "userEmailAddress", null );
userPassword = loginData.getString ( "userPassword", null );
if ( ( userEmailAddress == null ) || ( userPassword == null ) ) {
Bundle passedLoginData = passedData;
if ( passedLoginData == null) {
Intent loginIntent = new Intent ( this, LoginActivity.class );
startActivity ( loginIntent );
} else {
userEmailAddress = passedLoginData.getString ( "userEmailAddress" );
userPassword = passedLoginData.getString ( "userPassword" );
if ( ( userEmailAddress == null ) || (userPassword == null ) ) {
Intent loginIntent = new Intent ( this, LoginActivity.class );
startActivity ( loginIntent );
}
}
}
/* Create our custom list fragment
*/
overviewTabFragment = new OverviewListFragment( );
manageTabFragment = new ManageListFragment ( );
Toolbar toolbar = ( Toolbar ) findViewById ( R.id.toolbar );
setSupportActionBar ( toolbar );
getSupportActionBar ( ).setTitle ( "FindFun" );
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter ( getSupportFragmentManager ( ) );
// Set up the ViewPager with the sections adapter.
mViewPager = ( ViewPager ) findViewById ( R.id.container );
mViewPager.setAdapter ( mSectionsPagerAdapter );
TabLayout tabLayout = ( TabLayout ) findViewById ( R.id.tabs );
tabLayout.setupWithViewPager ( mViewPager );
FloatingActionButton fab = ( FloatingActionButton ) findViewById ( R.id.fab );
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
} );
}
@Override
public void onStart ( ) {
super.onStart ( );
/* Get events data from server
*/
overviewEventsFetcher = new OverviewEventsFetcher ( this, userEmailAddress, userPassword );
overviewEventsFetcher.fetch ( );
overviewTabFragment.setUserCredentials ( userEmailAddress, userPassword );
overviewTabFragment.setEventsFetcher ( overviewEventsFetcher );
manageEventsFetcher = new ManageEventsFetcher ( this, userEmailAddress, userPassword );
manageEventsFetcher.fetch ( );
manageTabFragment.setUserCredentials ( userEmailAddress, userPassword );
manageTabFragment.setEventsFetcher ( manageEventsFetcher );
}
@Override
public boolean onCreateOptionsMenu ( Menu menu ) {
super.onCreateOptionsMenu ( menu );
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater ( ).inflate ( R.menu.menu_main, menu );
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected ( item );
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed ( ) {
return;
}
@Override
public void onNewIntent ( Intent newIntent ) {
Log.d ( TAG, "onNewIntent started" );
if ( Intent.ACTION_SEARCH.equals ( newIntent.getAction ( ) ) ) {
//Intent searchIntent = new Intent ( Intent.ACTION_SEARCH, null, getApplicationContext ( ), SearchEventsActivity.class );
Intent searchIntent = new Intent ( this, SearchEventsActivity.class );
searchIntent.putExtra ( "userEmailAddress", userEmailAddress );
searchIntent.putExtra ( "userPassword", userPassword );
searchIntent.putExtra ( SearchManager.QUERY, newIntent.getStringExtra ( SearchManager.QUERY ) );
startActivity ( searchIntent );
}
}
@Override
public void onStop ( ) {
super.onStop ( );
overviewEventsFetcher.onActivityStop ( );
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
public PlaceholderFragment() {
}
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle ( );
args.putInt ( ARG_SECTION_NUMBER, sectionNumber );
fragment.setArguments ( args );
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate ( R.layout.fragment_overview, container, false );
TextView textView = ( TextView ) rootView.findViewById ( R.id.section_label );
textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
}
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter ( FragmentManager fragmentManager ) {
super ( fragmentManager );
}
@Override
public Fragment getItem ( int position ) {
if ( position == 0 ) {
return ( overviewTabFragment );
} else if ( position == 2 ) {
return ( manageTabFragment );
} else {
return PlaceholderFragment.newInstance(position + 1);
}
}
@Override
public int getCount ( ) {
/* We will have three tabs
*/
return ( 3 );
}
@Override
public CharSequence getPageTitle ( int position ) {
/* We will have three tabs
- Overview: showing an overview of events the user can participate in
- Participations: allowing the user to manage his or her participations
- Manage: allowing the user to manage the events he / she creates himself
*/
switch ( position ) {
case ( 0 ):
return ( "Overview" );
case ( 1 ):
return ( "Participations" );
case ( 2 ):
return ( "Manage" );
default:
return ( null );
}
}
}
}
SearchEventsActivity.java
package com.joshuaindustries.FindFun;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.RelativeLayout;
import com.joshuaindustries.netwerk.OverviewEventsFetcher;
import com.joshuaindustries.netwerk.SearchResultsEventsFetcher;
/**
* Created by Joshua on 7/01/2017.
*/
public class SearchEventsActivity extends AppCompatActivity implements ListView.OnItemClickListener {
private static final String TAG = "SearchEventsActivityt";
private static int nextSearchQueryID = 0;
private String userEmailAddress;
private String userPassword;
private String searchQuery;
private int searchQueryID;
private View viewRoot;
private ListView searchResultsList;
SearchResultsEventsFetcher eventsFetcher;
@Override
protected void onCreate ( Bundle savedInstanceState ) {
super.onCreate ( savedInstanceState );
Log.d ( TAG, "search activity started" );
setContentView ( R.layout.activity_search_events );
Intent searchIntent = getIntent ( );
Bundle passedData = searchIntent.getExtras ( );
userEmailAddress = passedData.getString ( "userEmailAddress" );
userPassword = passedData.getString ( "userPassword" );
searchQuery = passedData.getString ( SearchManager.QUERY );
searchQueryID = SearchEventsActivity.nextSearchQueryID;
++SearchEventsActivity.nextSearchQueryID;
eventsFetcher = new SearchResultsEventsFetcher ( this, userEmailAddress, userPassword, searchQuery, searchQueryID );
}
@Override
public View onCreateView ( String name, Context context, AttributeSet attributeSet ) {
viewRoot = super.onCreateView ( name, context, attributeSet );
searchResultsList = ( ListView ) viewRoot.findViewById ( R.id.list_search_results );
searchResultsList.setOnItemClickListener ( this );
searchResultsList.setAdapter ( this.eventsFetcher.getEventListAdapter ( ) );
Button loadMoreResultsButton = new Button ( this );
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams ( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT );
layoutParams.addRule ( RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE );
loadMoreResultsButton.setLayoutParams ( new AbsListView.LayoutParams ( layoutParams ) );
loadMoreResultsButton.setText ( "Load more results ..." );
loadMoreResultsButton.setOnClickListener (
new View.OnClickListener ( ) {
SearchResultsEventsFetcher eventsFetcher;
public View.OnClickListener passEventsFetcher ( SearchResultsEventsFetcher eventsFetcher ) {
this.eventsFetcher = eventsFetcher;
return ( this );
}
@Override
public void onClick ( View view ) {
eventsFetcher.fetch( );
}
}.passEventsFetcher ( eventsFetcher )
);
searchResultsList.addFooterView ( loadMoreResultsButton );
return ( viewRoot );
}
@Override
public void onItemClick ( AdapterView listView, View view, int viewPosition, long rowID ) {
Intent detailsIntent = new Intent ( this, DetailsActivity.class );
detailsIntent.putExtra ( "userEmailAddress", userEmailAddress );
detailsIntent.putExtra ( "userPassword", userPassword );
eventsFetcher.putEventInIntent ( detailsIntent, rowID );
startActivity ( detailsIntent );
}
}
Searchable.xml
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_name"
android:hint="@string/search_hint" >
</searchable>
我尝试过提出的解决方案here和here无济于事......
非常感谢任何帮助和/或建议!
谢谢, 约书亚
答案 0 :(得分:1)
我认为我的问题是SDK没有将我的可搜索配置链接到我的活动中实例化的SearchView。我不知道为什么会这样,但我有一个解决方法,即在MainActivity.java的onCreateOptionsMenu(菜单菜单)方法中以编程方式进行此耦合,如下所示:
SearchView searchView = ( SearchView ) menu.findItem ( R.id.action_search ).item.getActionView ( );
SearchManager searchManager = ( SearchManager ) getSystemService ( Context.SEARCH_SERVICE );
searchView.setSearchableInfo ( searchManager.getSearchableInfo ( getComponentName ( ) ) );
我希望将来可以帮助某人:)