package com.dxjia.doubantop.activitys; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.net.Uri; import android.speech.SpeechRecognizer; import android.support.design.widget.NavigationView; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.view.GravityCompat; import android.support.v4.view.ViewPager; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.CardView; import android.support.v7.widget.Toolbar; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.EditText; import android.widget.ImageView; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; import com.dxjia.doubantop.R; import com.dxjia.doubantop.adapters.SearchHistoryAdapter; import com.dxjia.doubantop.adapters.ViewPagerAdapter; import com.dxjia.doubantop.datas.SearchHistory; import com.dxjia.doubantop.datas.beans.BeansUtils; import com.dxjia.doubantop.datas.beans.MovieMajorInfos; import com.dxjia.doubantop.fragments.SearchPagerFragment; import com.dxjia.doubantop.interfaces.MovieInfoActionsListener; import com.dxjia.doubantop.interfaces.SearchStateToggleListener; import com.dxjia.doubantop.net.BaiduVoiceUtils; import java.util.ArrayList; import java.util.Date; import butterknife.ButterKnife; import butterknife.InjectView; public class MainActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener, SearchStateToggleListener, MovieInfoActionsListener { @InjectView(R.id.drawer_layout) DrawerLayout mDrawerLayout; @InjectView(R.id.toolbar) Toolbar mToolbar; @InjectView(R.id.tab_bar) TabLayout mTabLayout; @InjectView(R.id.nvView) NavigationView mNavigationView; @InjectView(R.id.view_pager) ViewPager mViewPager; private ViewPagerAdapter mViewPagerAdapter; private ActionBarDrawerToggle mDrawerToggle; private int mCurrentPagerPosition = ViewPagerAdapter.US_BOX_PAGER_POSITON; private final static String CURRENT_PAGER_POSITION_KEY = "pager_pos"; // 用来显示搜索历史 @InjectView(R.id.search_history_listview) ListView mSearchHistoryList; private SearchHistoryAdapter mSearchHistoryAdapter; /** * Search views */ // divider @InjectView(R.id.line_divider) View mHistoryListHeaderLineDivider; // search backgroud mask @InjectView(R.id.view_search_mask) RelativeLayout mSearchViewBackMaskView; // search view 主体 @InjectView(R.id.search_body) CardView mSearchView; @InjectView(R.id.image_search_back) ImageView mSearchViewHide; @InjectView(R.id.clearSearch) ImageView mCleanSearchInputText; @InjectView(R.id.search_text_input_edit) EditText mSearchInputEditText; @InjectView(R.id.do_search) ImageView mSearchBtn; private static final int VOICE_ACTIVITY_RESULT_CODE = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.inject(this); if (savedInstanceState != null) { mCurrentPagerPosition = savedInstanceState.getInt(CURRENT_PAGER_POSITION_KEY); } setupToolbar(); setupDrawerItemSelectListener(); mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); mDrawerLayout.setDrawerListener(mDrawerToggle); initSearchViews(); setupTabBar(); setupViewPager(); } private void setupToolbar() { setSupportActionBar(mToolbar); final ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); } /** * 设置toolbar上的search action响应 */ mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { int menuItem = item.getItemId(); switch (menuItem) { case R.id.action_about: startAboutActivity(); break; case R.id.action_search: toggleSearchViewsState(); adjustHeaderLineDivider(); break; default: break; } return false; } }); } private void setupTabBar() { int tabTextColor = getResources().getColor(R.color.titleTextColor); int tabSelectedTextColor = getResources().getColor(R.color.titleTextColorFocused); mTabLayout.setTabTextColors(tabTextColor, tabSelectedTextColor); } private void setupViewPager() { mViewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), this); mViewPager.setAdapter(mViewPagerAdapter); mTabLayout.setupWithViewPager(mViewPager);//this is the new nice thing ; mViewPager.addOnPageChangeListener(this); } private void setupDrawerItemSelectListener() { if(mNavigationView == null) { return; } mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(MenuItem menuItem) { drawerItemSelected(menuItem); return true; } }); } private void drawerItemSelected(MenuItem menuItem) { switch (menuItem.getItemId()) { case R.id.drawer_navigation_menu_collections: startFavoritesActivity(); break; case R.id.drawer_navigation_menu_github: startGitHubWeb(); break; } mDrawerLayout.closeDrawers(); } @Override protected void onResume() { super.onResume(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt(CURRENT_PAGER_POSITION_KEY, mCurrentPagerPosition); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); menu.removeItem(R.id.action_search); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { if (mDrawerToggle.onOptionsItemSelected(item)) { return true; } // 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(); switch (id) { case R.id.action_about: startAboutActivity(); return true; case android.R.id.home: mDrawerLayout.openDrawer(GravityCompat.START); return true; } return super.onOptionsItemSelected(item); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); mDrawerToggle.syncState(); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mDrawerToggle.syncState(); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { if(mDrawerLayout.isDrawerOpen(mNavigationView)) { mDrawerLayout.closeDrawers(); return true; } else { if (isSearchShowing()) { toggleSearchViewsState(); return true; } } } else if (event.getKeyCode() == KeyEvent.KEYCODE_MENU){ return true; } } return super.onKeyDown(keyCode, event); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { mCurrentPagerPosition = position; if (mToolbar == null) { return; } if (mSearchView.getVisibility() == View.VISIBLE && position != 2) { // hide toggleSearchViewsState(); } Menu menu = mToolbar.getMenu(); if (menu != null) { menu.clear(); } mToolbar.inflateMenu(R.menu.menu_main); if (position == ViewPagerAdapter.SEARCH_FRAGMENT_POSITON) { Fragment fragment = mViewPagerAdapter.getFragment(position); if (fragment != null && (fragment instanceof SearchPagerFragment)) { ((SearchPagerFragment)fragment).setSearchStateToggleListener(this); } } else { menu = mToolbar.getMenu(); menu.removeItem(R.id.action_search); } } @Override public void onPageScrollStateChanged(int state) { } /** * 整个container fragment其实一直包含有search view的布局, * 我们只是在不是第3个Pager的时候将他们隐藏而已 */ private void initSearchViews() { mSearchHistoryAdapter = new SearchHistoryAdapter(MainActivity.this, 0, SearchHistory.all()); mSearchHistoryList.setAdapter(mSearchHistoryAdapter); /** * 点击背景关闭search views */ mSearchViewBackMaskView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { toggleSearchViewsState(); } }); /** * 设置搜索历史点击后的动作 */ mSearchHistoryList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { SearchHistory searchHistory = mSearchHistoryAdapter.getItem(position); mSearchInputEditText.setText(searchHistory.getName()); mSearchHistoryList.setVisibility(View.GONE); // 隐藏 toggleSearchViewsState(); doSearchWork(searchHistory.getName()); } }); /** * 设置搜索编辑框文字发生变化后的历史列表显示 */ mSearchInputEditText.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 (mSearchInputEditText.getText().toString().length() == 0) { mSearchHistoryAdapter = new SearchHistoryAdapter(MainActivity.this, 0, SearchHistory.all()); updateSearchCleanOrMicState(false); } else { mSearchHistoryAdapter = new SearchHistoryAdapter(MainActivity.this, 0, SearchHistory.filterByName(mSearchInputEditText.getText().toString())); updateSearchCleanOrMicState(true); } mSearchHistoryList.setAdapter(mSearchHistoryAdapter); adjustHeaderLineDivider(); } @Override public void afterTextChanged(Editable s) { } }); /** * 设置清除编辑框文字listener * 起始默认设置为voice search功能 * 当编辑框文字有变化时更新为 clean listener */ mCleanSearchInputText.setOnClickListener(mVoiceCombinedClickListener); /** * 搜索键 */ mSearchBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mSearchInputEditText.getText().toString().trim().length() > 0) { String searchStr = mSearchInputEditText.getText().toString(); addToSearchHistory(searchStr); mSearchHistoryList.setVisibility(View.GONE); // 隐藏 toggleSearchViewsState(); doSearchWork(searchStr); } } }); /** * 关闭 search view 按钮listener */ mSearchViewHide.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { toggleSearchViewsState(); } }); /** * 设置输入法的 搜索 按钮响应 */ mSearchInputEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_SEARCH) { if (mSearchInputEditText.getText().toString().trim().length() > 0) { String searchStr = mSearchInputEditText.getText().toString(); addToSearchHistory(searchStr); mSearchHistoryList.setVisibility(View.GONE); // 隐藏 toggleSearchViewsState(); doSearchWork(searchStr); } return true; } return false; } }); } private View.OnClickListener mCleanInputClickListener = new View.OnClickListener() { @Override public void onClick(View v) { if (mSearchInputEditText.getText().toString().length() != 0) { mSearchInputEditText.setText(""); mSearchHistoryList.setVisibility(View.VISIBLE); ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); adjustHeaderLineDivider(); } } }; /** * 更新search控件上右侧的 x 按钮或者 语音识别按钮 * 它俩做在同一个imagebtn上,就是根据edit框里有没有文字来动态更新 * @param showCleanBtn false for show mic image, true for show X image */ private void updateSearchCleanOrMicState(boolean showCleanBtn) { if (showCleanBtn) { mCleanSearchInputText.setImageResource(R.mipmap.ic_close); mCleanSearchInputText.setOnClickListener(mCleanInputClickListener); } else { mCleanSearchInputText.setImageResource(R.mipmap.ic_keyboard_voice); mCleanSearchInputText.setOnClickListener(mVoiceCombinedClickListener); } } private void adjustHeaderLineDivider() { if (mSearchHistoryAdapter.getCount() == 0) { mHistoryListHeaderLineDivider.setVisibility(View.GONE); } else { mHistoryListHeaderLineDivider.setVisibility(View.VISIBLE); } } /** * 弹出语音识别控件 */ private View.OnClickListener mVoiceCombinedClickListener = new View.OnClickListener() { @Override public void onClick(View v) { // 先隐藏掉输入法 ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)). hideSoftInputFromWindow(mSearchViewBackMaskView.getWindowToken(), 0); // 关闭掉搜索历史列表 mSearchHistoryList.setVisibility(View.GONE); BaiduVoiceUtils.startVoiceRecognizer(MainActivity.this, VOICE_ACTIVITY_RESULT_CODE); } }; @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); mSearchHistoryList.setVisibility(View.VISIBLE); if (requestCode == VOICE_ACTIVITY_RESULT_CODE && resultCode == Activity.RESULT_OK) { Bundle results = data.getExtras(); if (results == null) { return; } ArrayList<String> nbest = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); if (nbest == null || nbest.size() == 0) { return; } // now we just get the first result String result = nbest.get(0); mSearchInputEditText.setText(result); mSearchInputEditText.setSelection(result.length()); } } /** * 将 搜索文字 加入到搜索历史数据库 */ private void addToSearchHistory(String key) { SearchHistory recentLog = new SearchHistory(); recentLog.setName(key); recentLog.setDate(new Date()); recentLog.save(); mSearchHistoryAdapter.add(recentLog); mSearchHistoryAdapter.notifyDataSetChanged(); } /** * 变换 search views的显示与隐藏 */ public void toggleSearchViewsState() { InputMethodManager inputMethodManager = ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)); final Animation fade_in = AnimationUtils.loadAnimation(getApplicationContext(), android.R.anim.fade_in); final Animation fade_out = AnimationUtils.loadAnimation(getApplicationContext(), android.R.anim.fade_out); if (mSearchView.getVisibility() == View.VISIBLE) { // 隐藏 inputMethodManager.hideSoftInputFromWindow(mSearchViewBackMaskView.getWindowToken(), 0); mSearchViewBackMaskView.startAnimation(fade_out); fade_out.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { mSearchViewBackMaskView.setVisibility(View.GONE); } @Override public void onAnimationRepeat(Animation animation) { } }); mSearchView.setVisibility(View.GONE); mSearchInputEditText.setText(""); mSearchInputEditText.clearFocus(); mSearchView.setEnabled(false); } else { // 显示 mSearchViewBackMaskView.setVisibility(View.VISIBLE); mSearchViewBackMaskView.startAnimation(fade_in); mSearchView.setVisibility(View.VISIBLE); mSearchView.setEnabled(true); mSearchHistoryList.setVisibility(View.VISIBLE); mSearchInputEditText.requestFocus(); inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); } } /** * 异步获取搜索结果 * @param key 搜索关键字 */ private void doSearchWork(String key) { if (TextUtils.isEmpty(key) || mViewPagerAdapter == null) { return; } Fragment fragment = mViewPagerAdapter.getFragment(ViewPagerAdapter.SEARCH_FRAGMENT_POSITON); if (fragment instanceof SearchPagerFragment) { ((SearchPagerFragment)fragment).startSearch(key); } } private void startAboutActivity() { Intent intent = new Intent(MainActivity.this, AboutActivity.class); startActivity(intent); } private void startFavoritesActivity() { Intent intent = new Intent(MainActivity.this, FavoritesActivity.class); startActivity(intent); } private void startGitHubWeb() { Uri uri = Uri.parse("https://github.com/dxjia/DoubanTop"); Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent); } private boolean isSearchShowing() { return (mSearchView != null) && (mSearchView.getVisibility() == View.VISIBLE); } @Override public void toggleSearchState() { toggleSearchViewsState(); } @Override public void showDetails(MovieMajorInfos movieInfos) { Intent intent = new Intent(MainActivity.this, DetailActivity.class); intent.putExtra(BeansUtils.MOVIE_MAJOR_INFOS_KEY, movieInfos); startActivity(intent); } }