package tv.acfun.a63;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBar.OnNavigationListener;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBarDrawerToggle;
import android.text.Editable;
import android.text.Html;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.android.volley.Cache;
import com.android.volley.Cache.Entry;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.ImageLoader;
import com.astuetz.PagerSlidingTabStrip;
import com.handmark.pulltorefresh.library.ILoadingLayout;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshBase.OnLastItemVisibleListener;
import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
import com.umeng.analytics.MobclickAgent;
import com.umeng.fb.FeedbackAgent;
import com.umeng.fb.model.Conversation;
import com.umeng.fb.model.Conversation.SyncListener;
import com.umeng.fb.model.DevReply;
import com.umeng.fb.model.Reply;
import com.umeng.update.UmengUpdateAgent;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import tv.acfun.a63.api.ArticleApi;
import tv.acfun.a63.api.Constants;
import tv.acfun.a63.api.entity.Content;
import tv.acfun.a63.api.entity.Contents;
import tv.acfun.a63.api.entity.User;
import tv.acfun.a63.db.DB;
import tv.acfun.a63.service.KeepOnlineService;
import tv.acfun.a63.service.PushService;
import tv.acfun.a63.util.ActionBarUtil;
import tv.acfun.a63.util.DensityUtil;
import tv.acfun.a63.util.FastJsonRequest;
import tv.acfun.a63.util.TextViewUtils;
import tv.acfun.a63.util.Theme;
public class MainActivity extends ActionBarActivity implements
OnItemClickListener, OnNavigationListener, OnClickListener {
private static final String KEY_CURRENT_ITEM = "current_item";
private static final String TAG = "MainActivity";
private static String[] mPlanetTitles;
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
private CharSequence mTitle;
private String[] mTitles;
private ActionBar mBar;
private View mDrawer;
private View mAvatarFrame;
private int mCurrentNavPosition;
private static RequestQueue mQueue;
private ImageView avatar;
private TextView nameText;
private TextView signatureText;
private User mUser;
private Fragment mContentFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
ActionBarUtil.compatibleDeviceWithSB(this);
Theme.onActivityCreate(this, savedInstanceState);
super.onCreate(savedInstanceState);
mUser = AcApp.getUser();
initUmeng();
setContentView(R.layout.activity_main);
ActionBarUtil.forceShowActionBarOverflowMenu(this);
mBar = getSupportActionBar();
ActionBarUtil.setXiaomiFilterDisplayOptions(getSupportActionBar(), true);
mTitle = getTitle();
mPlanetTitles = getResources().getStringArray(R.array.planets);
initDrawerLayout(savedInstanceState);
mQueue = AcApp.getGloableQueue();
if(mUser != null){
PushService.start(this);
KeepOnlineService.requestOnline(this, 0);
}
if (!PreferenceManager.getDefaultSharedPreferences(this).contains("last_public_alert_show"))
showLastPublicReleaseAlert();
}
private void showLastPublicReleaseAlert() {
new AlertDialog.Builder(this)
.setTitle("请知悉")
.setMessage("由于ACFUN·北京的\"举报\"及\"侵权\"的\"控告\"," +
"您所使用的应用将是最后一个\"公开发行版\"。\n" +
"\n另外,本应用从诞生起就是开源项目,作者依然还会更新Github上的代码。直到这个应用无人问津为止。\n" +
"(具体请看\"关于\")\n"+
"此致。")
.setPositiveButton("知道了",null)
.show();
PreferenceManager.getDefaultSharedPreferences(this)
.edit()
.putInt("last_public_alert_show", 1)
.apply();
}
private void initUmeng() {
MobclickAgent.setDebugMode(BuildConfig.DEBUG);
MobclickAgent.setCatchUncaughtExceptions(true);
MobclickAgent.openActivityDurationTrack(false);
Runnable action = new Runnable(){
public void run() {
UmengUpdateAgent.update(MainActivity.this);
ArticleApi.updateConfig(getApplicationContext());
SyncListener listener = new Conversation.SyncListener() {
@Override
public void onSendUserReply(List<Reply> replyList) {
}
@Override
public void onReceiveDevReply(List<DevReply> replyList) {
if(replyList == null || replyList.isEmpty()){
return;
}
Intent intent = new Intent(MainActivity.this, ConversationActivity.class);
String text = replyList.get(0).getContent();
AcApp.showNotification(intent, R.id.comments_content, text, R.drawable.notify_chat, getString(R.string.new_replay));
}
};
new FeedbackAgent(MainActivity.this).getDefaultConversation().sync(listener);
}
};
View decorView = getWindow().peekDecorView();
if(decorView == null)
action.run();
else
decorView.postDelayed(action, 2000);
}
private void initDrawerLayout(Bundle savedInstanceState) {
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawer = findViewById(R.id.left_drawer);
mAvatarFrame = findViewById(R.id.avatar_frame);
mAvatarFrame.setOnClickListener(this);
avatar = (ImageView) mAvatarFrame.findViewById(R.id.avatar);
nameText = (TextView) mAvatarFrame.findViewById(R.id.user_name);
signatureText = (TextView) mAvatarFrame.findViewById(R.id.signature);
setUserInfo();
mDrawerList = (ListView) findViewById(R.id.list);
mDrawerList.setFooterDividersEnabled(false);
// set a custom shadow that overlays the main content when the drawer
// opens
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
GravityCompat.START);
mDrawerLayout.setScrimColor(Color.argb(100, 0, 0, 0));
int[] iconIds = { R.drawable.ic_home,
R.drawable.ic_hot, R.drawable.ic_heart, R.drawable.ic_at, R.drawable.ic_action_search};
// set up the drawer's list view with items and click listener
View drawerFooter = getLayoutInflater().inflate(R.layout.drawer_footer_item, mDrawerList,false);
CheckBox check = (CheckBox) drawerFooter.findViewById(R.id.checkbox);
check.setChecked(Theme.isNightMode());
check.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
AcApp.putBoolean("is_night_mode", isChecked);
if(Build.VERSION.SDK_INT >= 11)
recreate();
else{
finish();
startActivity(getIntent());
}
}
});
mDrawerList.addFooterView(drawerFooter,null,false);
mDrawerList.setAdapter(new NavigationAdapter(mPlanetTitles, iconIds));
mDrawerList.setOnItemClickListener(this);
mDrawerToggle = new ActionBarDrawerToggle(this,
mDrawerLayout,
R.string.app_name_open,
R.string.app_name
) {
public void onDrawerClosed(View view) {
if (mCurrentNavPosition == 0) {
mBar.setDisplayShowTitleEnabled(false);
mBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
} else
mBar.setTitle(mTitle);
supportInvalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
if (mCurrentNavPosition == 0) {
mBar.setDisplayShowTitleEnabled(true);
mBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
}
mBar.setTitle(R.string.app_name_open);
supportInvalidateOptionsMenu();
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
mTitles = getResources().getStringArray(R.array.titles);
mFragments = new ArrayList<>(mTitles.length);
int position = 0;
if (savedInstanceState != null){
position = savedInstanceState.getInt(KEY_CURRENT_ITEM, 0);
}
if(position == 0)
setActionbarNavigation();
selectItem(position);
if (AcApp.getConfig().getBoolean("is_first_open", true)) {
mDrawerLayout.openDrawer(mDrawer);
AcApp.putBoolean("is_first_open", false);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(KEY_CURRENT_ITEM, mCurrentNavPosition);
}
private void setUserInfo() {
if(mUser != null){
AcApp.getGloableLoader().get(mUser.avatar, ImageLoader.getImageListener(avatar, R.drawable.account_avatar, R.drawable.account_avatar));
nameText.setText(mUser.name);
if(!TextUtils.isEmpty(mUser.signature)){
LayoutParams params = (LayoutParams) nameText.getLayoutParams();
params.addRule(RelativeLayout.CENTER_VERTICAL,0);
params.topMargin = DensityUtil.dip2px(getApplicationContext(), 8);
nameText.setLayoutParams(params);
signatureText.setText(mUser.signature);
signatureText.setVisibility(View.VISIBLE);
}
if(mUser.isExpired()){
new AlertDialog.Builder(this)
.setTitle(R.string.account_expired)
.setMessage(R.string.msg_account_expired)
.setPositiveButton(R.string.logout, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
AcApp.logout();
invalidateAvatarFrame();
}
}).show();
}
}
}
/**
* @see <a href="http://www.yrom.net/blog/2013/03/10/fragment-switch-not-restart/" >fragment switch</a>
* @param from
* @param to
*/
private void switchContent(Fragment from, Fragment to) {
if(to == null)
throw new IllegalStateException("content fragment还没有初始化!");
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction().setCustomAnimations(
android.R.anim.fade_in, R.anim.slide_out);
if(from == null){
mContentFragment = to;
transaction.replace(R.id.content_frame, to);
} else if (mContentFragment != to) {
mContentFragment = to;
transaction.hide(from);
if (!to.isAdded()) {
transaction.add(R.id.content_frame, to);
} else {
transaction.show(to);
}
}
transaction.commit();
}
private List<Fragment> mFragments;
private ArrayAdapter<String> mNavAdapter;
/**
* @see <a href="http://www.yrom.net/blog/2013/07/17/viewpager-cant-change-tag-of-fragment/">can't change tag of fragment</a>
* @param position
* @return
*/
private Fragment getFragment(int position){
Fragment f = null;
if(position <mFragments.size()){
f = mFragments.get(position);
if(f != null)
return f;
}
while(position>=mFragments.size()){
mFragments.add(null);
}
Bundle args = new Bundle();
switch (position) {
case 1:
MobclickAgent.onEvent(this, "rank");
f = new RankListFragment();
args.putInt(RankListFragment.ARG_LIST_MODE, 3);
args.putInt(RankListFragment.ARG_SECTION_NUMBER, 4);
f.setHasOptionsMenu(false);
break;
case 2:
MobclickAgent.onEvent(this, "fav");
f = new FavListFragment();
break;
case 4:
MobclickAgent.onEvent(this, "search");
f = new SearchFragment();
break;
case 0:
default:
MobclickAgent.onEvent(this, "main");
f = new HomeFragment();
args.putInt(HomeFragment.ARG_PLANET_NUMBER, position);
args.putStringArray(HomeFragment.ARG_TITLES, mTitles);
break;
}
f.setArguments(args);
mFragments.set(position,f);
return f;
}
private void selectItem(int position) {
Fragment f = getFragment(position);
switchContent(mContentFragment, f);
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
setTitle(mPlanetTitles[position]);
mDrawerLayout.closeDrawer(mDrawer);
mCurrentNavPosition = position;
}
private void setActionbarNavigation() {
mBar.setDisplayShowTitleEnabled(false);
mBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
if(mNavAdapter == null){
mNavAdapter = new ArrayAdapter<String>(
mBar.getThemedContext(), R.layout.list_item_2,
android.R.id.text2, getResources().getStringArray(
R.array.modes)) {
@Override
public View getView(int position, View convertView,
ViewGroup parent) {
View view = super.getView(position, convertView, parent);
TextView text = (TextView) view
.findViewById(android.R.id.text1);
text.setText(mPlanetTitles[0]);
return view;
}
};
mNavAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
}
mBar.setListNavigationCallbacks(mNavAdapter, this);
mBar.setSelectedNavigationItem(AcApp.getConfig().getInt("nav_item", 0));
}
/* Called whenever we call invalidateOptionsMenu() */
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If the nav drawer is open, hide action items related to the content
// view
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawer);
MenuItem findItem = menu.findItem(R.id.action_view_mode);
if (findItem != null)
findItem.setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
@Override
public void setTitle(CharSequence title) {
mTitle = title;
mBar.setTitle(mTitle);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggls
mDrawerToggle.onConfigurationChanged(newConfig);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
if (mDrawerLayout.isDrawerOpen(mDrawer)) {
mDrawerLayout.closeDrawer(mDrawer);
} else {
mDrawerLayout.openDrawer(mDrawer);
}
return true;
case R.id.action_settings:
SettingsActivity.start(this);
return true;
case R.id.action_feedback:
startActivity(new Intent(getApplicationContext(), ConversationActivity.class));
return true;
case R.id.action_donate:
DonateActivity.start(this);
return true;
case R.id.action_about:
ArticleActivity.start(this, getString(R.string.about_url));
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
/**
* 四个频道列表
*
*/
public static class SectionsPagerAdapter extends FragmentPagerAdapter {
String[] titles;
int contentListMode;
public SectionsPagerAdapter(FragmentManager fragmentManager,
String[] titles) {
super(fragmentManager);
this.titles = titles;
}
@Override
public Fragment getItem(int position) {
Fragment fragment = new ArticleListFragment();
Bundle args = new Bundle();
args.putInt(ArticleListFragment.ARG_SECTION_NUMBER, position);
contentListMode = AcApp.getConfig().getInt("nav_item", 0);
args.putInt(ArticleListFragment.ARG_LIST_MODE, contentListMode);
fragment.setArguments(args);
return fragment;
}
@Override
public int getCount() {
return titles.length;
}
@Override
public CharSequence getPageTitle(int position) {
if (position < titles.length)
return titles[position];
return null;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ArticleListFragment fragment = (ArticleListFragment) super.instantiateItem(container, position);
fragment.setContentListMode(contentListMode);
return fragment;
}
@Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
public void changeContentListMode(int itemPosition) {
if(contentListMode != itemPosition){
contentListMode = itemPosition;
AcApp.putInt("nav_item",itemPosition);
notifyDataSetChanged();
}
}
}
/**
* 主页,四个频道列表,三种阅读模式
*/
public static class HomeFragment extends BaseFragment {
public static final String ARG_TITLES = "titles";
public static final String ARG_PLANET_NUMBER = "planet_number";
private static int VIEW_MODE_CODE;
private MenuItem mModeMenu;
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
public HomeFragment() {
VIEW_MODE_CODE = AcApp.getViewMode();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.mode_mix:
VIEW_MODE_CODE = Constants.MODE_MIX;
break;
case R.id.mode_no_image:
VIEW_MODE_CODE = Constants.MODE_NO_PIC;
break;
case R.id.mode_comic:
VIEW_MODE_CODE = Constants.MODE_COMMIC;
break;
}
AcApp.putInt("view_mode", VIEW_MODE_CODE);
setMenuIcon();
return super.onOptionsItemSelected(item);
}
private void setMenuIcon() {
switch (VIEW_MODE_CODE) {
case Constants.MODE_NO_PIC:
mModeMenu.setIcon(R.drawable.mode_no_pic);
mModeMenu.setTitle(R.string.view_mode_no_image);
break;
case Constants.MODE_COMMIC:
mModeMenu.setTitle(R.string.view_mode_comic);
mModeMenu.setIcon(R.drawable.mode_comic);
break;
case Constants.MODE_MIX:
default:
mModeMenu.setTitle(R.string.view_mode_mix);
mModeMenu.setIcon(R.drawable.mode_mix);
break;
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.view_mode, menu);
mModeMenu = menu.findItem(R.id.action_view_mode);
setMenuIcon();
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
int i = getArguments().getInt(ARG_PLANET_NUMBER);
View rootView = null;
if (i == 0) {
setHasOptionsMenu(true);
rootView = createHomeView(inflater, container);
} else {
setHasOptionsMenu(false);
rootView = inflater.inflate(R.layout.fragment_planet,
container, false);
((TextView) rootView).setText(mPlanetTitles[i]);
}
return rootView;
}
private View createHomeView(LayoutInflater inflater, ViewGroup container) {
View rootView = inflater.inflate(R.layout.fragment_home, container,
false);
if(mSectionsPagerAdapter == null)
mSectionsPagerAdapter = new SectionsPagerAdapter(
getChildFragmentManager(), getArguments().getStringArray(ARG_TITLES));
PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) rootView.findViewById(R.id.tabs);
mViewPager = (ViewPager) rootView.findViewById(R.id.pager);
mViewPager.setOffscreenPageLimit(2);
mViewPager.setAdapter(mSectionsPagerAdapter);
tabs.setViewPager(mViewPager);
return rootView;
}
public void changeContentListMode(int itemPosition) {
if(BuildConfig.DEBUG)
Log.d(TAG, "on adapter change Content ListMode = " +itemPosition );
mSectionsPagerAdapter.changeContentListMode(itemPosition);
}
@Override
protected String getPageTitle() {
return "Home";
}
}
public static class FavListFragment extends BaseFragment{
@Override
public void onResume() {
super.onResume();
mEmptyView.setVisibility(View.GONE);
loadData();
}
@Override
protected String getPageTitle() {
return "FavList";
}
LayoutInflater inflater;
private ListView mList;
private View mProgress;
private View mEmptyView;
private OnItemClickListener mOnItemclick = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Content c = (Content) parent.getItemAtPosition(position);
ArticleActivity.start(getActivity(), c.aid, c.title);
}
};
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
this.inflater = inflater;
View root = inflater.inflate(R.layout.fragment_list,container,false);
mList = (ListView) root.findViewById(R.id.list);
mList.setOnItemClickListener(mOnItemclick);
mProgress = root.findViewById(R.id.loading);
mEmptyView = root.findViewById(R.id.time_out_text);
return root;
}
private void loadData() {
new Thread(){
public void run() {
final List<Content> favList = new DB(getActivity()).getFavList();
mList.post(new Runnable() {
@Override
public void run() {
mProgress.setVisibility(View.GONE);
setListAdapter(favList);
}
});
}
}.start();
}
private void setListAdapter(final List<Content> favList) {
if(favList == null || favList.isEmpty()){
mEmptyView.setVisibility(View.VISIBLE);
}else
setListAdapter(new ArticleListAdapter(inflater, favList, 0){
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ListViewHolder holder;
if(convertView == null){
convertView = inflater.inflate(R.layout.fav_list_item,parent,false);
holder = new ListViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.article_item_title);
holder.postTime = (TextView) convertView.findViewById(R.id.article_item_post_time);
holder.comments = (TextView) convertView.findViewById(R.id.article_desc);
holder.channel = (TextView) convertView.findViewById(R.id.item_tag_channel);
convertView.setTag(holder);
}else{
holder = (ListViewHolder) convertView.getTag();
}
Content content = getItem(position);
holder.title.setText(TextViewUtils.getSource(content.title));
if(!TextUtils.isEmpty(content.description))
holder.comments.setText(Html.fromHtml(TextViewUtils.getSource(content.description)));
else{
holder.comments.setText(R.string.no_desc);
}
String tip = String.format(Locale.CHINA, "于%s收藏,有%d人同好", AcApp.getPubDate(content.releaseDate),content.stows);
holder.postTime.setText(tip);
holder.channel.setText(ArticleApi.getChannelName(content.channelId));
return convertView;
}
});
}
private void setListAdapter(ListAdapter adapter) {
if(adapter == null) return;
mList.setVisibility(View.VISIBLE);
mList.setAdapter(adapter);
}
}
/**
* 搜索
*/
public static class SearchFragment extends BaseFragment implements OnClickListener, OnEditorActionListener,
OnScrollListener,OnItemClickListener {
private View mBtnClear;
private EditText mSearchText;
private View mProgress;
private ListView mResultList;
private LayoutInflater mInflater;
private ArticleListAdapter mAdapter;
private TextWatcher watcher = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void afterTextChanged(Editable s) {
if (s.length() > 0) {
mBtnClear.setVisibility(View.VISIBLE);
} else {
mBtnClear.setVisibility(View.GONE);
mProgress.setVisibility(View.GONE);
}
mResultList.setVisibility(View.GONE);
if(mAdapter != null && mAdapter.contents != null)
mAdapter.contents.clear();
}
};
protected int mPage;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
this.mInflater = inflater;
return inflater.inflate(R.layout.fragment_search, container,false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
mBtnClear = view.findViewById(R.id.btn_search_clear);
mBtnClear.setOnClickListener(this);
mSearchText = (EditText) view.findViewById(R.id.search_text);
mSearchText.addTextChangedListener(watcher);
mSearchText.setOnEditorActionListener(this);
mProgress = view.findViewById(R.id.search_plate_progress);
mResultList = (ListView) view.findViewById(android.R.id.list);
mResultList.setOnScrollListener(this);
mResultList.setOnItemClickListener(this);
}
@Override
public void onClick(View v) {
if(v == mBtnClear){
mSearchText.setText("");
}
}
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if(actionId == EditorInfo.IME_ACTION_SEARCH
|| (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) {
startSearch(v.getText().toString(),1);
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null && imm.isActive(mSearchText)) {
imm.hideSoftInputFromWindow(mSearchText.getWindowToken(), 0);
}
return true;
}
return false;
}
private int mTotalCount;
Listener<Contents> listener = new Listener<Contents>() {
@Override
public void onResponse(Contents response) {
mResultList.setVisibility(View.VISIBLE);
if(mAdapter == null){
mAdapter = new ArticleListAdapter(mInflater,response.getContents(),0);
}
if(mPage <= 1){
mAdapter.contents = response.getContents();
mResultList.setAdapter(mAdapter);
}else{
mAdapter.addData(response.getContents());
}
mProgress.setVisibility(View.GONE);
mAdapter.notifyDataSetChanged();
mTotalCount = response.totalcount;
}};
ErrorListener errorListner = new ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.w(TAG, "search failed!", error.getCause());
mProgress.setVisibility(View.GONE);
AcApp.showToast("搜索失败!");
}};
private boolean mLastItemVisible;
private void startSearch(String query, int page) {
mProgress.setVisibility(View.VISIBLE);
mPage = page;
String url = ArticleApi.getSearchUrl(getActivity(), query, mPage, 20);
if (BuildConfig.DEBUG) Log.d(TAG, "query url=" + url);
Request<?> request = new ContentListRequest(url, listener, errorListner);
AcApp.addRequest(request);
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE && mLastItemVisible) {
startSearch(mSearchText.getText().toString(),mPage+1);
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
mLastItemVisible = (totalItemCount > 0)
&& (firstVisibleItem + visibleItemCount >= totalItemCount - 1)
&& totalItemCount < mTotalCount;
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
startViewArticle(parent, position);
}
@Override
protected String getPageTitle() {
return "Search";
}
}
/**
* 排行榜
*
*/
public static class RankListFragment extends ArticleListFragment{
@Override
protected String getPageTitle() {
return "RankList";
}
}
static Contents parseJson(String rankJson){
JSONObject rankList = JSON.parseObject(rankJson);
if(rankList.getIntValue("status") != 200){
return null;
}
JSONObject page = rankList.getJSONObject("data").getJSONObject("page");
JSONArray jsonArr = page.getJSONArray("list");
List<Content> contents = new ArrayList<>();
for(int i=0;i<jsonArr.size();i++){
JSONObject carr = jsonArr.getJSONObject(i);
Content c = new Content();
String contentId = carr.getString("contentId");
if(TextUtils.isDigitsOnly(contentId))
c.aid = Integer.parseInt(contentId);
else if(contentId.startsWith("ac"))
c.aid = Integer.parseInt(contentId.substring(2));
c.title =carr.getString("title");
c.description = carr.getString("description");
c.releaseDate = carr.getLongValue("releaseDate");
c.views = carr.getIntValue("views");
c.comments = carr.getIntValue("comments");
c.stows = carr.getIntValue("stows");
c.channelId = carr.getIntValue("channelId");
c.isRecommend = carr.getBooleanValue("isRecommend");
contents.add(c);
}
Contents cs = new Contents();
cs.setContents(contents);
cs.totalpage = 1;
cs.totalcount = page.getIntValue("totalCount");
return cs;
}
static class ContentListRequest extends FastJsonRequest<Contents>{
public ContentListRequest(String url, Listener<Contents> listener,
ErrorListener errorListner) {
super(url, Contents.class, listener, errorListner);
}
@Override
protected Response<Contents> parseNetworkResponse(NetworkResponse response) {
try {
String json = new String(
response.data, HttpHeaderParser.parseCharset(response.headers));
Contents contents = parseJson(json);
if(contents == null)
throw new NullPointerException();
return Response.success(contents,HttpHeaderParser.parseCacheHeaders(response));
}catch (UnsupportedEncodingException e) {
String json = new String(response.data);
Contents contents = parseJson(json);
if(contents == null)
throw new NullPointerException();
return Response.success(contents,HttpHeaderParser.parseCacheHeaders(response));
} catch(Exception e){
return Response.error(new ParseError(e));
}
}
}
/**
* 文章列表
*
*/
public static class ArticleListFragment extends BaseFragment implements OnItemClickListener {
public static final String ARG_LIST_MODE = "list_mode";
public static final String ARG_SECTION_NUMBER = "section_number";
int DEFAULT_COUT = 20;
int page;
PullToRefreshListView list;
LayoutInflater inflater;
boolean isLoading;
View footView;
int listMode;
private Request<?> request;
private ILoadingLayout loadingLayout;
private View loadding;
public ArticleListFragment() {
}
@Override
protected String getPageTitle() {
return "Home.ArticleList["+section+"]";
}
public void setContentListMode(int contentListMode) {
if(listMode != contentListMode){
listMode = contentListMode;
if(BuildConfig.DEBUG) Log.d(TAG, String.format("[%d] framgent change Content ListMode =%d",section,listMode));
if(list != null) // ensure list
list.setRefreshing();
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
listMode = getArguments().getInt(ARG_LIST_MODE);
section = getArguments().getInt(ARG_SECTION_NUMBER);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
this.inflater = inflater;
View rootView = inflater.inflate(R.layout.fragment_main_dummy, container, false);
list = (PullToRefreshListView) rootView.findViewById(R.id.list);
timeOut = rootView.findViewById(R.id.time_out_text);
loadding = rootView.findViewById(R.id.loading);
footView = inflater.inflate(R.layout.list_footerview, list.getRefreshableView(),false);
list.getRefreshableView().addFooterView(footView, null, false);
loadingLayout = list.getLoadingLayoutProxy(true, false);
list.setOnRefreshListener(new OnRefreshListener<ListView>() {
@Override
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
// Do work to refresh the list here.
if(BuildConfig.DEBUG)
Log.d(TAG, String.format("[%d] on refresh ",section));
isLoading = true;
String label = DateUtils.formatDateTime(getActivity() != null ? getActivity() : AcApp.context(),
System.currentTimeMillis(),
DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL);
loadingLayout.setLastUpdatedLabel(label);
loadData(true,false);
}
});
list.setOnLastItemVisibleListener(new OnLastItemVisibleListener() {
@Override
public void onLastItemVisible() {
if(!isLoading){
if(hasNextPage()){
if(BuildConfig.DEBUG)
Log.d(TAG, String.format("[%d] 加载下一页, mode=%d",section,listMode));
loadData(false,false);
}else{
timeOut.setVisibility(View.GONE);
TextView text = (TextView) footView.findViewById(R.id.list_footview_text);
text.setText(R.string.no_more);
footView.findViewById(R.id.list_footview_progress).setVisibility(View.GONE);
footView.setOnClickListener(null);
}
}
}
});
list.setOnItemClickListener(this);
return rootView;
}
protected boolean hasNextPage() {
// 排行版只加载一页
return listMode != 3;
}
boolean isShowing;
@Override
public void onResume() {
super.onResume();
if(BuildConfig.DEBUG)
Log.d(TAG, String.format("[%d] on fragment resume, showing = %b",section,isShowing));
if(!isShowing){
loadding.setVisibility(View.VISIBLE);
loadData(true, true);
isShowing = true;
}
}
private ArticleListAdapter adapter;
Response.Listener<Contents> listener = new Response.Listener<Contents>() {
@Override
public void onResponse(Contents response) {
if(adapter == null){
adapter = new ArticleListAdapter(inflater,response.getContents(),listMode);
}
if(page <= 1){
adapter.contents = response.getContents();
list.setAdapter(adapter);
}else{
adapter.addData(response.getContents());
}
loadding.setVisibility(View.GONE);
adapter.notifyDataSetChanged();
list.onRefreshComplete();
needReload = false;
isLoading = false;
}
};
OnClickListener onReload = new OnClickListener() {
@Override
public void onClick(View v) {
if(needReload){
if(page >1) {
page -= 1;
loadData(false, false);
}else{
loadData(true, false);
}
}
}
};
boolean needReload;
Response.ErrorListener errorListner = new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, String.format("[%d] load list error",section), error);
TextView text = (TextView) footView.findViewById(R.id.list_footview_text);
text.setText(R.string.reloading);
footView.findViewById(R.id.list_footview_progress).setVisibility(View.GONE);
footView.setOnClickListener(onReload);
needReload = true;
if(list.getRefreshableView().getAdapter()==null)
timeOut.setVisibility(View.VISIBLE);
list.onRefreshComplete();
isLoading = false;
}
};
protected int section;
protected View timeOut;
final void loadData(boolean newData, boolean loadCache) {
initPage(newData);
String url = getContentListUrl();
// 缓存数据
final Cache.Entry entry = mQueue.getCache().get(url);
if (entry != null && entry.data != null && entry.data.length > 0) {
if (newData && !entry.isExpired()) {
// entry.ttl = entry.softTtl = System.currentTimeMillis() - 1000;
mQueue.getCache().invalidate(url, true);
if(BuildConfig.DEBUG) Log.d(TAG, String.format("[%d] 刷新数据",section));
}
if (loadCache) {
new Thread() {
@Override
public void run() {
Contents contens = loadDataFromCache(entry);
if (contens != null && contens.getContents() != null) {
adapter = new ArticleListAdapter(inflater, contens.getContents(),listMode);
list.post(new Runnable() {
@Override
public void run() {
list.setAdapter(adapter);
isLoading = false;
list.setRefreshing();
loadding.setVisibility(View.GONE);
}
});
}
}
}.start();
return;
}
}
request = getRequest(url);
request.setShouldCache(true);
if(BuildConfig.DEBUG)
Log.d(TAG, String.format("[%d] new request: %s",section,request.getUrl()));
mQueue.add(request);
}
protected Request<?> getRequest(String url) {
return new ContentListRequest(url, listener, errorListner);
}
protected Contents loadDataFromCache(Entry entry) {
return parseJson(new String(entry.data));
}
protected void initPage(boolean newData) {
timeOut.setVisibility(View.GONE);
TextView text = (TextView) footView.findViewById(R.id.list_footview_text);
text.setText(R.string.loading);
footView.findViewById(R.id.list_footview_progress).setVisibility(View.VISIBLE);
footView.setOnClickListener(null);
page = newData ? 1 : page + 1;
}
//将默认列表调整为热门
private String getContentListUrl() {
switch (listMode) {
case 1:
return ArticleApi.getLatestRepliedUrl(getActivity(),Constants.CAT_IDS[section],page);
case 2:
return ArticleApi.getDefaultUrl(getActivity(),Constants.CAT_IDS[section], DEFAULT_COUT, page);
case 3:
return ArticleApi.getRankListUrl(getActivity());
case 0:
default:
return ArticleApi.getHotListUrl(getActivity(),Constants.CAT_IDS[section],page);
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
isShowing = false;
if(request != null && !request.hasHadResponseDelivered() && !request.isCanceled()){
request.cancel();
Log.w(TAG, String.format("[%d]request canceled : %s",section,request.getUrl()));
request = null;
}
}
@Override
public void onDestroy() {
super.onDestroy();
if(adapter != null && adapter.contents != null){
if(BuildConfig.DEBUG)
Log.d(TAG, String.format("[%d] destory adapter,size=%d", section,adapter.getCount()));
adapter.contents.clear();
adapter = null;
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
startViewArticle(parent, position);
}
}
private static void startViewArticle(AdapterView<?> list, int position) {
Object obj = list.getItemAtPosition(position);
if(obj != null && obj instanceof Content){
Content c = (Content)obj;
ArticleActivity.start(list.getContext(), c.aid,c.title);
}
}
static class ArticleListAdapter extends BaseAdapter {
List<Content> contents;
LayoutInflater inflater;
int mode;
public ArticleListAdapter(LayoutInflater inflater, List<Content> contents, int listMode) {
this.contents = contents == null ? new ArrayList<Content>() : contents;
this.inflater = inflater;
this.mode = listMode;
}
@Override
public int getCount() {
return contents.size();
}
public void addData(List<Content> contents){
this.contents.addAll(contents);
}
@Override
public Content getItem(int position) {
return contents.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ListViewHolder holder;
if(convertView == null){
if(mode <3){
convertView = inflater.inflate(R.layout.article_list_item, parent,false);
}else{
convertView = inflater.inflate(R.layout.rank_list_item, parent,false);
}
holder = new ListViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.article_item_title);
holder.postTime = (TextView) convertView.findViewById(R.id.article_item_post_time);
holder.comments = (TextView) convertView.findViewById(R.id.article_desc);
convertView.setTag(holder);
}
holder = (ListViewHolder) convertView.getTag();
Content art = getItem(position);
holder.title.setText(TextViewUtils.getSource(art.getTitle()));
if(!TextUtils.isEmpty(art.description)){
CharSequence text = null;
try{
text = Html.fromHtml(TextViewUtils.getSource(art.description));
// catch java.io.IOException: Pushback buffer full
// at android.text.HtmlToSpannedConverter.convert(Html.java:438)
// at android.text.Html.fromHtml(Html.java:138)
// at android.text.Html.fromHtml(Html.java:101)
}catch(Exception e){
text = TextViewUtils.getSource(art.description);
}
holder.comments.setText(text);
}
else{
holder.comments.setText(R.string.no_desc);
}
if (mode < 3) {
View tagHot = convertView.findViewById(R.id.item_tag);
if (ArticleApi.isRecommendedArticle(art)) {
tagHot.setVisibility(View.VISIBLE);
((ImageView) tagHot).setImageResource(Theme.isNightMode() ? R.drawable.ic_recommended_dark : R.drawable.ic_recommended);
} else if (ArticleApi.isHotArticle(art)) {
tagHot.setVisibility(View.VISIBLE);
((ImageView) tagHot).setImageResource(Theme.isNightMode() ? R.drawable.ic_whats_hot_dark : R.drawable.ic_whats_hot);
} else
tagHot.setVisibility(View.GONE);
} else {
TextView rank = (TextView) convertView.findViewById(R.id.rank);
if (position < 10) {
rank.setVisibility(View.VISIBLE);
rank.setText(String.valueOf(position + 1));
int rankColorIndex = position > 3? 3:position;
rank.setBackgroundColor(rankColors[rankColorIndex]);
} else
rank.setVisibility(View.GONE);
}
String tip = String.format(Locale.CHINA, " %s / %d条评论,%d人围观", AcApp.getPubDate(art.releaseDate),art.comments,art.views);
// holder.postTime.setText(AcApp.getPubDate(art.releaseDate));
holder.postTime.setText(tip);
return convertView;
}
int rankColors[] = {0xffcc0000,0xffff4444,0xffff8800,0xffffbb33};
}
static class ListViewHolder{
TextView comments,
postTime,
channel,
views,
title;
ImageView titleImage;
}
static class NavigationItem {
String title;
Drawable icon;
}
public class NavigationAdapter extends BaseAdapter {
NavigationItem[] navs;
public NavigationAdapter(String[] titles, int[] iconIds) {
navs = new NavigationItem[titles.length];
for (int i = 0; i < titles.length && i < iconIds.length; i++) {
navs[i] = new NavigationItem();
navs[i].title = titles[i];
navs[i].icon = getResources().getDrawable(iconIds[i]);
}
}
@Override
public int getCount() {
return navs.length;
}
@Override
public NavigationItem getItem(int position) {
return navs[position];
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
NavigationItem item = getItem(position);
if (convertView == null) {
convertView = getLayoutInflater().inflate(
R.layout.navigation_list_item, parent, false);
}
ImageView iconView = (ImageView) convertView
.findViewById(R.id.icon);
TextView titleView = (TextView) convertView.findViewById(R.id.text);
iconView.setImageDrawable(item.icon);
titleView.setText(item.title);
return convertView;
}
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long arg3) {
if(position == arg0.getCount() -2 - ((ListView)arg0).getFooterViewsCount()){
MentionActivity.start(this);
mDrawerList.setItemChecked(mCurrentNavPosition, true);
return;
}else if(position == arg0.getCount() - ((ListView)arg0).getFooterViewsCount()){
Log.i(TAG, "footer clicked");
return;
}
if (mCurrentNavPosition != position)
selectItem(position);
}
@Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
if(mContentFragment == null){
mContentFragment = getSupportFragmentManager().findFragmentById(R.id.content_frame);
}
if(mContentFragment!= null && mContentFragment instanceof HomeFragment)
((HomeFragment)mContentFragment).changeContentListMode(itemPosition);
else
MobclickAgent.reportError(this.getApplicationContext(),
String.format("onNavigationItemSelected: %d, but mContentFragment isn't HomeFragment: %s",
itemPosition, String.valueOf(mContentFragment)));
return true;
}
@Override
public void onClick(View v) {
if (v == mAvatarFrame) {
if(mUser != null)
startActivityForResult(new Intent(this,ProfileActivity.class),2);
else
startActivityForResult(
SigninActivity.createIntent(getApplicationContext()),
SigninActivity.REQUEST_SIGN_IN);
}
}
/**
* Remove current avatar frame..
*/
private void invalidateAvatarFrame() {
mUser = null;
((LinearLayout)mDrawer).removeViewAt(0);
mAvatarFrame = getLayoutInflater().inflate(R.layout.avatar_frame, (LinearLayout)mDrawer,false);
mAvatarFrame.setOnClickListener(this);
((LinearLayout)mDrawer).addView(mAvatarFrame, 0);
avatar = (ImageView) mAvatarFrame.findViewById(R.id.avatar);
nameText = (TextView) mAvatarFrame.findViewById(R.id.user_name);
signatureText = (TextView) mAvatarFrame.findViewById(R.id.signature);
}
@Override
protected void onActivityResult(int request, int result, Intent data) {
if(result == RESULT_OK ){
if(request == SigninActivity.REQUEST_SIGN_IN){
mUser = data.getExtras().getParcelable("user");
setUserInfo();
startActivity(new Intent(this,ProfileActivity.class));
}else{
invalidateAvatarFrame();
}
}
}
@Override
public void onBackPressed() {
if(mDrawerLayout.isDrawerOpen(mDrawer)){
mDrawerLayout.closeDrawer(mDrawer);
}else if(mCurrentNavPosition != 0 ){
selectItem(0);
mDrawerToggle.onDrawerClosed(mDrawer);
}else
super.onBackPressed();
}
@Override
protected void onDestroy() {
super.onDestroy();
KeepOnlineService.requestOffline(this);
}
@Override
protected void onResume() {
super.onResume();
MobclickAgent.onResume(this);
}
@Override
protected void onPause() {
super.onPause();
MobclickAgent.onPause(this);
}
}