();
83 | if (HttpUtils.isNetworkConnected(mActivity)) {
84 | HttpUtils.get(Constant.THEMES, new JsonHttpResponseHandler() {
85 | @Override
86 | public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
87 | super.onSuccess(statusCode, headers, response);
88 | String json = response.toString();
89 | PreUtils.putStringToDefault(mActivity, Constant.THEMES, json);
90 | parseJson(response);
91 | }
92 | });
93 | } else {
94 | String json = PreUtils.getStringFromDefault(mActivity, Constant.THEMES, "");
95 | try {
96 | JSONObject jsonObject = new JSONObject(json);
97 | parseJson(jsonObject);
98 | } catch (JSONException e) {
99 | e.printStackTrace();
100 | }
101 | }
102 |
103 | }
104 |
105 | private void parseJson(JSONObject response) {
106 | try {
107 | JSONArray itemsArray = response.getJSONArray("others");
108 | for (int i = 0; i < itemsArray.length(); i++) {
109 | NewsListItem newsListItem = new NewsListItem();
110 | JSONObject itemObject = itemsArray.getJSONObject(i);
111 | newsListItem.setTitle(itemObject.getString("name"));
112 | newsListItem.setId(itemObject.getString("id"));
113 | items.add(newsListItem);
114 | }
115 | mAdapter = new NewsTypeAdapter();
116 | lv_item.setAdapter(mAdapter);
117 | updateTheme();
118 | } catch (JSONException e) {
119 | e.printStackTrace();
120 | }
121 | }
122 |
123 | public class NewsTypeAdapter extends BaseAdapter {
124 |
125 | @Override
126 | public int getCount() {
127 | return items.size();
128 | }
129 |
130 | @Override
131 | public Object getItem(int position) {
132 | return items.get(position);
133 | }
134 |
135 | @Override
136 | public long getItemId(int position) {
137 | return position;
138 | }
139 |
140 | @Override
141 | public View getView(int position, View convertView, ViewGroup parent) {
142 | if (convertView == null) {
143 | convertView = LayoutInflater.from(getActivity()).inflate(
144 | R.layout.menu_item, parent, false);
145 | }
146 | TextView tv_item = (TextView) convertView
147 | .findViewById(R.id.tv_item);
148 | tv_item.setTextColor(getResources().getColor(isLight ? R.color.light_menu_listview_textcolor : R.color.dark_menu_listview_textcolor));
149 | tv_item.setText(items.get(position).getTitle());
150 | return convertView;
151 | }
152 | }
153 |
154 | @Override
155 | public void onClick(View v) {
156 | switch (v.getId()) {
157 | case R.id.tv_main:
158 | ((MainActivity) mActivity).loadLatest();
159 | ((MainActivity) mActivity).closeMenu();
160 | break;
161 | }
162 | }
163 |
164 | public void updateTheme() {
165 | isLight = ((MainActivity) mActivity).isLight();
166 | ll_menu.setBackgroundColor(getResources().getColor(isLight ? R.color.light_menu_header : R.color.dark_menu_header));
167 | tv_login.setTextColor(getResources().getColor(isLight ? R.color.light_menu_header_tv : R.color.dark_menu_header_tv));
168 | tv_backup.setTextColor(getResources().getColor(isLight ? R.color.light_menu_header_tv : R.color.dark_menu_header_tv));
169 | tv_download.setTextColor(getResources().getColor(isLight ? R.color.light_menu_header_tv : R.color.dark_menu_header_tv));
170 | tv_main.setBackgroundColor(getResources().getColor(isLight ? R.color.light_menu_index_background : R.color.dark_menu_index_background));
171 | lv_item.setBackgroundColor(getResources().getColor(isLight ? R.color.light_menu_listview_background : R.color.dark_menu_listview_background));
172 | mAdapter.notifyDataSetChanged();
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/app/src/main/java/krelve/app/kuaihu/activity/LatestContentActivity.java:
--------------------------------------------------------------------------------
1 | package krelve.app.kuaihu.activity;
2 |
3 | import android.annotation.TargetApi;
4 | import android.database.Cursor;
5 | import android.database.sqlite.SQLiteDatabase;
6 | import android.graphics.Color;
7 | import android.os.Build;
8 | import android.os.Bundle;
9 | import android.support.design.widget.AppBarLayout;
10 | import android.support.design.widget.CollapsingToolbarLayout;
11 | import android.support.v7.app.AppCompatActivity;
12 | import android.support.v7.widget.Toolbar;
13 | import android.view.View;
14 | import android.view.ViewTreeObserver;
15 | import android.view.Window;
16 | import android.view.WindowManager;
17 | import android.webkit.WebSettings;
18 | import android.webkit.WebView;
19 | import android.widget.ImageView;
20 |
21 | import com.google.gson.Gson;
22 | import com.loopj.android.http.TextHttpResponseHandler;
23 | import com.nostra13.universalimageloader.core.DisplayImageOptions;
24 | import com.nostra13.universalimageloader.core.ImageLoader;
25 |
26 | import org.apache.http.Header;
27 |
28 | import krelve.app.kuaihu.R;
29 | import krelve.app.kuaihu.db.WebCacheDbHelper;
30 | import krelve.app.kuaihu.model.Content;
31 | import krelve.app.kuaihu.model.StoriesEntity;
32 | import krelve.app.kuaihu.util.Constant;
33 | import krelve.app.kuaihu.util.HttpUtils;
34 | import krelve.app.kuaihu.view.RevealBackgroundView;
35 |
36 | /**
37 | * Created by wwjun.wang on 2015/8/17.
38 | */
39 | public class LatestContentActivity extends AppCompatActivity implements RevealBackgroundView.OnStateChangeListener {
40 | private WebView mWebView;
41 | private StoriesEntity entity;
42 | private Content content;
43 | private ImageView iv;
44 | private RevealBackgroundView vRevealBackground;
45 | private AppBarLayout mAppBarLayout;
46 | private WebCacheDbHelper dbHelper;
47 | private boolean isLight;
48 |
49 | @Override
50 | protected void onCreate(Bundle savedInstanceState) {
51 | super.onCreate(savedInstanceState);
52 | setContentView(R.layout.latest_content_layout);
53 | dbHelper = new WebCacheDbHelper(this, 1);
54 | isLight = getIntent().getBooleanExtra("isLight", true);
55 | mAppBarLayout = (AppBarLayout) findViewById(R.id.app_bar_layout);
56 | mAppBarLayout.setVisibility(View.INVISIBLE);
57 | vRevealBackground = (RevealBackgroundView) findViewById(R.id.revealBackgroundView);
58 | entity = (StoriesEntity) getIntent().getSerializableExtra("entity");
59 | iv = (ImageView) findViewById(R.id.iv);
60 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
61 | setSupportActionBar(toolbar);
62 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
63 | toolbar.setNavigationOnClickListener(new View.OnClickListener() {
64 | @Override
65 | public void onClick(View v) {
66 | onBackPressed();
67 |
68 | }
69 | });
70 | CollapsingToolbarLayout mCollapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar_layout);
71 | mCollapsingToolbarLayout.setTitle(entity.getTitle());
72 | mCollapsingToolbarLayout.setContentScrimColor(getResources().getColor(isLight ? R.color.light_toolbar : R.color.dark_toolbar));
73 | mCollapsingToolbarLayout.setStatusBarScrimColor(getResources().getColor(isLight ? R.color.light_toolbar : R.color.dark_toolbar));
74 | mWebView = (WebView) findViewById(R.id.webview);
75 | mWebView.getSettings().setJavaScriptEnabled(true);
76 | mWebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
77 | // 开启DOM storage API 功能
78 | mWebView.getSettings().setDomStorageEnabled(true);
79 | // 开启database storage API功能
80 | mWebView.getSettings().setDatabaseEnabled(true);
81 | // 开启Application Cache功能
82 | mWebView.getSettings().setAppCacheEnabled(true);
83 | if (HttpUtils.isNetworkConnected(this)) {
84 | HttpUtils.get(Constant.CONTENT + entity.getId(), new TextHttpResponseHandler() {
85 | @Override
86 | public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
87 |
88 | }
89 |
90 | @Override
91 | public void onSuccess(int statusCode, Header[] headers, String responseString) {
92 | SQLiteDatabase db = dbHelper.getWritableDatabase();
93 | responseString = responseString.replaceAll("'", "''");
94 | db.execSQL("replace into Cache(newsId,json) values(" + entity.getId() + ",'" + responseString + "')");
95 | db.close();
96 | parseJson(responseString);
97 | }
98 | });
99 | } else {
100 | SQLiteDatabase db = dbHelper.getReadableDatabase();
101 | Cursor cursor = db.rawQuery("select * from Cache where newsId = " + entity.getId(), null);
102 | if (cursor.moveToFirst()) {
103 | String json = cursor.getString(cursor.getColumnIndex("json"));
104 | parseJson(json);
105 | }
106 | cursor.close();
107 | db.close();
108 | }
109 | setupRevealBackground(savedInstanceState);
110 | setStatusBarColor(getResources().getColor(isLight ? R.color.light_toolbar : R.color.dark_toolbar));
111 | }
112 |
113 | private void parseJson(String responseString) {
114 | Gson gson = new Gson();
115 | content = gson.fromJson(responseString, Content.class);
116 | final ImageLoader imageloader = ImageLoader.getInstance();
117 | DisplayImageOptions options = new DisplayImageOptions.Builder()
118 | .cacheInMemory(true)
119 | .cacheOnDisk(true)
120 | .build();
121 | imageloader.displayImage(content.getImage(), iv, options);
122 | String css = " ";
123 | String html = "" + css + "" + content.getBody() + "";
124 | html = html.replace("", "");
125 | mWebView.loadDataWithBaseURL("x-data://base", html, "text/html", "UTF-8", null);
126 | }
127 |
128 |
129 | private void setupRevealBackground(Bundle savedInstanceState) {
130 | vRevealBackground.setOnStateChangeListener(this);
131 | if (savedInstanceState == null) {
132 | final int[] startingLocation = getIntent().getIntArrayExtra(Constant.START_LOCATION);
133 | vRevealBackground.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
134 | @Override
135 | public boolean onPreDraw() {
136 | vRevealBackground.getViewTreeObserver().removeOnPreDrawListener(this);
137 | vRevealBackground.startFromLocation(startingLocation);
138 | return true;
139 | }
140 | });
141 | } else {
142 | vRevealBackground.setToFinishedFrame();
143 | }
144 | }
145 |
146 | @Override
147 | public void onStateChange(int state) {
148 | if (RevealBackgroundView.STATE_FINISHED == state) {
149 | mAppBarLayout.setVisibility(View.VISIBLE);
150 | setStatusBarColor(Color.TRANSPARENT);
151 | }
152 | }
153 |
154 | @Override
155 | public void onBackPressed() {
156 | finish();
157 | overridePendingTransition(0, R.anim.slide_out_to_left_from_right);
158 | }
159 |
160 | @TargetApi(21)
161 | private void setStatusBarColor(int statusBarColor) {
162 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
163 | // If both system bars are black, we can remove these from our layout,
164 | // removing or shrinking the SurfaceFlinger overlay required for our views.
165 | Window window = this.getWindow();
166 | if (statusBarColor == Color.BLACK && window.getNavigationBarColor() == Color.BLACK) {
167 | window.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
168 | } else {
169 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
170 | }
171 | window.setStatusBarColor(statusBarColor);
172 | }
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/app/src/main/java/krelve/app/kuaihu/view/Kanner.java:
--------------------------------------------------------------------------------
1 | package krelve.app.kuaihu.view;
2 |
3 | import android.content.Context;
4 | import android.os.Handler;
5 | import android.support.v4.view.PagerAdapter;
6 | import android.support.v4.view.ViewPager;
7 | import android.support.v4.view.ViewPager.OnPageChangeListener;
8 | import android.util.AttributeSet;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.View.OnClickListener;
12 | import android.view.ViewGroup;
13 | import android.widget.FrameLayout;
14 | import android.widget.ImageView;
15 | import android.widget.ImageView.ScaleType;
16 | import android.widget.LinearLayout;
17 | import android.widget.TextView;
18 |
19 | import com.nostra13.universalimageloader.core.DisplayImageOptions;
20 | import com.nostra13.universalimageloader.core.ImageLoader;
21 |
22 | import java.util.ArrayList;
23 | import java.util.List;
24 |
25 | import krelve.app.kuaihu.Kpplication;
26 | import krelve.app.kuaihu.R;
27 | import krelve.app.kuaihu.model.Latest;
28 |
29 | public class Kanner extends FrameLayout implements OnClickListener {
30 | private List topStoriesEntities;
31 | private ImageLoader mImageLoader;
32 | private DisplayImageOptions options;
33 | private List views;
34 | private Context context;
35 | private ViewPager vp;
36 | private boolean isAutoPlay;
37 | private int currentItem;
38 | private int delayTime;
39 | private LinearLayout ll_dot;
40 | private List iv_dots;
41 | private Handler handler = new Handler();
42 | private OnItemClickListener mItemClickListener;
43 |
44 | public Kanner(Context context, AttributeSet attrs, int defStyle) {
45 | super(context, attrs, defStyle);
46 | mImageLoader = ImageLoader.getInstance();
47 | options = new DisplayImageOptions.Builder()
48 | .cacheInMemory(true)
49 | .cacheOnDisk(true)
50 | .build();
51 | this.context = context;
52 | this.topStoriesEntities = new ArrayList<>();
53 | initView();
54 | }
55 |
56 | private void initView() {
57 | views = new ArrayList();
58 | iv_dots = new ArrayList();
59 | delayTime = 2000;
60 | }
61 |
62 | public Kanner(Context context, AttributeSet attrs) {
63 | this(context, attrs, 0);
64 | }
65 |
66 | public Kanner(Context context) {
67 | this(context, null);
68 | }
69 |
70 | public void setTopEntities(List topEntities) {
71 | this.topStoriesEntities = topEntities;
72 | reset();
73 | }
74 |
75 | private void reset() {
76 | views.clear();
77 | initUI();
78 | }
79 |
80 | private void initUI() {
81 | View view = LayoutInflater.from(context).inflate(
82 | R.layout.kanner_layout, this, true);
83 | vp = (ViewPager) view.findViewById(R.id.vp);
84 | ll_dot = (LinearLayout) view.findViewById(R.id.ll_dot);
85 | ll_dot.removeAllViews();
86 |
87 | int len = topStoriesEntities.size();
88 | for (int i = 0; i < len; i++) {
89 | ImageView iv_dot = new ImageView(context);
90 | LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
91 | LinearLayout.LayoutParams.WRAP_CONTENT,
92 | LinearLayout.LayoutParams.WRAP_CONTENT);
93 | params.leftMargin = 5;
94 | params.rightMargin = 5;
95 | ll_dot.addView(iv_dot, params);
96 | iv_dots.add(iv_dot);
97 | }
98 |
99 | for (int i = 0; i <= len + 1; i++) {
100 | View fm = LayoutInflater.from(context).inflate(
101 | R.layout.kanner_content_layout, null);
102 | ImageView iv = (ImageView) fm.findViewById(R.id.iv_title);
103 | TextView tv_title = (TextView) fm.findViewById(R.id.tv_title);
104 | iv.setScaleType(ScaleType.CENTER_CROP);
105 | // iv.setBackgroundResource(R.drawable.loading1);
106 | if (i == 0) {
107 | mImageLoader.displayImage(topStoriesEntities.get(len - 1).getImage(), iv, options);
108 | tv_title.setText(topStoriesEntities.get(len - 1).getTitle());
109 | } else if (i == len + 1) {
110 | mImageLoader.displayImage(topStoriesEntities.get(0).getImage(), iv, options);
111 | tv_title.setText(topStoriesEntities.get(0).getTitle());
112 | } else {
113 | mImageLoader.displayImage(topStoriesEntities.get(i - 1).getImage(), iv, options);
114 | tv_title.setText(topStoriesEntities.get(i - 1).getTitle());
115 | }
116 | fm.setOnClickListener(this);
117 | views.add(fm);
118 | }
119 | vp.setAdapter(new MyPagerAdapter());
120 | vp.setFocusable(true);
121 | vp.setCurrentItem(1);
122 | currentItem = 1;
123 | vp.addOnPageChangeListener(new MyOnPageChangeListener());
124 | startPlay();
125 | }
126 |
127 | private void startPlay() {
128 | isAutoPlay = true;
129 | handler.postDelayed(task, 3000);
130 | }
131 |
132 |
133 | private final Runnable task = new Runnable() {
134 |
135 | @Override
136 | public void run() {
137 | if (isAutoPlay) {
138 | currentItem = currentItem % (topStoriesEntities.size() + 1) + 1;
139 | if (currentItem == 1) {
140 | vp.setCurrentItem(currentItem, false);
141 | handler.post(task);
142 | } else {
143 | vp.setCurrentItem(currentItem);
144 | handler.postDelayed(task, 5000);
145 | }
146 | } else {
147 | handler.postDelayed(task, 5000);
148 | }
149 | }
150 | };
151 |
152 | class MyPagerAdapter extends PagerAdapter {
153 |
154 | @Override
155 | public int getCount() {
156 | return views.size();
157 | }
158 |
159 | @Override
160 | public boolean isViewFromObject(View arg0, Object arg1) {
161 | return arg0 == arg1;
162 | }
163 |
164 | @Override
165 | public Object instantiateItem(ViewGroup container, int position) {
166 | container.addView(views.get(position));
167 | return views.get(position);
168 | }
169 |
170 | @Override
171 | public void destroyItem(ViewGroup container, int position, Object object) {
172 | container.removeView((View) object);
173 | }
174 |
175 | }
176 |
177 | class MyOnPageChangeListener implements OnPageChangeListener {
178 |
179 | @Override
180 | public void onPageScrollStateChanged(int arg0) {
181 | switch (arg0) {
182 | case 1:
183 | isAutoPlay = false;
184 | break;
185 | case 2:
186 | isAutoPlay = true;
187 | break;
188 | case 0:
189 | if (vp.getCurrentItem() == 0) {
190 | vp.setCurrentItem(topStoriesEntities.size(), false);
191 | } else if (vp.getCurrentItem() == topStoriesEntities.size() + 1) {
192 | vp.setCurrentItem(1, false);
193 | }
194 | currentItem = vp.getCurrentItem();
195 | isAutoPlay = true;
196 | break;
197 | }
198 | }
199 |
200 | @Override
201 | public void onPageScrolled(int arg0, float arg1, int arg2) {
202 | }
203 |
204 | @Override
205 | public void onPageSelected(int arg0) {
206 | for (int i = 0; i < iv_dots.size(); i++) {
207 | if (i == arg0 - 1) {
208 | iv_dots.get(i).setImageResource(R.drawable.dot_focus);
209 | } else {
210 | iv_dots.get(i).setImageResource(R.drawable.dot_blur);
211 | }
212 | }
213 |
214 | }
215 |
216 | }
217 |
218 |
219 | public void setOnItemClickListener(OnItemClickListener mItemClickListener) {
220 | this.mItemClickListener = mItemClickListener;
221 | }
222 |
223 | public interface OnItemClickListener {
224 | public void click(View v, Latest.TopStoriesEntity entity);
225 | }
226 |
227 | @Override
228 | public void onClick(View v) {
229 | if (mItemClickListener != null) {
230 | Latest.TopStoriesEntity entity = topStoriesEntities.get(vp.getCurrentItem() - 1);
231 | mItemClickListener.click(v, entity);
232 | }
233 | }
234 | }
235 |
--------------------------------------------------------------------------------
/app/src/main/java/krelve/app/kuaihu/fragment/MainFragment.java:
--------------------------------------------------------------------------------
1 | package krelve.app.kuaihu.fragment;
2 |
3 | import android.content.Intent;
4 | import android.database.Cursor;
5 | import android.database.sqlite.SQLiteDatabase;
6 | import android.os.Bundle;
7 | import android.os.Handler;
8 | import android.support.design.widget.Snackbar;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.AbsListView;
13 | import android.widget.AdapterView;
14 | import android.widget.ListView;
15 | import android.widget.TextView;
16 |
17 | import com.google.gson.Gson;
18 | import com.loopj.android.http.TextHttpResponseHandler;
19 |
20 | import org.apache.http.Header;
21 |
22 | import java.util.List;
23 |
24 | import krelve.app.kuaihu.R;
25 | import krelve.app.kuaihu.activity.LatestContentActivity;
26 | import krelve.app.kuaihu.activity.MainActivity;
27 | import krelve.app.kuaihu.adapter.MainNewsItemAdapter;
28 | import krelve.app.kuaihu.db.CacheDbHelper;
29 | import krelve.app.kuaihu.model.Before;
30 | import krelve.app.kuaihu.model.Latest;
31 | import krelve.app.kuaihu.model.StoriesEntity;
32 | import krelve.app.kuaihu.util.Constant;
33 | import krelve.app.kuaihu.util.HttpUtils;
34 | import krelve.app.kuaihu.util.PreUtils;
35 | import krelve.app.kuaihu.view.Kanner;
36 |
37 | /**
38 | * Created by wwjun.wang on 2015/8/12.
39 | */
40 | public class MainFragment extends BaseFragment {
41 | private ListView lv_news;
42 | private MainNewsItemAdapter mAdapter;
43 | private Latest latest;
44 | private Before before;
45 | private Kanner kanner;
46 | private String date;
47 | private boolean isLoading = false;
48 | private Handler handler = new Handler();
49 |
50 | @Override
51 | protected View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
52 | ((MainActivity) mActivity).setToolbarTitle("今日热闻");
53 | View view = inflater.inflate(R.layout.main_news_layout, container, false);
54 | lv_news = (ListView) view.findViewById(R.id.lv_news);
55 | View header = inflater.inflate(R.layout.kanner, lv_news, false);
56 | kanner = (Kanner) header.findViewById(R.id.kanner);
57 | kanner.setOnItemClickListener(new Kanner.OnItemClickListener() {
58 | @Override
59 | public void click(View v, Latest.TopStoriesEntity entity) {
60 | int[] startingLocation = new int[2];
61 | v.getLocationOnScreen(startingLocation);
62 | startingLocation[0] += v.getWidth() / 2;
63 | StoriesEntity storiesEntity = new StoriesEntity();
64 | storiesEntity.setId(entity.getId());
65 | storiesEntity.setTitle(entity.getTitle());
66 | Intent intent = new Intent(mActivity, LatestContentActivity.class);
67 | intent.putExtra(Constant.START_LOCATION, startingLocation);
68 | intent.putExtra("entity", storiesEntity);
69 | intent.putExtra("isLight", ((MainActivity) mActivity).isLight());
70 | startActivity(intent);
71 | mActivity.overridePendingTransition(0, 0);
72 | }
73 | });
74 | lv_news.addHeaderView(header);
75 | mAdapter = new MainNewsItemAdapter(mActivity);
76 | lv_news.setAdapter(mAdapter);
77 | lv_news.setOnScrollListener(new AbsListView.OnScrollListener() {
78 | @Override
79 | public void onScrollStateChanged(AbsListView view, int scrollState) {
80 |
81 | }
82 |
83 | @Override
84 | public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
85 | if (lv_news != null && lv_news.getChildCount() > 0) {
86 | boolean enable = (firstVisibleItem == 0) && (view.getChildAt(firstVisibleItem).getTop() == 0);
87 | ((MainActivity) mActivity).setSwipeRefreshEnable(enable);
88 |
89 | if (firstVisibleItem + visibleItemCount == totalItemCount && !isLoading) {
90 | loadMore(Constant.BEFORE + date);
91 | }
92 | }
93 |
94 | }
95 | });
96 | lv_news.setOnItemClickListener(new AdapterView.OnItemClickListener() {
97 | @Override
98 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
99 | int[] startingLocation = new int[2];
100 | view.getLocationOnScreen(startingLocation);
101 | startingLocation[0] += view.getWidth() / 2;
102 | StoriesEntity entity = (StoriesEntity) parent.getAdapter().getItem(position);
103 | Intent intent = new Intent(mActivity, LatestContentActivity.class);
104 | intent.putExtra(Constant.START_LOCATION, startingLocation);
105 | intent.putExtra("entity", entity);
106 | intent.putExtra("isLight", ((MainActivity) mActivity).isLight());
107 | String readSequence = PreUtils.getStringFromDefault(mActivity, "read", "");
108 | String[] splits = readSequence.split(",");
109 | StringBuffer sb = new StringBuffer();
110 | if (splits.length >= 200) {
111 | for (int i = 100; i < splits.length; i++) {
112 | sb.append(splits[i] + ",");
113 | }
114 | readSequence = sb.toString();
115 | }
116 |
117 | if (!readSequence.contains(entity.getId() + "")) {
118 | readSequence = readSequence + entity.getId() + ",";
119 | }
120 | PreUtils.putStringToDefault(mActivity, "read", readSequence);
121 | TextView tv_title = (TextView) view.findViewById(R.id.tv_title);
122 | tv_title.setTextColor(getResources().getColor(R.color.clicked_tv_textcolor));
123 | startActivity(intent);
124 | mActivity.overridePendingTransition(0, 0);
125 | }
126 | });
127 | return view;
128 | }
129 |
130 | private void loadFirst() {
131 | isLoading = true;
132 | if (HttpUtils.isNetworkConnected(mActivity)) {
133 | HttpUtils.get(Constant.LATESTNEWS, new TextHttpResponseHandler() {
134 | @Override
135 | public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
136 | }
137 |
138 | @Override
139 | public void onSuccess(int statusCode, Header[] headers, String responseString) {
140 | SQLiteDatabase db = ((MainActivity) mActivity).getCacheDbHelper().getWritableDatabase();
141 | db.execSQL("replace into CacheList(date,json) values(" + Constant.LATEST_COLUMN + ",' " + responseString + "')");
142 | db.close();
143 | parseLatestJson(responseString);
144 | }
145 |
146 | });
147 | } else {
148 | SQLiteDatabase db = ((MainActivity) mActivity).getCacheDbHelper().getReadableDatabase();
149 | Cursor cursor = db.rawQuery("select * from CacheList where date = " + Constant.LATEST_COLUMN, null);
150 | if (cursor.moveToFirst()) {
151 | String json = cursor.getString(cursor.getColumnIndex("json"));
152 | parseLatestJson(json);
153 | } else {
154 | isLoading = false;
155 | }
156 | cursor.close();
157 | db.close();
158 | }
159 |
160 | }
161 |
162 | private void parseLatestJson(String responseString) {
163 | Gson gson = new Gson();
164 | latest = gson.fromJson(responseString, Latest.class);
165 | date = latest.getDate();
166 | kanner.setTopEntities(latest.getTop_stories());
167 | handler.post(new Runnable() {
168 | @Override
169 | public void run() {
170 | List storiesEntities = latest.getStories();
171 | StoriesEntity topic = new StoriesEntity();
172 | topic.setType(Constant.TOPIC);
173 | topic.setTitle("今日热闻");
174 | storiesEntities.add(0, topic);
175 | mAdapter.addList(storiesEntities);
176 | isLoading = false;
177 | }
178 | });
179 | }
180 |
181 | private void loadMore(final String url) {
182 | isLoading = true;
183 | if (HttpUtils.isNetworkConnected(mActivity)) {
184 | HttpUtils.get(url, new TextHttpResponseHandler() {
185 | @Override
186 | public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
187 | }
188 |
189 | @Override
190 | public void onSuccess(int statusCode, Header[] headers, String responseString) {
191 | // PreUtils.putStringTo(Constant.CACHE, mActivity, url, responseString);
192 | SQLiteDatabase db = ((MainActivity) mActivity).getCacheDbHelper().getWritableDatabase();
193 | db.execSQL("replace into CacheList(date,json) values(" + date + ",' " + responseString + "')");
194 | db.close();
195 | parseBeforeJson(responseString);
196 |
197 | }
198 |
199 | });
200 | } else {
201 | SQLiteDatabase db = ((MainActivity) mActivity).getCacheDbHelper().getReadableDatabase();
202 | Cursor cursor = db.rawQuery("select * from CacheList where date = " + date, null);
203 | if (cursor.moveToFirst()) {
204 | String json = cursor.getString(cursor.getColumnIndex("json"));
205 | parseBeforeJson(json);
206 | } else {
207 | db.delete("CacheList", "date < " + date, null);
208 | isLoading = false;
209 | Snackbar sb = Snackbar.make(lv_news, "没有更多的离线内容了~", Snackbar.LENGTH_SHORT);
210 | sb.getView().setBackgroundColor(getResources().getColor(((MainActivity) mActivity).isLight() ? android.R.color.holo_blue_dark : android.R.color.black));
211 | sb.show();
212 | }
213 | cursor.close();
214 | db.close();
215 | }
216 | }
217 |
218 | private void parseBeforeJson(String responseString) {
219 | Gson gson = new Gson();
220 | before = gson.fromJson(responseString, Before.class);
221 | if (before == null) {
222 | isLoading = false;
223 | return;
224 | }
225 | date = before.getDate();
226 | handler.post(new Runnable() {
227 | @Override
228 | public void run() {
229 | List storiesEntities = before.getStories();
230 | StoriesEntity topic = new StoriesEntity();
231 | topic.setType(Constant.TOPIC);
232 | topic.setTitle(convertDate(date));
233 | storiesEntities.add(0, topic);
234 | mAdapter.addList(storiesEntities);
235 | isLoading = false;
236 | }
237 | });
238 | }
239 |
240 | @Override
241 | protected void initData() {
242 | super.initData();
243 | loadFirst();
244 | }
245 |
246 | private String convertDate(String date) {
247 | String result = date.substring(0, 4);
248 | result += "年";
249 | result += date.substring(4, 6);
250 | result += "月";
251 | result += date.substring(6, 8);
252 | result += "日";
253 | return result;
254 | }
255 |
256 | public void updateTheme() {
257 | mAdapter.updateTheme();
258 | }
259 | }
260 |
--------------------------------------------------------------------------------
/app/src/main/assets/css/news.css:
--------------------------------------------------------------------------------
1 | article,
2 | aside,
3 | details,
4 | figcaption,
5 | figure,
6 | footer,
7 | header,
8 | hgroup,
9 | main,
10 | nav,
11 | section,
12 | summary {
13 | display: block;
14 | }
15 | audio,
16 | canvas,
17 | video {
18 | display: inline-block;
19 | }
20 | audio:not([controls]) {
21 | display: none;
22 | height: 0;
23 | }
24 | html {
25 | font-family: sans-serif;
26 | -webkit-text-size-adjust: 100%;
27 | }
28 | body {
29 | font-family: 'Helvetica Neue', Helvetica, Arial, Sans-serif;
30 | background: #fff;
31 | padding-top: 0;
32 | margin: 0;
33 | }
34 | a:focus {
35 | outline: thin dotted;
36 | }
37 | a:active,
38 | a:hover {
39 | outline: 0;
40 | }
41 | h1 {
42 | margin: .67em 0;
43 | }
44 | h1,
45 | h2,
46 | h3,
47 | h4,
48 | h5,
49 | h6 {
50 | font-size: 16px;
51 | }
52 | abbr[title] {
53 | border-bottom: 1px dotted;
54 | }
55 | hr {
56 | box-sizing: content-box;
57 | height: 0;
58 | }
59 | mark {
60 | background: #ff0;
61 | color: #000;
62 | }
63 | code,
64 | kbd,
65 | pre,
66 | samp {
67 | font-family: monospace,serif;
68 | font-size: 1em;
69 | }
70 | pre {
71 | white-space: pre-wrap;
72 | }
73 | q {
74 | quotes: \201C\201D\2018\2019;
75 | }
76 | small {
77 | font-size: 80%;
78 | }
79 | sub,
80 | sup {
81 | font-size: 75%;
82 | line-height: 0;
83 | position: relative;
84 | vertical-align: baseline;
85 | }
86 | sup {
87 | top: -0.5em;
88 | }
89 | sub {
90 | bottom: -0.25em;
91 | }
92 | img {
93 | border: 0;
94 | vertical-align: middle;
95 | color: transparent;
96 | font-size: 0;
97 | }
98 | svg:not(:root) {
99 | overflow: hidden;
100 | }
101 | figure {
102 | margin: 0;
103 | }
104 | fieldset {
105 | border: 1px solid silver;
106 | margin: 0 2px;
107 | padding: .35em .625em .75em;
108 | }
109 | legend {
110 | border: 0;
111 | padding: 0;
112 | }
113 | table {
114 | border-collapse: collapse;
115 | border-spacing: 0;
116 | overflow: hidden;
117 | }
118 | a {
119 | text-decoration: none;
120 | }
121 | blockquote {
122 | border-left: 3px solid #D0E5F2;
123 | font-style: normal;
124 | display: block;
125 | line-height: 1.4em;
126 | vertical-align: baseline;
127 | font-size: 100%;
128 | margin: .5em 0;
129 | padding: 0 0 0 .5em;
130 | }
131 | ul,
132 | ol {
133 | padding-left: 20px;
134 | }
135 | .main-wrap {
136 | max-width: 100%;
137 | min-width: 300px;
138 | margin: 0 auto;
139 | }
140 | .content-wrap {
141 | overflow: hidden;
142 | background-color: #f9f9f9;
143 | }
144 | .content-wrap a {
145 | word-break: break-all;
146 | }
147 | .headline {
148 | border-bottom: 4px solid #f6f6f6;
149 | }
150 | .headline-title.onlyheading {
151 | margin: 20px 0;
152 | }
153 | .headline img {
154 | max-width: 100%;
155 | vertical-align: top;
156 | }
157 | .headline-background-link {
158 | line-height: 2em;
159 | position: relative;
160 | display: block;
161 | padding: 20px 45px 20px 20px !important;
162 | }
163 | .icon-arrow-right {
164 | position: absolute;
165 | top: 50%;
166 | right: 20px;
167 | background-image: url(http://static.daily.zhihu.com/img/share-icons.png);
168 | background-repeat: no-repeat;
169 | display: inline-block;
170 | vertical-align: middle;
171 | background-position: -70px -20px;
172 | width: 10px;
173 | height: 15px;
174 | margin-top: -7.5px;
175 | }
176 | .headline-background .heading {
177 | color: #999;
178 | font-size: 15px!important;
179 | margin-bottom: 8px;
180 | line-height: 1em;
181 | }
182 | .headline-background .heading-content {
183 | color: #444;
184 | font-size: 17px!important;
185 | line-height: 1.2em;
186 | }
187 | .headline-title {
188 | line-height: 1.2em;
189 | color: #000;
190 | font-size: 22px;
191 | margin: 20px 0 10px;
192 | padding: 0 20px!important;
193 | font-weight: bold;
194 | }
195 | .meta {
196 | white-space: nowrap;
197 | text-overflow: ellipsis;
198 | overflow: hidden;
199 | font-size: 16px;
200 | color: #b8b8b8;
201 | }
202 | .meta .source-icon {
203 | width: 20px;
204 | height: 20px;
205 | margin-right: 4px;
206 | }
207 | .meta .time {
208 | float: right;
209 | margin-top: 2px;
210 | }
211 | .content {
212 | color: #444;
213 | line-height: 1.6em;
214 | font-size: 17px;
215 | margin: 10px 0 20px;
216 | }
217 | .content img {
218 | max-width: 100%;
219 | display: block;
220 | margin: 10px 0;
221 | }
222 | .content img[src*="zhihu.com/equation"] {
223 | display: inline-block;
224 | margin: 0 3px;
225 | }
226 | .content a {
227 | color: #259;
228 | }
229 | .content a:hover {
230 | text-decoration: underline;
231 | }
232 | .view-more {
233 | margin-bottom: 25px;
234 | text-align: center;
235 | }
236 | .view-more a {
237 | font-size: 16px;
238 | display: inline-block;
239 | width: 125px;
240 | height: 30px;
241 | line-height: 30px;
242 | background: #f0f0f0;
243 | color: #B8B8B8;
244 | }
245 | .question {
246 | overflow: hidden;
247 | padding: 0 20px!important;
248 | }
249 | .question + .question {
250 | border-top: 5px solid #f6f6f6;
251 | }
252 | .question-title {
253 | line-height: 1.4em;
254 | color: #000;
255 | font-weight: 700;
256 | font-size: 18px;
257 | margin: 20px 0;
258 | }
259 | .meta .author {
260 | color: #444;
261 | font-weight: 700;
262 | }
263 | .answer + .answer {
264 | border-top: 2px solid #f6f6f6;
265 | padding-top: 20px;
266 | }
267 | .footer {
268 | text-align: center;
269 | color: #b8b8b8;
270 | font-size: 13px;
271 | padding: 20px 0;
272 | }
273 | .footer a {
274 | color: #b8b8b8;
275 | }
276 | .question .view-more a {
277 | width: 100%;
278 | display: block;
279 | }
280 | .hot-comment {
281 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
282 | }
283 | .comment-label {
284 | font-size: 16px;
285 | color: #333;
286 | line-height: 1.5em;
287 | font-weight: 700;
288 | border-top: 1px solid #eee;
289 | border-bottom: 1px solid #eee;
290 | margin: 0;
291 | padding: 9px 20px;
292 | }
293 | .comment-list {
294 | margin-bottom: 20px;
295 | }
296 | .comment-item {
297 | font-size: 15px;
298 | color: #666;
299 | border-bottom: 1px solid #eee;
300 | padding: 15px 20px;
301 | }
302 | .comment-meta {
303 | position: relative;
304 | margin-bottom: 10px;
305 | }
306 | .comment-meta .author {
307 | vertical-align: middle;
308 | color: #444;
309 | }
310 | .comment-meta .vote {
311 | position: absolute;
312 | color: #b8b8b8;
313 | font-size: 12px;
314 | right: 0;
315 | }
316 | .night .comment-label {
317 | color: #b8b8b8;
318 | border-top: 1px solid #303030;
319 | border-bottom: 1px solid #303030;
320 | }
321 | .night .comment-item {
322 | color: #7f7f7f;
323 | border-bottom: 1px solid #303030;
324 | }
325 | .icon-vote,
326 | .icon-voted {
327 | background-repeat: no-repeat;
328 | display: inline-block;
329 | vertical-align: 0;
330 | width: 11px;
331 | height: 12px;
332 | margin-right: 4px;
333 | background-image: url(http://static.daily.zhihu.com/img/app/Comment_Vote.png) !important;
334 | }
335 | .icon-voted {
336 | background-image: url(http://static.daily.zhihu.com/img/app/Comment_Voted.png) !important;
337 | }
338 | .night .icon-vote {
339 | background-image: url(http://static.daily.zhihu.com/img/app/Dark_Comment_Vote.png) !important;
340 | }
341 | .img-wrap .headline-title {
342 | bottom: 5px;
343 | }
344 | .img-wrap .img-source {
345 | right: 10px!important;
346 | font-size: 9px;
347 | }
348 | .global-header {
349 | position: static;
350 | }
351 | .button {
352 | width: 60px;
353 | }
354 | .button i {
355 | margin-right: 0;
356 | }
357 | .headline .img-place-holder {
358 | height: 200px;
359 | }
360 | .from-column {
361 | width: 280px;
362 | line-height: 30px;
363 | height: 30px;
364 | padding-left: 90px;
365 | color: #2aacec;
366 | background-image: url(http://static.daily.zhihu.com/img/News_Column_Entrance.png);
367 | box-sizing: border-box;
368 | margin: 0 20px 20px;
369 | }
370 | .from-column:active {
371 | background-image: url(http://static.daily.zhihu.com/img/News_Column_Entrance_Highlight.png);
372 | }
373 | .night .headline {
374 | border-bottom: 4px solid #303030;
375 | }
376 | .night img {
377 | -webkit-mask-image: -webkit-gradient(linear, 0 0, 0 100%, from(rgba(0, 0, 0, 0.7)), to(rgba(0, 0, 0, 0.7)));
378 | }
379 | body.night,
380 | .night .content-wrap {
381 | background: #343434;
382 | }
383 | .night .answer + .answer {
384 | border-top: 2px solid #303030;
385 | }
386 | .night .question + .question {
387 | border-top: 4px solid #303030;
388 | }
389 | .night .view-more a {
390 | background: #292929;
391 | color: #666;
392 | }
393 | .night .icon-arrow-right {
394 | background-image: url(http://static.daily.zhihu.com/img/share-icons.png);
395 | background-repeat: no-repeat;
396 | display: inline-block;
397 | vertical-align: middle;
398 | background-position: -70px -35px;
399 | width: 10px;
400 | height: 15px;
401 | }
402 | .night blockquote,
403 | .night sup {
404 | border-left: 3px solid #666;
405 | }
406 | .night .content a {
407 | color: #698ebf;
408 | }
409 | .night .from-column {
410 | color: #2b82ac;
411 | background-image: url(http://static.daily.zhihu.com/img/Dark_News_Column_Entrance.png);
412 | }
413 | .night .from-column:active {
414 | background-image: url(http://static.daily.zhihu.com/img/Dark_News_Column_Entrance_Highlight.png);
415 | }
416 | .large .question-title {
417 | font-size: 24px;
418 | }
419 | .large .meta {
420 | font-size: 18px;
421 | }
422 | .large .content {
423 | font-size: 20px;
424 | }
425 | .large blockquote,
426 | .large sup {
427 | line-height: 1.6;
428 | }
429 | .meta .meta-item {
430 | -o-text-overflow: ellipsis;
431 | width: 39%;
432 | overflow: hidden;
433 | white-space: nowrap;
434 | text-overflow: ellipsis;
435 | display: inline-block;
436 | color: #929292;
437 | margin-right: 7px;
438 | }
439 | .headline .meta {
440 | white-space: nowrap;
441 | text-overflow: ellipsis;
442 | overflow: hidden;
443 | font-size: 11px;
444 | color: #b8b8b8;
445 | margin: 15px 0;
446 | padding: 0 20px;
447 | }
448 | .headline .meta a,
449 | .headline .meta a:hover {
450 | padding-left: 1em;
451 | margin-top: 2px;
452 | float: right;
453 | font-size: 11px;
454 | color: #0066cf;
455 | text-decoration: none;
456 | }
457 | .highlight {
458 | overflow: auto;
459 | word-wrap: normal;
460 | background: #fff;
461 | }
462 | .highlight pre {
463 | white-space: pre;
464 | }
465 | .highlight .hll {
466 | background-color: #ffc;
467 | }
468 | .highlight .err {
469 | color: #a61717;
470 | background-color: #e3d2d2;
471 | }
472 | .highlight .cp {
473 | color: #999;
474 | font-weight: 700;
475 | }
476 | .highlight .cs {
477 | color: #999;
478 | font-weight: 700;
479 | font-style: italic;
480 | }
481 | .highlight .gd {
482 | color: #000;
483 | background-color: #fdd;
484 | }
485 | .highlight .gi {
486 | color: #000;
487 | background-color: #dfd;
488 | }
489 | .highlight .gu {
490 | color: #aaa;
491 | }
492 | .highlight .ni {
493 | color: purple;
494 | }
495 | .highlight .nt {
496 | color: navy;
497 | }
498 | .highlight .w {
499 | color: #bbb;
500 | }
501 | .highlight .sr {
502 | color: olive;
503 | }
504 | [hidden],
505 | .button span {
506 | display: none;
507 | }
508 | b,
509 | strong,
510 | .highlight .k,
511 | .highlight .o,
512 | .highlight .gs,
513 | .highlight .kc,
514 | .highlight .kd,
515 | .highlight .kn,
516 | .highlight .kp,
517 | .highlight .kr,
518 | .highlight .ow {
519 | font-weight: 700;
520 | }
521 | dfn,
522 | .highlight .ge {
523 | font-style: italic;
524 | }
525 | .meta span,
526 | .meta .source {
527 | vertical-align: middle;
528 | }
529 | .meta .avatar,
530 | .comment-meta .avatar {
531 | width: 20px;
532 | height: 20px;
533 | border-radius: 2px;
534 | margin-right: 5px;
535 | }
536 | .meta .bio,
537 | .highlight .gh,
538 | .highlight .bp {
539 | color: #999;
540 | }
541 | .night .comment-meta .author,
542 | .night .content,
543 | .night .meta .author,
544 | .highlight .go {
545 | color: #888;
546 | }
547 | .night .headline-title,
548 | .night .headline-background .heading-content,
549 | .night .question-title {
550 | color: #B8B8B8;
551 | }
552 | .highlight .c,
553 | .highlight .cm,
554 | .highlight .c1 {
555 | color: #998;
556 | font-style: italic;
557 | }
558 | .highlight .gr,
559 | .highlight .gt {
560 | color: #a00;
561 | }
562 | .highlight .gp,
563 | .highlight .nn {
564 | color: #555;
565 | }
566 | .highlight .kt,
567 | .highlight .nc {
568 | color: #458;
569 | font-weight: 700;
570 | }
571 | .highlight .m,
572 | .highlight .mf,
573 | .highlight .mh,
574 | .highlight .mi,
575 | .highlight .mo,
576 | .highlight .il {
577 | color: #099;
578 | }
579 | .highlight .s,
580 | .highlight .sb,
581 | .highlight .sc,
582 | .highlight .sd,
583 | .highlight .s2,
584 | .highlight .se,
585 | .highlight .sh,
586 | .highlight .si,
587 | .highlight .sx,
588 | .highlight .s1,
589 | .highlight .ss {
590 | color: #d32;
591 | }
592 | .highlight .na,
593 | .highlight .nb,
594 | .highlight .no,
595 | .highlight .nv,
596 | .highlight .vc,
597 | .highlight .vg,
598 | .highlight .vi {
599 | color: teal;
600 | }
601 | .highlight .ne,
602 | .highlight .nf {
603 | color: #900;
604 | font-weight: 700;
605 | }
606 | .answer h1,
607 | .answer h2,
608 | .answer h3,
609 | .answer h4,
610 | .answer h5 {
611 | font-size: 19px;
612 | }
613 | @media only screen and (-webkit-min-device-pixel-ratio2), only screen and (min-device-pixel-ratio2) {
614 | .icon-arrow-right {
615 | background-image: url(http://static.daily.zhihu.com/img/share-icons@2x.png);
616 | -webkit-background-size: 82px 55px;
617 | background-size: 82px 55px;
618 | }
619 | .icon-vote,
620 | .icon-voted {
621 | background-image: url(http://static.daily.zhihu.com/img/app/Comment_Vote@2x.png) !important;
622 | background-size: 11px 12px;
623 | }
624 | .icon-voted {
625 | background-image: url(http://static.daily.zhihu.com/img/app/Comment_Voted@2x.png) !important;
626 | }
627 | .night .icon-vote {
628 | background-image: url(http://static.daily.zhihu.com/img/app/Dark_Comment_Vote@2x.png) !important;
629 | }
630 | .from-column {
631 | background-image: url(http://static.daily.zhihu.com/img/News_Column_Entrance@2x.png) !important;
632 | background-size: 280px 30px;
633 | }
634 | .from-column:active {
635 | background-image: url(http://static.daily.zhihu.com/img/News_Column_Entrance_Highlight@2x.png) !important;
636 | }
637 | .night .from-column {
638 | color: #2b82ac;
639 | background-image: url(http://static.daily.zhihu.com/img/Dark_News_Column_Entrance@2x.png) !important;
640 | }
641 | .night .from-column:active {
642 | background-image: url(http://static.daily.zhihu.com/img/Dark_News_Column_Entrance_Highlight@2x.png) !important;
643 | }
644 | }
645 | .meta .meta-item {
646 | width: 39%;
647 | overflow: hidden;
648 | white-space: nowrap;
649 | text-overflow: ellipsis;
650 | display: inline-block;
651 | color: #929292;
652 | margin-right: 7px;
653 | }
654 | .headline .meta {
655 | white-space: nowrap;
656 | text-overflow: ellipsis;
657 | overflow: hidden;
658 | font-size: 11px;
659 | color: #b8b8b8;
660 | margin: 20px 0;
661 | padding: 0 20px;
662 | }
663 | .headline .meta a,
664 | .headline .meta a:hover {
665 | margin-top: 2px;
666 | float: right;
667 | font-size: 11px;
668 | color: #0066cf;
669 | text-decoration: none;
670 | }
671 | .answer h1,
672 | .answer h2,
673 | .answer h3,
674 | .answer h4,
675 | .answer h5 {
676 | font-size: 19px;
677 | }
678 | .origin-source,
679 | a.origin-source:link {
680 | display: block;
681 | margin: 25px 0;
682 | height: 50px;
683 | overflow: hidden;
684 | background: #f0f0f0;
685 | color: #888;
686 | position: relative;
687 | -webkit-touch-callout: none;
688 | }
689 | .origin-source .source-logo,
690 | a.origin-source:link .source-logo {
691 | float: left;
692 | width: 50px;
693 | height: 50px;
694 | margin-right: 10px;
695 | }
696 | .origin-source .text,
697 | a.origin-source:link .text {
698 | line-height: 50px;
699 | height: 50px;
700 | font-size: 13px;
701 | }
702 | .origin-source.with-link .text {
703 | color: #333;
704 | }
705 | .origin-source.with-link:after {
706 | display: block;
707 | position: absolute;
708 | border-color: transparent transparent transparent #f0f0f0;
709 | border-width: 7px;
710 | border-style: solid;
711 | height: 0;
712 | width: 0;
713 | top: 18px;
714 | right: 4px;
715 | line-height: 0;
716 | content: "";
717 | }
718 | .origin-source.with-link:before {
719 | display: block;
720 | height: 0;
721 | width: 0;
722 | position: absolute;
723 | top: 18px;
724 | right: 3px;
725 | border-color: transparent transparent transparent #000;
726 | border-width: 7px;
727 | border-style: solid;
728 | line-height: 0;
729 | content: "";
730 | }
731 | .origin-source-wrap {
732 | position: relative;
733 | background: #f0f0f0;
734 | }
735 | .origin-source-wrap .focus-link {
736 | position: absolute;
737 | right: 0;
738 | top: 0;
739 | width: 45px;
740 | color: #00a2ed;
741 | height: 50px;
742 | display: none;
743 | text-align: center;
744 | font-size: 12px;
745 | -webkit-touch-callout: none;
746 | }
747 | .origin-source-wrap .focus-link .btn-label {
748 | text-align: center;
749 | display: block;
750 | margin-top: 8px;
751 | border-left: solid 1px #ccc;
752 | height: 34px;
753 | line-height: 34px;
754 | }
755 | .origin-source-wrap.unfocused .focus-link {
756 | display: block;
757 | }
758 | .origin-source-wrap.unfocused .origin-source:before,
759 | .origin-source-wrap.unfocused .origin-source:after {
760 | display: none;
761 | }
762 | .night .origin-source-wrap {
763 | background: #292929;
764 | }
765 | .night .origin-source-wrap .focus-link {
766 | color: #116f9e;
767 | }
768 | .night .origin-source-wrap .btn-label {
769 | border-left: solid 1px #3f3f3f;
770 | }
771 | .night .origin-source,
772 | .night .origin-source.with-link {
773 | background: #292929;
774 | color: #666;
775 | }
776 | .night .origin-source .text,
777 | .night .origin-source.with-link .text {
778 | color: #666;
779 | }
780 | .night .origin-source.with-link:after {
781 | border-color: transparent transparent transparent #292929;
782 | }
783 | .night .origin-source.with-link:before {
784 | border-color: transparent transparent transparent #666;
785 | }
786 |
--------------------------------------------------------------------------------