├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── App36Kr_CNK.iml ├── README.md ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── libs │ ├── jsoup-1.8.3.jar │ └── nineoldandroids-2.4.0.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── cniao5 │ │ └── app36kr │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── cniao5 │ │ └── app36kr_cnk │ │ ├── adapter │ │ ├── FixedPagerAdapter.java │ │ └── LeftItemAdapter.java │ │ ├── application │ │ └── CNKApplication.java │ │ ├── biz │ │ ├── ArticleDataManager.java │ │ ├── CategoryDataManager.java │ │ ├── HeadDataManager.java │ │ └── HomeNewsDataManager.java │ │ ├── common │ │ ├── Config.java │ │ ├── DefineView.java │ │ └── RequestURL.java │ │ ├── entity │ │ ├── AdHeadBean.java │ │ ├── ArticleBean.java │ │ ├── AuthorBean.java │ │ ├── CategoriesBean.java │ │ ├── HomeNewsBean.java │ │ ├── LeftItemMenu.java │ │ └── TagBean.java │ │ ├── fragment │ │ ├── HomeFragment.java │ │ ├── MainInfoFragment.java │ │ ├── PageFragment.java │ │ └── base │ │ │ └── BaseFragment.java │ │ ├── ui │ │ ├── MainActivity.java │ │ ├── WelcomeActivity.java │ │ └── base │ │ │ └── BaseActivity.java │ │ ├── utils │ │ ├── CTextUtils.java │ │ ├── CategoryDataUtils.java │ │ ├── HttpRequest.java │ │ ├── ImageUtils.java │ │ ├── MenuDataUtils.java │ │ └── OkhttpManager.java │ │ └── widget │ │ ├── CustomRelativeLayout.java │ │ ├── CustomVideoView.java │ │ ├── DragLayout.java │ │ ├── RoundAngleImageView.java │ │ └── ViewDragHelper.java │ └── res │ ├── drawable-hdpi │ ├── bottom_line_blue.9.png │ ├── bottom_line_gray.9.png │ ├── defaultbg.png │ ├── defaultbg_h.png │ ├── head_bt_bg.9.png │ ├── ic_data_loaded.png │ ├── icon_avatar.png │ ├── icon_avatar_white.png │ ├── icon_search.png │ ├── icon_search_click.png │ ├── icon_shezhi.png │ ├── icon_shoucang.png │ ├── icon_wodeguanzhu.png │ ├── icon_yijianfankui.png │ ├── icon_zhanghaoxinxi.png │ └── load_error_bak.png │ ├── drawable │ ├── bigreddot.xml │ ├── btn_serach_selector.xml │ └── reddot.xml │ ├── layout │ ├── activity_main.xml │ ├── empty.xml │ ├── error.xml │ ├── gallery_indicator_layout.xml │ ├── home_fragment_layout.xml │ ├── item_gallery_layout.xml │ ├── item_home_news_layout.xml │ ├── item_left_menu_layout.xml │ ├── item_text.xml │ ├── left_view_layout.xml │ ├── loading.xml │ ├── main_info_fragment_layout.xml │ ├── page_fragment_layout.xml │ ├── top_bar_common_layout.xml │ └── welcome_layout.xml │ ├── menu │ └── menu_main.xml │ ├── mipmap-hdpi │ ├── head_bg.png │ ├── ic_launcher.png │ └── shadow.9.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── raw │ └── kr36.mp4 │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── attrs.xml │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── cwidgetutil ├── .gitignore ├── build.gradle ├── cwidgetutil.iml ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── cniao5 │ │ └── cwidgetutils │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── cniao5 │ │ │ ├── adapter │ │ │ └── helper │ │ │ │ ├── BaseAdapterHelper.java │ │ │ │ ├── BaseQuickAdapter.java │ │ │ │ ├── EnhancedQuickAdapter.java │ │ │ │ └── QuickAdapter.java │ │ │ ├── cwidgetutils │ │ │ ├── AutoGallery.java │ │ │ ├── FlowIndicator.java │ │ │ └── PullToRefreshListView.java │ │ │ └── utils │ │ │ ├── SharedPreferencesHelper.java │ │ │ ├── SharedPreferencesTag.java │ │ │ └── UIUtils.java │ └── res │ │ ├── anim │ │ └── ic_loading_refresh.xml │ │ ├── drawable-hdpi │ │ ├── hui.png │ │ ├── ic_loading.png │ │ ├── ic_refresh_down.png │ │ └── lan.png │ │ ├── layout │ │ └── pull_to_refresh_header.xml │ │ └── values │ │ ├── attrs.xml │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── cniao5 │ └── cwidgetutils │ └── ExampleUnitTest.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── pull_1.gif ├── screenshot ├── Screenshot_2015-12-07-12-35-53.png ├── Screenshot_2015-12-07-12-36-11.png ├── Screenshot_2015-12-07-12-36-18.png ├── Screenshot_2015-12-07-12-38-19.png ├── Screenshot_2015-12-08-08-11-57.png ├── Screenshot_2015-12-08-08-12-03.png ├── Screenshot_2015-12-08-08-12-08.png ├── cniaonews.gif └── pull_4 (2).gif └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | /captures 8 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | App36Kr_CNK -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 | 50 | 1.7 51 | 52 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /App36Kr_CNK.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |  [菜鸟新闻](http://www.cniao5.com)客户端是一个仿照36Kr官方,实 时抓取36Kr官网数据的资讯类新闻客户端。 2 |
包括首页新闻,详情,发现,活动,实时数据抓取,侧滑效果,第三方登录以及分享,消息推送等相关功能客户端。 3 |
视频和源码都分享出来了,有需要的话直接去下载 4 |
交流QQ群:**99787482** 5 |
**下载**: 6 |
课程地址: http://www.cniao5.com/clazz/view/10076.html 7 |
视频下载链接: http://pan.baidu.com/s/1eQLyQxc 密码:3ts1 8 |

**【运行截图】** 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 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 | 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.1" 6 | 7 | defaultConfig { 8 | applicationId "com.cniao5.app36kr_cnk" 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | compile 'com.android.support:support-v4:23.1.1' 25 | compile files('libs/nineoldandroids-2.4.0.jar') 26 | compile files('libs/jsoup-1.8.3.jar') 27 | compile 'com.android.support:design:23.1.1' 28 | compile 'com.android.support:appcompat-v7:23.1.1' 29 | compile 'com.squareup.okhttp:okhttp:2.6.0' 30 | compile 'com.squareup.okio:okio:1.6.0' 31 | compile project(':cwidgetutil') 32 | compile 'com.google.code.gson:gson:2.2.4' 33 | } 34 | -------------------------------------------------------------------------------- /app/libs/jsoup-1.8.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/libs/jsoup-1.8.3.jar -------------------------------------------------------------------------------- /app/libs/nineoldandroids-2.4.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/libs/nineoldandroids-2.4.0.jar -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/jiangqq/Documents/android-sdk-macosx/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/cniao5/app36kr/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/adapter/FixedPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.adapter; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentStatePagerAdapter; 6 | import android.view.ViewGroup; 7 | 8 | import com.cniao5.app36kr_cnk.entity.CategoriesBean; 9 | import com.cniao5.app36kr_cnk.fragment.base.BaseFragment; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * 当前类注释:ViewPager Fragment自定义适配器,其中管理每个页面(Fragment集合)和Tab显示标题 15 | * ProjectName:App36Kr_CNK 16 | * Author:菜鸟窝 17 | * Description: 18 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 19 | * 打造极致课程,是菜鸟窝不变的承诺 20 | */ 21 | public class FixedPagerAdapter extends FragmentStatePagerAdapter { 22 | private List categoriesBeans; 23 | 24 | public void setCategoriesBeans(List categoriesBeans) { 25 | this.categoriesBeans = categoriesBeans; 26 | } 27 | private List fragments; 28 | public void setFragments(List fragments) { 29 | this.fragments = fragments; 30 | } 31 | 32 | public FixedPagerAdapter(FragmentManager fm) { 33 | super(fm); 34 | } 35 | @Override 36 | public Fragment getItem(int position) { 37 | return fragments.get(position); 38 | } 39 | 40 | @Override 41 | public int getCount() { 42 | return fragments.size(); 43 | } 44 | 45 | @Override 46 | public Object instantiateItem(ViewGroup container, int position) { 47 | Fragment fragment=null; 48 | try{ 49 | fragment=(Fragment)super.instantiateItem(container,position); 50 | }catch (Exception e){ 51 | 52 | } 53 | return fragment; 54 | } 55 | @Override 56 | public void destroyItem(ViewGroup container, int position, Object object) { 57 | } 58 | 59 | @Override 60 | public CharSequence getPageTitle(int position) { 61 | return categoriesBeans.get(position%categoriesBeans.size()).getTitle(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/adapter/LeftItemAdapter.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.adapter; 2 | 3 | import android.view.LayoutInflater; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.widget.BaseAdapter; 7 | import android.widget.ImageView; 8 | import android.widget.TextView; 9 | 10 | import com.cniao5.app36kr_cnk.R; 11 | import com.cniao5.app36kr_cnk.application.CNKApplication; 12 | import com.cniao5.app36kr_cnk.entity.LeftItemMenu; 13 | import com.cniao5.app36kr_cnk.utils.MenuDataUtils; 14 | 15 | import java.util.List; 16 | 17 | /** 18 | * 当前类注释: 19 | * ProjectName:App36Kr_CNK 20 | * Author:菜鸟窝 21 | * Description: 22 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 23 | * 打造极致课程,是菜鸟窝不变的承诺 24 | */ 25 | public class LeftItemAdapter extends BaseAdapter { 26 | public LayoutInflater mInflater; 27 | private List itemMenus; 28 | public LeftItemAdapter(){ 29 | mInflater=LayoutInflater.from(CNKApplication.getInstance()); 30 | itemMenus= MenuDataUtils.getItemMenus(); 31 | } 32 | @Override 33 | public int getCount() { 34 | return itemMenus!=null?itemMenus.size():0; 35 | } 36 | @Override 37 | public Object getItem(int position) { 38 | return itemMenus.get(position); 39 | } 40 | @Override 41 | public long getItemId(int position) { 42 | return position; 43 | } 44 | @Override 45 | public View getView(int position, View convertView, ViewGroup parent) { 46 | Holder _Holder=null; 47 | if(convertView==null){ 48 | _Holder=new Holder(); 49 | convertView=mInflater.inflate(R.layout.item_left_menu_layout,null); 50 | _Holder.item_left_view_img=(ImageView)convertView.findViewById(R.id.item_left_view_img); 51 | _Holder.item_left_view_title=(TextView)convertView.findViewById(R.id.item_left_view_title); 52 | convertView.setTag(_Holder); 53 | }else{ 54 | _Holder=(Holder)convertView.getTag(); 55 | } 56 | _Holder.item_left_view_img.setImageResource(itemMenus.get(position).getLeftIcon()); 57 | _Holder.item_left_view_title.setText(itemMenus.get(position).getTitle()); 58 | return convertView; 59 | } 60 | private static class Holder{ 61 | ImageView item_left_view_img; 62 | TextView item_left_view_title; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/application/CNKApplication.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.application; 2 | 3 | import android.app.Application; 4 | 5 | /** 6 | * 当前类注释:全局Application类,作为全局数据的配置以及相关参数数据初始化工作 7 | * ProjectName:App36Kr 8 | * Author:菜鸟窝 9 | * Description: 10 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 11 | * 打造极致课程,是菜鸟窝不变的承诺 12 | */ 13 | public class CNKApplication extends Application{ 14 | private static CNKApplication instance=null; 15 | @Override 16 | public void onCreate() { 17 | super.onCreate(); 18 | this.instance=this; 19 | } 20 | public static CNKApplication getInstance(){ 21 | return instance; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/biz/ArticleDataManager.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.biz; 2 | 3 | import com.cniao5.app36kr_cnk.entity.ArticleBean; 4 | import com.cniao5.app36kr_cnk.entity.AuthorBean; 5 | import com.cniao5.app36kr_cnk.entity.TagBean; 6 | import com.cniao5.app36kr_cnk.utils.CTextUtils; 7 | import com.cniao5.app36kr_cnk.utils.HttpRequest; 8 | import com.cniao5.app36kr_cnk.utils.ImageUtils; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | import org.json.JSONException; 14 | import org.json.JSONObject; 15 | import org.jsoup.Jsoup; 16 | import org.jsoup.nodes.Document; 17 | import org.jsoup.nodes.Element; 18 | import org.jsoup.select.Elements; 19 | 20 | 21 | /** 22 | * 文章详情数据 以及作者,搜索标签相关信息数据抓取服务器类 23 | * 当前类注释: 24 | * ProjectName:36KrDataCrawler 25 | * Author:菜鸟窝 26 | * Description: 27 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 28 | * 打造极致课程,是菜鸟窝不变的承诺 29 | */ 30 | public class ArticleDataManager { 31 | private String articleId; 32 | public ArticleDataManager(String articleId){ 33 | this.articleId=articleId; 34 | } 35 | /** 36 | * 进行根据HTML Document对象抓取文章相关信息 37 | * @param document 38 | * @return 39 | */ 40 | public ArticleBean getArticleBean(Document document){ 41 | ArticleBean articleBean=new ArticleBean(); 42 | //首先获取局部的文章相关数据 43 | Element singleElement=document.select("article.single-post").first(); 44 | //获取标题 45 | //single-post__title 46 | String title=singleElement.select("h1.single-post__title").first().text(); 47 | //获取时间 48 | String datetime=singleElement.select("time.timeago").first().attr("datetime"); 49 | String datetext=singleElement.select("time.timeago").first().text(); 50 | //获取头图片 51 | String headImage= ImageUtils.getCutImageUrl(singleElement.select("div.single-post-header__headline").first().select("img[src]").first().attr("src")); 52 | //获取文章内容 53 | String context=Jsoup.parseBodyFragment(singleElement.select("section.article").first().toString()).toString(); 54 | articleBean.setTitle(title); 55 | articleBean.setDatetime(datetime); 56 | articleBean.setDatetext(datetext); 57 | articleBean.setHeadImage(headImage); 58 | articleBean.setContext(CTextUtils.replaceSSymbol(context)); 59 | //抓取搜索标签 60 | Elements tagElements=singleElement.select("span.tag-item"); 61 | if(tagElements!=null&&tagElements.size()>0){ 62 | List tagBeans=new ArrayList(); 63 | for (Element element : tagElements) { 64 | Element a_Element=element.select("a").first(); 65 | String href=a_Element.attr("abs:href"); 66 | String tagname=a_Element.text(); 67 | tagBeans.add(new TagBean(href, tagname)); 68 | } 69 | articleBean.setTagBeans(tagBeans); 70 | } 71 | //开始抓取用户信息 72 | String author_Str=HttpRequest.sendPost("http://36kr.com/asynces/posts/author_info", "url_code="+articleId); 73 | AuthorBean bean=null; 74 | try { 75 | JSONObject authorObject=new JSONObject(author_Str); 76 | String name=authorObject.getString("name"); 77 | String description=CTextUtils.replaceEmail(authorObject.getString("tagline")); 78 | String avatar=ImageUtils.getCutImageUrl(authorObject.getString("avatar")); 79 | String badge=authorObject.getString("role"); 80 | String article_total=authorObject.getString("posts_count"); 81 | String read_number=authorObject.getString("views_count"); 82 | String href="http:"+authorObject.getString("more_articles"); 83 | bean=new AuthorBean(); 84 | bean.setName(name); 85 | bean.setDescription(description); 86 | bean.setAvatar(avatar); 87 | bean.setBadge(badge); 88 | bean.setArticle_total(article_total); 89 | bean.setRead_number(read_number); 90 | bean.setHref(href); 91 | } catch (JSONException e) { 92 | e.printStackTrace(); 93 | } 94 | articleBean.setAuthorBean(bean); 95 | return articleBean; 96 | } 97 | 98 | /** 99 | * 进行抓取文章详情 100 | * @param document 101 | * @return 102 | */ 103 | public ArticleBean getArticleBean_CNK(Document document){ 104 | ArticleBean bean=new ArticleBean(); 105 | Element singleElement=document.select("article.single-post").first(); 106 | String title=singleElement.select("h1.single-post__title").first().text(); 107 | String datetime=singleElement.select("time.timeago").first().attr("datetime"); 108 | String datetext=singleElement.select("time.timeago").first().text(); 109 | Element head=singleElement.select("div.single-post-header__headline").first(); 110 | String headImage= ImageUtils.getCutImageUrl(head.select("img").first().attr("src")); 111 | String context=singleElement.select("section.article").first().toString(); 112 | bean.setTitle(title); 113 | bean.setDatetime(datetime); 114 | bean.setDatetext(datetext); 115 | bean.setHeadImage(headImage); 116 | bean.setContext(context); 117 | 118 | //开始抓取标签Tag数据 119 | Elements tagsElements= singleElement.select("section.single-post-tags").first().select("span.tag-item"); 120 | List tagBeans=new ArrayList(); 121 | for (Element element : tagsElements) { 122 | String href=element.select("a").first().attr("abs:href"); 123 | String tagname=element.text(); 124 | TagBean tagBean=new TagBean(); 125 | tagBean.setHref(href); 126 | tagBean.setTagname(tagname); 127 | tagBeans.add(tagBean); 128 | } 129 | bean.setTagBeans(tagBeans); 130 | //开始抓取作者信息 131 | AuthorBean authorBean=new AuthorBean(); 132 | String result= HttpRequest.sendPost("http://36kr.com/asynces/posts/author_info", "url_code=" + articleId); 133 | try { 134 | JSONObject authorObject=new JSONObject(result); 135 | String name=authorObject.getString("name"); 136 | String avatar=authorObject.getString("avatar"); 137 | String badge=authorObject.getString("role"); 138 | String description=authorObject.getString("tagline"); 139 | String href="http:"+authorObject.getString("more_articles"); 140 | String article_total=authorObject.getString("posts_count"); 141 | String read_number=authorObject.getString("views_count"); 142 | authorBean.setName(name); 143 | authorBean.setAvatar(avatar); 144 | authorBean.setBadge(badge); 145 | authorBean.setDescription(description); 146 | authorBean.setHref(href); 147 | authorBean.setArticle_total(article_total); 148 | authorBean.setRead_number(read_number); 149 | } catch (JSONException e) { 150 | e.printStackTrace(); 151 | } 152 | bean.setAuthorBean(authorBean); 153 | return bean; 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/biz/CategoryDataManager.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.biz; 2 | 3 | import com.cniao5.app36kr_cnk.entity.CategoriesBean; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import org.jsoup.nodes.Document; 9 | import org.jsoup.nodes.Element; 10 | import org.jsoup.select.Elements; 11 | 12 | /** 13 | * 分类Tab数据抓取服务 14 | * @author jiangqq 15 | * 16 | */ 17 | public class CategoryDataManager { 18 | public CategoryDataManager(){ 19 | } 20 | 21 | public List getCategoriesBeans(Document document){ 22 | List categoriesBeans=new ArrayList(); 23 | Elements elements=document.select("div.categories").first().select("a"); 24 | for (Element element : elements) { 25 | String title=element.text(); 26 | String data_type=element.attr("data-type"); 27 | String href=element.attr("abs:href"); 28 | CategoriesBean bean=new CategoriesBean(); 29 | bean.setTitle(title); 30 | bean.setHref(href); 31 | bean.setData_type(data_type); 32 | categoriesBeans.add(bean); 33 | } 34 | return categoriesBeans; 35 | } 36 | 37 | /** 38 | * 抓取文章分类数据 39 | * @param document 40 | * @return 41 | */ 42 | public List getCategoriesBeans_CNK(Document document){ 43 | List categoriesBeans=new ArrayList(); 44 | Elements cateElement=document.select("div.categories").first().select("a"); 45 | //System.out.println(cateElement); 46 | for (Element element : cateElement) { 47 | String title=element.text(); 48 | String href=element.attr("abs:href"); 49 | String data_type=element.attr("data-type"); 50 | categoriesBeans.add(new CategoriesBean(title, href, data_type)); 51 | } 52 | return categoriesBeans; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/biz/HeadDataManager.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.biz; 2 | 3 | import com.cniao5.app36kr_cnk.entity.AdHeadBean; 4 | import com.cniao5.app36kr_cnk.utils.ImageUtils; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import org.jsoup.nodes.Document; 10 | import org.jsoup.nodes.Element; 11 | import org.jsoup.select.Elements; 12 | 13 | 14 | /** 15 | * 首页顶部广告数据抓取工具类 16 | * @author jiangqq 17 | * 18 | */ 19 | public class HeadDataManager { 20 | public HeadDataManager(){ 21 | 22 | } 23 | /** 24 | * 进行根据地址抓取顶部广告数据 25 | * @param pUrl 26 | * @return 27 | */ 28 | public List getHeadBeans(Document document){ 29 | List adHeadBeans=new ArrayList();; 30 | Elements elements=document.select("div.head-images"); 31 | Elements links = elements.first().select("a[data-lazyload]"); //带有data-lazyload属性的a元素 32 | for (Element element : links) { 33 | String title=element.text(); 34 | String href=element.attr("href"); 35 | String imgurl= ImageUtils.getCutImageUrl(element.attr("data-lazyload")); 36 | String mask= element.select("span").first().text(); 37 | AdHeadBean bean=new AdHeadBean(); 38 | bean.setTitle(title); 39 | bean.setImgurl(imgurl); 40 | bean.setHref(href); 41 | bean.setMask(mask); 42 | adHeadBeans.add(bean); 43 | } 44 | return adHeadBeans; 45 | } 46 | 47 | 48 | /** 49 | * 进行抓取广告轮播信息 50 | * @param document 51 | * @return 52 | */ 53 | public List getHeadBeans_CNK(Document document){ 54 | List adHeadBeans=new ArrayList(); 55 | Elements headElements=document.select("div.head-images").first().select("a[data-lazyload]"); 56 | //System.out.println(headElements); 57 | for (Element element : headElements) { 58 | String imgurl=ImageUtils.getCutImageUrl(element.attr("data-lazyload")); 59 | String href=element.attr("href"); 60 | String mask=element.select("span").first().text(); 61 | String title=element.text(); 62 | adHeadBeans.add(new AdHeadBean(title, imgurl, href, mask)); 63 | } 64 | return adHeadBeans; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/biz/HomeNewsDataManager.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.biz; 2 | 3 | import com.cniao5.app36kr_cnk.common.Config; 4 | import com.cniao5.app36kr_cnk.entity.AuthorBean; 5 | import com.cniao5.app36kr_cnk.entity.HomeNewsBean; 6 | import com.cniao5.app36kr_cnk.utils.ImageUtils; 7 | import com.cniao5.app36kr_cnk.utils.CTextUtils; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | import org.jsoup.nodes.Document; 12 | import org.jsoup.nodes.Element; 13 | import org.jsoup.select.Elements; 14 | 15 | 16 | /** 17 | * 首页新闻数据抓取管理器 18 | * @author jiangqq 19 | * 20 | */ 21 | public class HomeNewsDataManager { 22 | public HomeNewsDataManager(){ 23 | } 24 | /** 25 | * 进行抓取首页信息数据 26 | * @param document 27 | * @return 28 | */ 29 | public List getHomeNewsBeans(Document document){ 30 | List homeNewsBeans=new ArrayList(); 31 | Elements elements= document.select("div.articles").first().select("article"); 32 | for (Element element : elements) { 33 | //图标以及文章类型 34 | Element a_pic_element=element.select("a.pic").first(); 35 | String imgurl=""; 36 | String mask=""; 37 | if(a_pic_element!=null){ 38 | imgurl= ImageUtils.getCutImageUrl(a_pic_element.attr("data-lazyload")); 39 | mask=a_pic_element.text(); 40 | } 41 | //desc信息 连接地址和标题 42 | Element desc_element=element.select("div.desc").first(); 43 | String href=desc_element.select("a.title").first().attr("href"); 44 | //进行href过滤 因为网站又文章列表无法点击 ,所以这边直接滤过了 45 | if(href.equals("javascript:void(0)")){ 46 | continue; 47 | } 48 | String tId=CTextUtils.getTitleId(href); 49 | href=Config.CRAWLER_URL+href; 50 | String title=desc_element.select("a.title").first().text(); 51 | //作者信息 52 | Element author_element=desc_element.select("div.author").first(); 53 | //查找只存在data-lazyload属性的a标签 54 | Element link = author_element.select("a").first(); 55 | String author_href= Config.CRAWLER_URL+link.attr("href"); 56 | String avatar=ImageUtils.getCutImageUrl(link.select("span.avatar").first().attr("data-lazyload")); 57 | String name=link.text(); 58 | //时间 59 | Element time_element=author_element.select("time.timeago").first(); 60 | String datetime=""; 61 | String datetext=""; 62 | if(time_element!=null){ 63 | datetime=author_element.select("time.timeago").first().attr("title"); 64 | datetext=author_element.select("time.timeago").first().text(); 65 | }else { 66 | datetime=author_element.select("abbr.timeago").first().attr("title"); 67 | datetext=author_element.select("abbr.timeago").first().text(); 68 | } 69 | //文章简介 70 | String brief=desc_element.select("div.brief").first().text(); 71 | AuthorBean authorBean=new AuthorBean(); 72 | authorBean.setName(name); 73 | authorBean.setAvatar(avatar); 74 | authorBean.setHref(author_href); 75 | HomeNewsBean bean=new HomeNewsBean(); 76 | bean.settId(tId); 77 | bean.setImgurl(imgurl); 78 | bean.setMask(mask); 79 | bean.setHref(href); 80 | bean.setTitle(title); 81 | bean.setAuthorBean(authorBean); 82 | bean.setDatetime(datetime); 83 | bean.setBrief(brief); 84 | bean.setDatetext(datetext); 85 | homeNewsBeans.add(bean); 86 | } 87 | return homeNewsBeans; 88 | } 89 | 90 | /** 91 | * 抓取文章类别数据 根据分类 92 | * @param document 93 | * @return 94 | */ 95 | public List getHomeNewsBeans_CNK(Document document){ 96 | List homeNewsBeans=new ArrayList(); 97 | Elements articleElement=document.select("div.articles").first().select("article"); 98 | for (Element element : articleElement) { 99 | Element pic_element=element.select("a.pic").first(); 100 | String imgurl=ImageUtils.getCutImageUrl(pic_element.attr("data-lazyload")); 101 | String href=pic_element.attr("abs:href"); 102 | String mask=pic_element.text(); 103 | String aId=CTextUtils.getArticleId(href); 104 | 105 | Element descElement=element.select("div.desc").first(); 106 | String title=descElement.select("a.title").first().text(); 107 | String brief=descElement.select("div.brief").first().text(); 108 | 109 | Element authorElement=descElement.select("div.author").first(); 110 | String datetime=authorElement.select("time.timeago").first().attr("datetime"); 111 | String datetext=authorElement.select("time.timeago").first().text(); 112 | 113 | Element a_Element=authorElement.select("a").first(); 114 | String au_href=a_Element.attr("abs:href"); 115 | Element avatarElement=a_Element.select("span.avatar").first(); 116 | String avatar=avatarElement.attr("data-lazyload"); 117 | String name=a_Element.select("span.name").first().text(); 118 | AuthorBean authorBean=new AuthorBean(); 119 | authorBean.setHref(au_href); 120 | authorBean.setAvatar(avatar); 121 | authorBean.setName(name); 122 | HomeNewsBean bean=new HomeNewsBean(); 123 | bean.settId(aId); 124 | bean.setImgurl(imgurl); 125 | bean.setHref(href); 126 | bean.setMask(mask); 127 | bean.setTitle(title); 128 | bean.setBrief(brief); 129 | bean.setDatetime(datetime); 130 | bean.setDatetext(datetext); 131 | bean.setAuthorBean(authorBean); 132 | homeNewsBeans.add(bean); 133 | } 134 | 135 | return homeNewsBeans; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/common/Config.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.common; 2 | 3 | /** 4 | * 项目数据常量配置 5 | * @author jiangqq 6 | * 7 | */ 8 | public class Config { 9 | public static final String CRAWLER_URL="http://www.36kr.com"; 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/common/DefineView.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.common; 2 | 3 | /** 4 | * 当前类注释:所有的Activity,Fragment可以实现这个接口,来进行一些公共的操作 5 | * ProjectName:App36Kr 6 | * Author:菜鸟窝 7 | * Description: 8 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 9 | * 打造极致课程,是菜鸟窝不变的承诺 10 | */ 11 | public interface DefineView { 12 | 13 | public void initView(); //初始化界面元素 14 | public void initValidata(); //初始化变量 15 | public void initListener(); //初始化监听器 16 | public void bindData(); //绑定数据 17 | 18 | // public void getPageData();// show page 19 | // public void getDataOk(); // data ok 20 | // public void getDataError();// data error 21 | // public void getDataRefresh();// data refresh 22 | 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/common/RequestURL.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.common; 2 | 3 | /** 4 | * 当前类注释:做数据请求服务器地址的配置 5 | * ProjectName:App36Kr 6 | * Author:菜鸟窝 7 | * Description: 8 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 9 | * 打造极致课程,是菜鸟窝不变的承诺 10 | */ 11 | public class RequestURL { 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/entity/AdHeadBean.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.entity; 2 | 3 | /** 4 | * 首页顶部广告条信息实体类 5 | * 6 | * @author jiangqq 7 | * 8 | */ 9 | public class AdHeadBean { 10 | private String title; // 标题 11 | private String imgurl; // 图片地址 12 | private String href; // 文章详情地址 13 | private String mask; // 文章类型 14 | public AdHeadBean() { 15 | super(); 16 | } 17 | public AdHeadBean(String title, String imgurl, String href, String mask) { 18 | super(); 19 | this.title = title; 20 | this.imgurl = imgurl; 21 | this.href = href; 22 | this.mask = mask; 23 | } 24 | public String getTitle() { 25 | return title; 26 | } 27 | public void setTitle(String title) { 28 | this.title = title; 29 | } 30 | public String getImgurl() { 31 | return imgurl; 32 | } 33 | public void setImgurl(String imgurl) { 34 | this.imgurl = imgurl; 35 | } 36 | public String getHref() { 37 | return href; 38 | } 39 | public void setHref(String href) { 40 | this.href = href; 41 | } 42 | public String getMask() { 43 | return mask; 44 | } 45 | public void setMask(String mask) { 46 | this.mask = mask; 47 | } 48 | @Override 49 | public String toString() { 50 | return "AdHeadBean [title=" + title + ", imgurl=" + imgurl + ", href=" 51 | + href + ", mask=" + mask + "]"; 52 | } 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/entity/ArticleBean.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.entity; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 7 | * 当前类注释:文章详情数据bean ProjectName:36KrDataCrawler Author:菜鸟窝 Description: 9 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 打造极致课程,是菜鸟窝不变的承诺 10 | */ 11 | public class ArticleBean { 12 | private String title; // 文章标题 13 | private String datetime; // 文章发表时间 14 | private String datetext; // 文章发表时间时间 已计算 15 | private String context; // 文章内容 16 | private String headImage; //文章头图片 17 | 18 | private List tagBeans; // 文章搜索标签集合 19 | private AuthorBean authorBean; // 文章作者信息 20 | 21 | public ArticleBean() { 22 | super(); 23 | } 24 | 25 | public ArticleBean(String title, String datetime, String datetext, 26 | String context, String headImage, List tagBeans, 27 | AuthorBean authorBean) { 28 | super(); 29 | this.title = title; 30 | this.datetime = datetime; 31 | this.datetext = datetext; 32 | this.context = context; 33 | this.headImage = headImage; 34 | this.tagBeans = tagBeans; 35 | this.authorBean = authorBean; 36 | } 37 | 38 | public String getTitle() { 39 | return title; 40 | } 41 | 42 | public void setTitle(String title) { 43 | this.title = title; 44 | } 45 | 46 | public String getDatetime() { 47 | return datetime; 48 | } 49 | 50 | public void setDatetime(String datetime) { 51 | this.datetime = datetime; 52 | } 53 | 54 | public String getDatetext() { 55 | return datetext; 56 | } 57 | 58 | public void setDatetext(String datetext) { 59 | this.datetext = datetext; 60 | } 61 | 62 | public String getContext() { 63 | return context; 64 | } 65 | 66 | public void setContext(String context) { 67 | this.context = context; 68 | } 69 | 70 | public String getHeadImage() { 71 | return headImage; 72 | } 73 | 74 | public void setHeadImage(String headImage) { 75 | this.headImage = headImage; 76 | } 77 | 78 | public List getTagBeans() { 79 | return tagBeans; 80 | } 81 | 82 | public void setTagBeans(List tagBeans) { 83 | this.tagBeans = tagBeans; 84 | } 85 | 86 | public AuthorBean getAuthorBean() { 87 | return authorBean; 88 | } 89 | 90 | public void setAuthorBean(AuthorBean authorBean) { 91 | this.authorBean = authorBean; 92 | } 93 | 94 | @Override 95 | public String toString() { 96 | return "ArticleBean [title=" + title + ", datetime=" + datetime 97 | + ", datetext=" + datetext + ", context=" + context 98 | + ", headImage=" + headImage + ", tagBeans=" + tagBeans 99 | + ", authorBean=" + authorBean + "]"; 100 | } 101 | 102 | 103 | } 104 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/entity/AuthorBean.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.entity; 2 | 3 | /** 4 | * 作者用户信息实体类 5 | * 6 | * @author jiangqq 7 | * 8 | */ 9 | public class AuthorBean { 10 | private String name; // 作者名字 11 | private String avatar; // 作者头像 12 | private String href; // 作者主页地址 13 | private String badge; // 作者等级 (例如:新人作者) 14 | private String description; // 作者个人说明 15 | private String article_total; // 发表文章的总量 16 | private String read_number; // 文章的总阅读量 17 | 18 | public AuthorBean() { 19 | super(); 20 | } 21 | 22 | public AuthorBean(String name, String avatar, String href, String badge, 23 | String description, String article_total, String read_number) { 24 | super(); 25 | this.name = name; 26 | this.avatar = avatar; 27 | this.href = href; 28 | this.badge = badge; 29 | this.description = description; 30 | this.article_total = article_total; 31 | this.read_number = read_number; 32 | } 33 | 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public void setName(String name) { 39 | this.name = name; 40 | } 41 | 42 | public String getAvatar() { 43 | return avatar; 44 | } 45 | 46 | public void setAvatar(String avatar) { 47 | this.avatar = avatar; 48 | } 49 | 50 | public String getHref() { 51 | return href; 52 | } 53 | 54 | public void setHref(String href) { 55 | this.href = href; 56 | } 57 | 58 | public String getBadge() { 59 | return badge; 60 | } 61 | 62 | public void setBadge(String badge) { 63 | this.badge = badge; 64 | } 65 | 66 | public String getDescription() { 67 | return description; 68 | } 69 | 70 | public void setDescription(String description) { 71 | this.description = description; 72 | } 73 | 74 | public String getArticle_total() { 75 | return article_total; 76 | } 77 | 78 | public void setArticle_total(String article_total) { 79 | this.article_total = article_total; 80 | } 81 | 82 | public String getRead_number() { 83 | return read_number; 84 | } 85 | 86 | public void setRead_number(String read_number) { 87 | this.read_number = read_number; 88 | } 89 | 90 | @Override 91 | public String toString() { 92 | return "AuthorBean [name=" + name + ", avatar=" + avatar + ", href=" 93 | + href + ", badge=" + badge + ", description=" + description 94 | + ", article_total=" + article_total + ", read_number=" 95 | + read_number + "]"; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/entity/CategoriesBean.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 首页新闻资讯分类Tab信息实体类 7 | * 8 | * @author jiangqq 9 | * 10 | */ 11 | public class CategoriesBean implements Serializable{ 12 | private String title; // 分类Tab名称 13 | private String href; // 分类点击地址 14 | private String data_type; // 分类类型 15 | public CategoriesBean() { 16 | super(); 17 | } 18 | public CategoriesBean(String title, String href, String data_type) { 19 | super(); 20 | this.title = title; 21 | this.href = href; 22 | this.data_type = data_type; 23 | } 24 | 25 | public String getTitle() { 26 | return title; 27 | } 28 | 29 | public void setTitle(String title) { 30 | this.title = title; 31 | } 32 | 33 | public String getHref() { 34 | return href; 35 | } 36 | 37 | public void setHref(String href) { 38 | this.href = href; 39 | } 40 | 41 | public String getData_type() { 42 | return data_type; 43 | } 44 | 45 | public void setData_type(String data_type) { 46 | this.data_type = data_type; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return "CategoriesBean [title=" + title + ", href=" + href 52 | + ", data_type=" + data_type + "]"; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/entity/HomeNewsBean.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.entity; 2 | 3 | /** 4 | * 首页列表数据信息实体类 5 | * 6 | * @author jiangqq 7 | * 8 | */ 9 | public class HomeNewsBean { 10 | private String tId; //文章ID 11 | private String imgurl; // 文章列表缩略图片 12 | private String mask; // 文章类型 13 | private String href; // 文章地址 14 | AuthorBean authorBean; // 用户信息 15 | private String title; // 文章标题 16 | private String brief; // 文章简述 17 | private String datetime; // 文章发表时间 18 | private String datetext; //文章发表时间时间 已计算 19 | 20 | public HomeNewsBean() { 21 | super(); 22 | } 23 | 24 | public HomeNewsBean(String tId, String imgurl, String mask, String href, 25 | AuthorBean authorBean, String title, String brief, String datetime, 26 | String datetext) { 27 | super(); 28 | this.tId = tId; 29 | this.imgurl = imgurl; 30 | this.mask = mask; 31 | this.href = href; 32 | this.authorBean = authorBean; 33 | this.title = title; 34 | this.brief = brief; 35 | this.datetime = datetime; 36 | this.datetext = datetext; 37 | } 38 | 39 | public String gettId() { 40 | return tId; 41 | } 42 | 43 | public void settId(String tId) { 44 | this.tId = tId; 45 | } 46 | 47 | public String getImgurl() { 48 | return imgurl; 49 | } 50 | 51 | public void setImgurl(String imgurl) { 52 | this.imgurl = imgurl; 53 | } 54 | 55 | public String getMask() { 56 | return mask; 57 | } 58 | 59 | public void setMask(String mask) { 60 | this.mask = mask; 61 | } 62 | 63 | public String getHref() { 64 | return href; 65 | } 66 | 67 | public void setHref(String href) { 68 | this.href = href; 69 | } 70 | 71 | public AuthorBean getAuthorBean() { 72 | return authorBean; 73 | } 74 | 75 | public void setAuthorBean(AuthorBean authorBean) { 76 | this.authorBean = authorBean; 77 | } 78 | 79 | public String getTitle() { 80 | return title; 81 | } 82 | 83 | public void setTitle(String title) { 84 | this.title = title; 85 | } 86 | 87 | public String getBrief() { 88 | return brief; 89 | } 90 | 91 | public void setBrief(String brief) { 92 | this.brief = brief; 93 | } 94 | 95 | public String getDatetime() { 96 | return datetime; 97 | } 98 | 99 | public void setDatetime(String datetime) { 100 | this.datetime = datetime; 101 | } 102 | 103 | public String getDatetext() { 104 | return datetext; 105 | } 106 | 107 | public void setDatetext(String datetext) { 108 | this.datetext = datetext; 109 | } 110 | 111 | @Override 112 | public String toString() { 113 | return "HomeNewsBean [tId=" + tId + ", imgurl=" + imgurl + ", mask=" 114 | + mask + ", href=" + href + ", authorBean=" + authorBean 115 | + ", title=" + title + ", brief=" + brief + ", datetime=" 116 | + datetime + ", datetext=" + datetext + "]"; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/entity/LeftItemMenu.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.entity; 2 | 3 | /** 4 | * 当前类注释:左侧功能菜单 item实体类 5 | * ProjectName:App36Kr 6 | * Author:菜鸟窝 7 | * Description: 8 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 9 | * 打造极致课程,是菜鸟窝不变的承诺 10 | */ 11 | public class LeftItemMenu { 12 | private int leftIcon; 13 | private String title; 14 | public LeftItemMenu() { 15 | } 16 | 17 | public LeftItemMenu(int leftIcon, String title) { 18 | this.leftIcon = leftIcon; 19 | this.title = title; 20 | } 21 | 22 | public int getLeftIcon() { 23 | return leftIcon; 24 | } 25 | 26 | public void setLeftIcon(int leftIcon) { 27 | this.leftIcon = leftIcon; 28 | } 29 | 30 | public String getTitle() { 31 | return title; 32 | } 33 | 34 | public void setTitle(String title) { 35 | this.title = title; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return "LeftItemMenu{" + 41 | "leftIcon=" + leftIcon + 42 | ", title='" + title + '\'' + 43 | '}'; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/entity/TagBean.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.entity; 2 | 3 | /** 4 | * 5 | * 当前类注释:文章标签信息实体类 ProjectName:36KrDataCrawler Author:菜鸟窝 Description: 7 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 打造极致课程,是菜鸟窝不变的承诺 8 | */ 9 | public class TagBean { 10 | private String href; 11 | private String tagname; 12 | 13 | public TagBean() { 14 | super(); 15 | } 16 | 17 | public TagBean(String href, String tagname) { 18 | super(); 19 | this.href = href; 20 | this.tagname = tagname; 21 | } 22 | 23 | public String getHref() { 24 | return href; 25 | } 26 | 27 | public void setHref(String href) { 28 | this.href = href; 29 | } 30 | 31 | public String getTagname() { 32 | return tagname; 33 | } 34 | 35 | public void setTagname(String tagname) { 36 | this.tagname = tagname; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "TagBean [href=" + href + ", tagname=" + tagname + "]"; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/fragment/HomeFragment.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.util.Log; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.AdapterView; 9 | import android.widget.BaseAdapter; 10 | import android.widget.FrameLayout; 11 | import android.widget.ImageView; 12 | import android.widget.LinearLayout; 13 | import android.widget.TextView; 14 | 15 | import com.cniao5.adapter.helper.BaseAdapterHelper; 16 | import com.cniao5.adapter.helper.QuickAdapter; 17 | import com.cniao5.app36kr_cnk.R; 18 | import com.cniao5.app36kr_cnk.biz.HeadDataManager; 19 | import com.cniao5.app36kr_cnk.biz.HomeNewsDataManager; 20 | import com.cniao5.app36kr_cnk.common.Config; 21 | import com.cniao5.app36kr_cnk.common.DefineView; 22 | import com.cniao5.app36kr_cnk.entity.AdHeadBean; 23 | import com.cniao5.app36kr_cnk.entity.CategoriesBean; 24 | import com.cniao5.app36kr_cnk.entity.HomeNewsBean; 25 | import com.cniao5.app36kr_cnk.fragment.base.BaseFragment; 26 | import com.cniao5.app36kr_cnk.utils.OkhttpManager; 27 | import com.cniao5.cwidgetutils.AutoGallery; 28 | import com.cniao5.cwidgetutils.FlowIndicator; 29 | import com.cniao5.cwidgetutils.PullToRefreshListView; 30 | import com.squareup.okhttp.Request; 31 | import com.squareup.picasso.Picasso; 32 | 33 | import org.jsoup.Jsoup; 34 | import org.jsoup.nodes.Document; 35 | 36 | import java.util.List; 37 | 38 | /** 39 | * 当前类注释: 40 | * ProjectName:App36Kr_CNK 41 | * Author:菜鸟窝 42 | * Description: 43 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 44 | * 打造极致课程,是菜鸟窝不变的承诺 45 | */ 46 | public class HomeFragment extends BaseFragment implements DefineView { 47 | private View mView; 48 | private static final String KEY="EXTRA"; 49 | private CategoriesBean categoriesBean; 50 | private PullToRefreshListView home_listview; 51 | private List homeNewsBeans; 52 | private List adHeadBeans; 53 | private QuickAdapter quickAdapter; 54 | private String[] masks; 55 | private int[] mask_colors; 56 | private FrameLayout home_framelayout; 57 | private LinearLayout loading,empty,error; 58 | private View headView; 59 | private LayoutInflater mInflater; 60 | private AutoGallery headline_image_gallery; 61 | private FlowIndicator headline_circle_indicator; 62 | private int gallerySelectedPositon=0;//Gallery索引 63 | private int circleSelectedPosition = 0; // 默认指示器的圆圈的位置为第一 64 | 65 | public static HomeFragment newInstance(CategoriesBean extra){ 66 | Bundle bundle=new Bundle(); 67 | bundle.putSerializable(KEY,extra); 68 | HomeFragment fragment=new HomeFragment(); 69 | fragment.setArguments(bundle); 70 | return fragment; 71 | } 72 | @Override 73 | public void onCreate(Bundle savedInstanceState) { 74 | super.onCreate(savedInstanceState); 75 | Bundle bundle=getArguments(); 76 | if(bundle!=null) { 77 | categoriesBean=(CategoriesBean)bundle.getSerializable(KEY); 78 | } 79 | } 80 | @Override 81 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 82 | if(mView==null){ 83 | mView=inflater.inflate(R.layout.home_fragment_layout,container,false); 84 | mInflater=LayoutInflater.from(getActivity()); 85 | headView=mInflater.inflate(R.layout.gallery_indicator_layout,null); 86 | initView(); 87 | initValidata(); 88 | initListener(); 89 | } 90 | return mView; 91 | } 92 | 93 | @Override 94 | public void initView() { 95 | home_listview=(PullToRefreshListView)mView.findViewById(R.id.home_listview); 96 | home_listview.addHeaderView(headView); 97 | home_framelayout=(FrameLayout)mView.findViewById(R.id.home_framelayout); 98 | loading=(LinearLayout)mView.findViewById(R.id.loading); 99 | empty=(LinearLayout)mView.findViewById(R.id.empty); 100 | error=(LinearLayout)mView.findViewById(R.id.error); 101 | 102 | //获取AutoGallery和FlowIndicator控件 103 | headline_image_gallery=(AutoGallery)headView.findViewById(R.id.headline_image_gallery); 104 | headline_circle_indicator=(FlowIndicator)headView.findViewById(R.id.headline_circle_indicator); 105 | } 106 | @Override 107 | public void initValidata() { 108 | masks=new String[]{"氪TV","O2O","新硬件","Fun!!","企业服务","Fit&Health","在线教育","互联网金融","大公司","专栏"}; 109 | mask_colors=new int[]{R.color.mask_tags_1,R.color.mask_tags_2, 110 | R.color.mask_tags_3,R.color.mask_tags_4,R.color.mask_tags_5, 111 | R.color.mask_tags_6,R.color.mask_tags_7,R.color.mask_tags_8, 112 | R.color.mask_tags_9,R.color.mask_tags_10,R.color.mask_tags_11,R.color.mask_tags_12}; 113 | 114 | home_listview.setVisibility(View.GONE); 115 | home_framelayout.setVisibility(View.VISIBLE); 116 | loading.setVisibility(View.VISIBLE); 117 | empty.setVisibility(View.GONE); 118 | error.setVisibility(View.GONE); 119 | 120 | OkhttpManager.getAsync(categoriesBean.getHref(), new OkhttpManager.DataCallBack() { 121 | @Override 122 | public void requestFailure(Request request, Exception e) { 123 | Log.d("zttjianggqq","首页新闻数据加载失败..."); 124 | } 125 | @Override 126 | public void requestSuccess(String result) { 127 | Document document=Jsoup.parse(result, Config.CRAWLER_URL); 128 | adHeadBeans=new HeadDataManager().getHeadBeans(document); 129 | homeNewsBeans=new HomeNewsDataManager().getHomeNewsBeans(document); 130 | if(adHeadBeans!=null&&homeNewsBeans!=null){ 131 | home_listview.setVisibility(View.VISIBLE); 132 | home_framelayout.setVisibility(View.GONE); 133 | loading.setVisibility(View.GONE); 134 | empty.setVisibility(View.GONE); 135 | error.setVisibility(View.GONE); 136 | bindData(); 137 | }else{ 138 | home_listview.setVisibility(View.GONE); 139 | home_framelayout.setVisibility(View.VISIBLE); 140 | loading.setVisibility(View.GONE); 141 | empty.setVisibility(View.VISIBLE); 142 | error.setVisibility(View.GONE); 143 | } 144 | } 145 | }); 146 | 147 | } 148 | 149 | @Override 150 | public void initListener() { 151 | 152 | } 153 | 154 | @Override 155 | public void bindData() { 156 | int topSize=adHeadBeans.size(); 157 | //设置指示器 158 | headline_circle_indicator.setCount(topSize); 159 | headline_circle_indicator.setSeletion(circleSelectedPosition); 160 | //设置画廊Gallery 161 | headline_image_gallery.setLength(topSize); 162 | gallerySelectedPositon=topSize*50+circleSelectedPosition; 163 | headline_image_gallery.setSelection(gallerySelectedPositon); 164 | headline_image_gallery.setDelayMillis(4000); 165 | headline_image_gallery.start(); 166 | headline_image_gallery.setAdapter(new GalleryAdapter()); 167 | headline_image_gallery.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 168 | @Override 169 | public void onItemSelected(AdapterView parent, View view, int position, long id) { 170 | circleSelectedPosition=position; 171 | gallerySelectedPositon=circleSelectedPosition%adHeadBeans.size(); 172 | headline_circle_indicator.setSeletion(gallerySelectedPositon); 173 | } 174 | 175 | @Override 176 | public void onNothingSelected(AdapterView parent) { 177 | 178 | } 179 | }); 180 | quickAdapter=new QuickAdapter(getActivity(),R.layout.item_home_news_layout,homeNewsBeans) { 181 | @Override 182 | protected void convert(BaseAdapterHelper helper, HomeNewsBean item) { 183 | String mask=item.getMask(); 184 | helper.setText(R.id.item_news_tv_name,item.getAuthorBean().getName()) 185 | .setText(R.id.item_news_tv_time,item.getDatetext()) 186 | .setText(R.id.item_news_tv_type,mask) 187 | .setText(R.id.item_news_tv_title,item.getTitle()) 188 | .setImageUrl(R.id.item_news_tv_img,item.getImgurl()) 189 | .setImageUrl(R.id.item_news_img_icon,item.getAuthorBean().getAvatar()); 190 | int index=0; 191 | for(int i=0;i菜鸟窝 26 | * Description: 27 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 28 | * 打造极致课程,是菜鸟窝不变的承诺 29 | */ 30 | public class MainInfoFragment extends BaseFragment implements DefineView,ViewPager.OnPageChangeListener{ 31 | private View mView; 32 | private TabLayout tab_layout; 33 | private ViewPager info_viewpager; 34 | private FixedPagerAdapter fixedPagerAdapter; 35 | private List fragments; 36 | private static List categoriesBeans= CategoryDataUtils.getCategoryBeans(); 37 | @Override 38 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 39 | if(mView==null){ 40 | mView=inflater.inflate(R.layout.main_info_fragment_layout,container,false); 41 | initView(); 42 | initValidata(); 43 | initListener(); 44 | bindData(); 45 | } 46 | return mView; 47 | } 48 | 49 | @Override 50 | public void initView() { 51 | tab_layout=(TabLayout)mView.findViewById(R.id.tab_layout); 52 | info_viewpager=(ViewPager)mView.findViewById(R.id.info_viewpager); 53 | } 54 | 55 | @Override 56 | public void initValidata() { 57 | fixedPagerAdapter=new FixedPagerAdapter(getChildFragmentManager()); 58 | fixedPagerAdapter.setCategoriesBeans(categoriesBeans); 59 | fragments=new ArrayList(); 60 | for(int i=0;i菜鸟窝 28 | * Description: 29 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 30 | * 打造极致课程,是菜鸟窝不变的承诺 31 | */ 32 | public class PageFragment extends BaseFragment implements DefineView{ 33 | private View mView; 34 | private static final String KEY="EXTRA"; 35 | private CategoriesBean categoriesBean; 36 | private TextView tv_page; 37 | public static PageFragment newInstance(CategoriesBean extra){ 38 | Bundle bundle=new Bundle(); 39 | bundle.putSerializable(KEY,extra); 40 | PageFragment fragment=new PageFragment(); 41 | fragment.setArguments(bundle); 42 | return fragment; 43 | } 44 | @Override 45 | public void onCreate(Bundle savedInstanceState) { 46 | super.onCreate(savedInstanceState); 47 | Bundle bundle=getArguments(); 48 | if(bundle!=null) { 49 | categoriesBean=(CategoriesBean)bundle.getSerializable(KEY); 50 | } 51 | } 52 | 53 | @Override 54 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 55 | if(mView==null){ 56 | mView=inflater.inflate(R.layout.page_fragment_layout,container,false); 57 | initView(); 58 | initValidata(); 59 | initListener(); 60 | bindData(); 61 | } 62 | return mView; 63 | } 64 | @Override 65 | public void initView() { 66 | tv_page=(TextView)mView.findViewById(R.id.tv_page); 67 | tv_page.setText(categoriesBean.getTitle()); 68 | } 69 | @Override 70 | public void initValidata() { 71 | } 72 | 73 | @Override 74 | public void initListener() { 75 | 76 | } 77 | 78 | @Override 79 | public void bindData() { 80 | 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/fragment/base/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.fragment.base; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.Fragment; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | /** 10 | * 当前类注释:Fragment基类,主要封装了一些Fragment的公共操作 11 | * ProjectName:App36Kr 12 | * Author:菜鸟窝 13 | * Description: 14 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 15 | * 打造极致课程,是菜鸟窝不变的承诺 16 | */ 17 | public class BaseFragment extends Fragment { 18 | @Override 19 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 20 | return super.onCreateView(inflater, container, savedInstanceState); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/ui/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.ui; 2 | import android.os.Bundle; 3 | import android.os.Handler; 4 | import android.os.Message; 5 | import android.view.View; 6 | import android.widget.Button; 7 | import android.widget.ImageView; 8 | import android.widget.ListView; 9 | import android.widget.TextView; 10 | 11 | import com.cniao5.app36kr_cnk.R; 12 | import com.cniao5.app36kr_cnk.adapter.LeftItemAdapter; 13 | import com.cniao5.app36kr_cnk.biz.HeadDataManager; 14 | import com.cniao5.app36kr_cnk.common.DefineView; 15 | import com.cniao5.app36kr_cnk.entity.AdHeadBean; 16 | import com.cniao5.app36kr_cnk.ui.base.BaseActivity; 17 | import com.cniao5.app36kr_cnk.widget.DragLayout; 18 | import com.nineoldandroids.view.ViewHelper; 19 | 20 | import org.jsoup.Jsoup; 21 | import org.jsoup.nodes.Document; 22 | 23 | import java.io.IOException; 24 | import java.util.List; 25 | 26 | /** 27 | * 当前类注释:主Activity类 28 | * ProjectName:App36Kr 29 | * Author:菜鸟窝 30 | * Description: 31 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 32 | * 打造极致课程,是菜鸟窝不变的承诺 33 | */ 34 | public class MainActivity extends BaseActivity implements DefineView{ 35 | public DragLayout getDrag_layout() { 36 | return drag_layout; 37 | } 38 | 39 | private DragLayout drag_layout; 40 | private ImageView top_bar_icon; 41 | private ListView lv_left_main; 42 | 43 | @Override 44 | protected void onCreate(Bundle savedInstanceState) { 45 | super.onCreate(savedInstanceState); 46 | setContentView(R.layout.activity_main); 47 | setStatusBar(); 48 | initView(); 49 | initValidata(); 50 | initListener(); 51 | bindData(); 52 | } 53 | public void initView() { 54 | drag_layout = (DragLayout) findViewById(R.id.drag_layout); 55 | top_bar_icon = (ImageView) findViewById(R.id.top_bar_icon); 56 | lv_left_main=(ListView)findViewById(R.id.lv_left_main); 57 | } 58 | @Override 59 | public void initValidata() { 60 | lv_left_main.setAdapter(new LeftItemAdapter()); 61 | } 62 | @Override 63 | public void initListener() { 64 | drag_layout.setDragListener(new CustomDragListener()); 65 | top_bar_icon.setOnClickListener(new CustomOnClickListener()); 66 | 67 | } 68 | @Override 69 | public void bindData() { 70 | 71 | } 72 | class CustomDragListener implements DragLayout.DragListener{ 73 | 74 | /** 75 | * 界面打开 76 | */ 77 | @Override 78 | public void onOpen() { 79 | 80 | } 81 | 82 | /** 83 | * 界面关闭 84 | */ 85 | @Override 86 | public void onClose() { 87 | 88 | } 89 | 90 | /** 91 | * 界面进行滑动 92 | * @param percent 93 | */ 94 | @Override 95 | public void onDrag(float percent) { 96 | ViewHelper.setAlpha(top_bar_icon,1-percent); 97 | } 98 | } 99 | class CustomOnClickListener implements View.OnClickListener{ 100 | @Override 101 | public void onClick(View arg0) { 102 | drag_layout.open(); 103 | } 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/ui/WelcomeActivity.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.ui; 2 | 3 | import android.content.Context; 4 | import android.content.pm.PackageInfo; 5 | import android.content.pm.PackageManager; 6 | import android.media.MediaPlayer; 7 | import android.net.Uri; 8 | import android.os.Bundle; 9 | import android.text.TextUtils; 10 | import android.view.View; 11 | import android.widget.Button; 12 | 13 | import com.cniao5.app36kr_cnk.R; 14 | import com.cniao5.app36kr_cnk.ui.base.BaseActivity; 15 | import com.cniao5.app36kr_cnk.widget.CustomVideoView; 16 | 17 | /** 18 | * 当前类注释:启动欢迎界面 19 | * ProjectName:App36Kr 20 | * Author:菜鸟窝 21 | * Description: 22 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 23 | * 打造极致课程,是菜鸟窝不变的承诺 24 | */ 25 | public class WelcomeActivity extends BaseActivity { 26 | private Button welcome_button; 27 | private CustomVideoView welcome_videoview; 28 | @Override 29 | protected void onCreate(Bundle savedInstanceState) { 30 | super.onCreate(savedInstanceState); 31 | setContentView(R.layout.welcome_layout); 32 | welcome_button=(Button)this.findViewById(R.id.welcome_button); 33 | welcome_videoview = (CustomVideoView) this.findViewById(R.id.welcome_videoview); 34 | welcome_videoview.setVideoURI(Uri.parse("android.resource://"+this.getPackageName()+"/"+R.raw.kr36)); 35 | welcome_videoview.start(); 36 | welcome_videoview.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 37 | @Override 38 | public void onCompletion(MediaPlayer mp) { 39 | welcome_videoview.start(); 40 | 41 | } 42 | }); 43 | welcome_button.setOnClickListener(new View.OnClickListener() { 44 | @Override 45 | public void onClick(View v) { 46 | if(welcome_videoview.isPlaying()){ 47 | welcome_videoview.stopPlayback(); 48 | welcome_videoview=null; 49 | } 50 | openActivity(MainActivity.class); 51 | WelcomeActivity.this.finish(); 52 | } 53 | }); 54 | } 55 | 56 | private String getAppVersionName(Context context) { 57 | String versionName = ""; 58 | try { 59 | PackageManager packageManager = context.getPackageManager(); 60 | PackageInfo packageInfo = packageManager.getPackageInfo(this.getPackageName(), 0); 61 | versionName = packageInfo.versionName; 62 | if (TextUtils.isEmpty(versionName)) { 63 | return ""; 64 | } 65 | } catch (Exception e) { 66 | e.printStackTrace(); 67 | } 68 | return versionName; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/ui/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.ui.base; 2 | import android.content.Intent; 3 | import android.os.Build; 4 | import android.os.Bundle; 5 | import android.support.v4.app.FragmentActivity; 6 | import android.view.ViewGroup; 7 | import android.view.Window; 8 | import android.view.WindowManager; 9 | 10 | import com.cniao5.app36kr_cnk.R; 11 | 12 | import java.lang.reflect.Field; 13 | 14 | /** 15 | * 当前类注释:基类Activity 继承自FragmentActivity 16 | * ProjectName:App36Kr 17 | * Author:菜鸟窝 18 | * Description: 19 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 20 | * 打造极致课程,是菜鸟窝不变的承诺 21 | */ 22 | public class BaseActivity extends FragmentActivity{ 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | this.requestWindowFeature(Window.FEATURE_NO_TITLE); 27 | //当系统版本为4.4或者4.4以上时可以使用沉浸式状态栏 28 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 29 | //透明状态栏 30 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 31 | //透明导航栏 32 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 33 | } 34 | } 35 | protected void openActivity(Class pClass){ 36 | Intent mIntent=new Intent(this,pClass); 37 | this.startActivity(mIntent); 38 | } 39 | 40 | /** 41 | * 设置沉浸式状态栏 42 | */ 43 | protected void setStatusBar() { 44 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 45 | final ViewGroup linear_bar = (ViewGroup) findViewById(R.id.bar_layout); 46 | final int statusHeight = getStatusBarHeight(); 47 | linear_bar.post(new Runnable() { 48 | @Override 49 | public void run() { 50 | int titleHeight = linear_bar.getHeight(); 51 | android.widget.LinearLayout.LayoutParams params = (android.widget.LinearLayout.LayoutParams) linear_bar.getLayoutParams(); 52 | params.height = statusHeight + titleHeight; 53 | linear_bar.setLayoutParams(params); 54 | } 55 | }); 56 | } 57 | } 58 | /** 59 | * 获取状态栏的高度 60 | * @return 61 | */ 62 | protected int getStatusBarHeight(){ 63 | try 64 | { 65 | Class c=Class.forName("com.android.internal.R$dimen"); 66 | Object obj=c.newInstance(); 67 | Field field=c.getField("status_bar_height"); 68 | int x=Integer.parseInt(field.get(obj).toString()); 69 | return getResources().getDimensionPixelSize(x); 70 | }catch(Exception e){ 71 | e.printStackTrace(); 72 | } 73 | return 0; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/utils/CTextUtils.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.utils; 2 | 3 | /** 4 | * 文本字符串相关处理工具类 5 | * @author jiangqq 6 | * 7 | */ 8 | public class CTextUtils { 9 | /** 10 | * 提取文章编号 例如:/p/5040196.html 转成5040196 11 | * @param pStr 12 | * @return 13 | */ 14 | public static String getTitleId(String pStr){ 15 | if(pStr.contains(".")){ 16 | String[] temp=pStr.split("\\."); // /p/5040196 17 | int index =temp[0].lastIndexOf("/"); 18 | return temp[0].substring(index+1); 19 | } 20 | return pStr; 21 | } 22 | /** 23 | * http://36kr.com/p/5040401.html-->5040401 24 | * @param pStr 25 | * @return 26 | */ 27 | public static String getArticleId(String pStr){ 28 | String tempStr=pStr.substring(pStr.lastIndexOf("/")+1); 29 | if(tempStr.contains(".")){ 30 | String[] temp=tempStr.split("\\."); // 5040196 31 | return temp[0]; 32 | } 33 | return pStr; 34 | } 35 | 36 | public static String replaceSSymbol(String pStr){ 37 | return pStr.replace("\\n", ""); 38 | } 39 | 40 | /** 41 | * 进行邮箱的#号转换成@符号 42 | * @param pStr 43 | * @return 44 | */ 45 | public static String replaceEmail(String pStr){ 46 | if(pStr.contains("#")){ 47 | return pStr.replace("#", "@"); 48 | } 49 | return pStr; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/utils/CategoryDataUtils.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.utils; 2 | 3 | import com.cniao5.app36kr_cnk.entity.CategoriesBean; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * 当前类注释: 10 | * ProjectName:App36Kr_CNK 11 | * Author:菜鸟窝 12 | * Description: 13 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 14 | * 打造极致课程,是菜鸟窝不变的承诺 15 | */ 16 | public class CategoryDataUtils { 17 | public static List getCategoryBeans(){ 18 | List beans=new ArrayList<>(); 19 | beans.add(new CategoriesBean("全部","http://www.36kr.com/","全部")); 20 | beans.add(new CategoriesBean("氪TV","http://www.36kr.com/columns/tv","tv")); 21 | beans.add(new CategoriesBean("O2O","http://www.36kr.com/columns/o2o","o2o")); 22 | beans.add(new CategoriesBean("新硬件","http://www.36kr.com/columns/hardware","hardware")); 23 | beans.add(new CategoriesBean("Fun!!","http://www.36kr.com/columns/fun","fun")); 24 | beans.add(new CategoriesBean("企业服务","http://www.36kr.com/columns/enterprise","enterprise")); 25 | beans.add(new CategoriesBean("Fit&Health","http://www.36kr.com/columns/sports","sports")); 26 | beans.add(new CategoriesBean("在线教育","http://www.36kr.com/columns/edu","edu")); 27 | beans.add(new CategoriesBean("互联网金融","http://www.36kr.com/columns/finance","finance")); 28 | beans.add(new CategoriesBean("大公司","http://www.36kr.com/columns/company","company")); 29 | beans.add(new CategoriesBean("专栏","http://www.36kr.com/columns/column","column")); 30 | return beans; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/utils/HttpRequest.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.utils; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.io.PrintWriter; 7 | import java.net.URL; 8 | import java.net.URLConnection; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | public class HttpRequest { 13 | /** 14 | * 向指定URL发送GET方法的请求 15 | * 16 | * @param url 17 | * 发送请求的URL 18 | * @param param 19 | * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 20 | * @return URL 所代表远程资源的响应结果 21 | */ 22 | public static String sendGet(String url, String param) { 23 | String result = ""; 24 | BufferedReader in = null; 25 | try { 26 | String urlNameString = url + "?" + param; 27 | URL realUrl = new URL(urlNameString); 28 | // 打开和URL之间的连接 29 | URLConnection connection = realUrl.openConnection(); 30 | // 设置通用的请求属性 31 | connection.setRequestProperty("accept", "*/*"); 32 | connection.setRequestProperty("connection", "Keep-Alive"); 33 | connection.setRequestProperty("user-agent", 34 | "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); 35 | // 建立实际的连接 36 | connection.connect(); 37 | // 获取所有响应头字段 38 | Map> map = connection.getHeaderFields(); 39 | // 遍历所有的响应头字段 40 | for (String key : map.keySet()) { 41 | System.out.println(key + "--->" + map.get(key)); 42 | } 43 | // 定义 BufferedReader输入流来读取URL的响应 44 | in = new BufferedReader(new InputStreamReader( 45 | connection.getInputStream())); 46 | String line; 47 | while ((line = in.readLine()) != null) { 48 | result += line; 49 | } 50 | } catch (Exception e) { 51 | System.out.println("发送GET请求出现异常!" + e); 52 | e.printStackTrace(); 53 | } 54 | // 使用finally块来关闭输入流 55 | finally { 56 | try { 57 | if (in != null) { 58 | in.close(); 59 | } 60 | } catch (Exception e2) { 61 | e2.printStackTrace(); 62 | } 63 | } 64 | return result; 65 | } 66 | 67 | /** 68 | * 向指定 URL 发送POST方法的请求 69 | * 70 | * @param url 71 | * 发送请求的 URL 72 | * @param param 73 | * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 74 | * @return 所代表远程资源的响应结果 75 | */ 76 | public static String sendPost(String url, String param) { 77 | PrintWriter out = null; 78 | BufferedReader in = null; 79 | String result = ""; 80 | try { 81 | URL realUrl = new URL(url); 82 | // 打开和URL之间的连接 83 | URLConnection conn = realUrl.openConnection(); 84 | // 设置通用的请求属性 85 | conn.setRequestProperty("accept", "*/*"); 86 | conn.setRequestProperty("connection", "Keep-Alive"); 87 | conn.setRequestProperty("user-agent", 88 | "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); 89 | // 发送POST请求必须设置如下两行 90 | conn.setDoOutput(true); 91 | conn.setDoInput(true); 92 | // 获取URLConnection对象对应的输出流 93 | out = new PrintWriter(conn.getOutputStream()); 94 | // 发送请求参数 95 | out.print(param); 96 | // flush输出流的缓冲 97 | out.flush(); 98 | // 定义BufferedReader输入流来读取URL的响应 99 | in = new BufferedReader( 100 | new InputStreamReader(conn.getInputStream())); 101 | String line; 102 | while ((line = in.readLine()) != null) { 103 | result += line; 104 | } 105 | } catch (Exception e) { 106 | System.out.println("发送 POST 请求出现异常!"+e); 107 | e.printStackTrace(); 108 | } 109 | //使用finally块来关闭输出流、输入流 110 | finally{ 111 | try{ 112 | if(out!=null){ 113 | out.close(); 114 | } 115 | if(in!=null){ 116 | in.close(); 117 | } 118 | } 119 | catch(IOException ex){ 120 | ex.printStackTrace(); 121 | } 122 | } 123 | return result; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/utils/ImageUtils.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.utils; 2 | 3 | public class ImageUtils { 4 | /** 5 | * 进行图片地址截断 这边按照!号分隔 6 | * @param pUrl 7 | * @return 8 | */ 9 | public static String getCutImageUrl(String pUrl){ 10 | if(pUrl.contains("!")){ 11 | String[] urlsStrings=pUrl.split("!"); 12 | return urlsStrings[0]; 13 | } 14 | return pUrl; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/utils/MenuDataUtils.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.utils; 2 | 3 | 4 | import com.cniao5.app36kr_cnk.R; 5 | import com.cniao5.app36kr_cnk.entity.LeftItemMenu; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * 当前类注释:左侧菜单Item数据构造 12 | * ProjectName:App36Kr 13 | * Author:菜鸟窝 14 | * Description: 15 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 16 | * 打造极致课程,是菜鸟窝不变的承诺 17 | */ 18 | public class MenuDataUtils { 19 | public static List getItemMenus(){ 20 | List menus=new ArrayList(); 21 | menus.add(new LeftItemMenu(R.drawable.icon_zhanghaoxinxi,"账号信息")); 22 | menus.add(new LeftItemMenu(R.drawable.icon_wodeguanzhu,"我的关注")); 23 | menus.add(new LeftItemMenu(R.drawable.icon_shoucang,"我的收藏")); 24 | menus.add(new LeftItemMenu(R.drawable.icon_yijianfankui,"意见反馈")); 25 | menus.add(new LeftItemMenu(R.drawable.icon_shezhi,"设置")); 26 | return menus; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/utils/OkhttpManager.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.utils; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | import android.util.Log; 6 | 7 | import com.squareup.okhttp.Call; 8 | import com.squareup.okhttp.Callback; 9 | import com.squareup.okhttp.FormEncodingBuilder; 10 | import com.squareup.okhttp.OkHttpClient; 11 | import com.squareup.okhttp.Request; 12 | import com.squareup.okhttp.RequestBody; 13 | import com.squareup.okhttp.Response; 14 | 15 | import java.io.File; 16 | import java.io.FileOutputStream; 17 | import java.io.IOException; 18 | import java.io.InputStream; 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | /** 23 | * 当前类注释:OKHttpManager_Test 工具类封装 24 | * ProjectName:OkhttpTest 25 | * Author:菜鸟窝 26 | * Description: 27 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 28 | * 打造极致课程,是菜鸟窝不变的承诺 29 | */ 30 | public class OkhttpManager { 31 | private static final String FILE_PREFIX="CNIAO5_"; 32 | //OKhttp对象实例 33 | private OkHttpClient client; 34 | private static OkhttpManager okhttpManager; 35 | private Handler handler; 36 | 37 | private static OkhttpManager getInstance(){ 38 | if(okhttpManager==null){ 39 | okhttpManager=new OkhttpManager(); 40 | } 41 | return okhttpManager; 42 | } 43 | private OkhttpManager(){ 44 | client=new OkHttpClient(); 45 | handler=new Handler(Looper.getMainLooper()); 46 | } 47 | /** 48 | * 同步Get请求方法 49 | * @param url 50 | * @return 51 | * @throws IOException 52 | */ 53 | private Response p_getSync(String url)throws IOException{ 54 | final Request request = new Request.Builder() 55 | .url(url) 56 | .build(); 57 | Call call = client.newCall(request); 58 | Response response = call.execute(); 59 | return response; 60 | } 61 | 62 | /** 63 | * 进行发送同步GET请求,并且返回String类型数据 64 | * @param url 65 | * @return 66 | * @throws IOException 67 | */ 68 | private String p_getSyncAsString(String url)throws IOException{ 69 | Response response=p_getSync(url); 70 | return response.body().string(); 71 | } 72 | 73 | /** 74 | * 进行GET异步请求 75 | * @param url 76 | * @param callBack 77 | */ 78 | private void p_getAsync(String url, final DataCallBack callBack){ 79 | final Request request=new Request.Builder().url(url).build(); 80 | client.newCall(request).enqueue(new Callback() { 81 | @Override 82 | public void onFailure(Request request, IOException e) { 83 | deliverFailure(request, e, callBack); 84 | } 85 | /** 86 | * 异步返回数据 87 | * @param response 88 | * @throws IOException 89 | */ 90 | @Override 91 | public void onResponse(Response response) throws IOException { 92 | try { 93 | deliverSuccess(response.body().string(), callBack); 94 | }catch (IOException e){ 95 | deliverFailure(request,e,callBack); 96 | } 97 | } 98 | }); 99 | } 100 | /** 101 | * 102 | * @param url 103 | * @param params 104 | * @param callBack 105 | */ 106 | private void p_postAsyncParams(String url,Map params,final DataCallBack callBack){ 107 | RequestBody requestBody=null; 108 | if(params==null){ 109 | params=new HashMap(); 110 | } 111 | FormEncodingBuilder builder=new FormEncodingBuilder(); 112 | for (Map.Entry entry:params.entrySet()) { 113 | String key=entry.getKey().toString(); 114 | String value=null; 115 | if(entry.getValue()==null){ 116 | value=""; 117 | }else { 118 | value=entry.getValue(); 119 | } 120 | builder.add(key,value); 121 | } 122 | requestBody=builder.build(); 123 | final Request request=new Request.Builder().url(url).post(requestBody).build(); 124 | client.newCall(request).enqueue(new Callback() { 125 | @Override 126 | public void onFailure(Request request, IOException e) { 127 | deliverFailure(request, e, callBack); 128 | } 129 | 130 | @Override 131 | public void onResponse(Response response) throws IOException { 132 | try { 133 | deliverSuccess(response.body().string(), callBack); 134 | }catch (IOException e){ 135 | deliverFailure(request,e,callBack); 136 | } 137 | } 138 | }); 139 | } 140 | /** 141 | * 进行异步下载文件 142 | * @param url 文件的地址 143 | * @param destDir 文件存储的绝对路径 144 | * @param callBack 145 | */ 146 | private void p_downloadAsync(final String url, final String destDir,final DataCallBack callBack){ 147 | final Request request=new Request.Builder().url(url).build(); 148 | client.newCall(request).enqueue(new Callback() { 149 | @Override 150 | public void onFailure(Request request, IOException e) { 151 | deliverFailure(request,e,callBack); 152 | } 153 | @Override 154 | public void onResponse(Response response) throws IOException { 155 | //开始进行写入文件 156 | InputStream inputStream=null; 157 | FileOutputStream fileOutputStream=null; 158 | try { 159 | inputStream=response.body().byteStream(); 160 | byte[] buffer=new byte[2048]; 161 | int len=0; 162 | File file= new File(destDir,getFileName(url)); 163 | fileOutputStream=new FileOutputStream(file); 164 | while((len=inputStream.read(buffer))!=-1){ 165 | fileOutputStream.write(buffer,0,len); 166 | } 167 | fileOutputStream.flush(); 168 | deliverSuccess(file.getAbsolutePath(),callBack); 169 | }catch (IOException e) 170 | { 171 | deliverFailure(request,e,callBack); 172 | }finally { 173 | if(fileOutputStream!=null){ 174 | fileOutputStream.close(); 175 | } 176 | if(inputStream!=null){ 177 | inputStream.close();; 178 | } 179 | } 180 | } 181 | }); 182 | } 183 | 184 | /** 185 | * 根据文件URL地址获取文件的路径文件名 186 | * @param pUrl 187 | * @return 188 | */ 189 | private String getFileName(String pUrl){ 190 | int separatorIndex = pUrl.lastIndexOf("/"); 191 | String path=(separatorIndex < 0) ? pUrl : pUrl.substring(separatorIndex + 1, pUrl.length()); 192 | return FILE_PREFIX+path; 193 | } 194 | //*************************数据请求成功或者失败分发方法********************** 195 | /** 196 | * 进行分发请求失败的数据情况 197 | * @param request 198 | * @param e 199 | * @param callBack 200 | */ 201 | private void deliverFailure(final Request request,final IOException e, final DataCallBack callBack){ 202 | handler.post(new Runnable() { 203 | @Override 204 | public void run() { 205 | if (callBack != null) { 206 | callBack.requestFailure(request, e); 207 | } 208 | } 209 | }); 210 | } 211 | 212 | /** 213 | * 请求分发请求成功的数据情况 214 | * @param result 215 | * @param callBack 216 | */ 217 | private void deliverSuccess(final String result, final DataCallBack callBack){ 218 | handler.post(new Runnable() { 219 | @Override 220 | public void run() { 221 | if (callBack != null) { 222 | callBack.requestSuccess(result); 223 | } 224 | } 225 | }); 226 | } 227 | 228 | //*************对外公布的方法******************** 229 | 230 | /** 231 | * 根据请求地址,进行发起GET同步请求,并且返回Response信息 232 | * @param url 233 | * @return 234 | * @throws IOException 235 | */ 236 | public static Response getSync(String url) throws IOException{ 237 | return getInstance().p_getSync(url); 238 | } 239 | 240 | /** 241 | * 根据请求地址,进行发起GET同步请求,并且返回String信息 242 | * @param url 243 | * @return 244 | * @throws IOException 245 | */ 246 | public static String getSyncAsString(String url)throws IOException{ 247 | return getInstance().p_getSyncAsString(url); 248 | } 249 | 250 | /** 251 | * 进行GET异步请求数据 252 | * @param url 253 | * @param callBack 254 | */ 255 | public static void getAsync(String url,DataCallBack callBack){ 256 | getInstance().p_getAsync(url, callBack); 257 | } 258 | 259 | /** 260 | * 进行POST异步请求数据 261 | * @param url 262 | * @param params 需要POST的数据 263 | * @param callBack 264 | */ 265 | public static void postAsyncParams(String url,Map params,DataCallBack callBack){ 266 | getInstance().p_postAsyncParams(url, params, callBack); 267 | } 268 | 269 | /** 270 | * 进行异步下载文件 271 | * @param url 文件地址 272 | * @param destDir 存入本地的路径 273 | * @param callBack 下载成功回调 274 | */ 275 | public static void downloadAsync(String url,String destDir,DataCallBack callBack){ 276 | getInstance().p_downloadAsync(url,destDir,callBack); 277 | } 278 | 279 | //*************数据回调接口************************ 280 | public interface DataCallBack{ 281 | /** 282 | * 请求失败 283 | * @param request 284 | */ 285 | void requestFailure(Request request, Exception e); 286 | 287 | /** 288 | * 请求成功 289 | * @param result 290 | */ 291 | void requestSuccess(String result); 292 | } 293 | } 294 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/widget/CustomRelativeLayout.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.widget; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.MotionEvent; 6 | import android.widget.RelativeLayout; 7 | 8 | 9 | public class CustomRelativeLayout extends RelativeLayout { 10 | private DragLayout dl; 11 | 12 | public CustomRelativeLayout(Context context) { 13 | super(context); 14 | } 15 | 16 | public CustomRelativeLayout(Context context, AttributeSet attrs) { 17 | super(context, attrs); 18 | } 19 | 20 | public CustomRelativeLayout(Context context, AttributeSet attrs, int defStyle) { 21 | super(context, attrs, defStyle); 22 | } 23 | 24 | public void setDragLayout(DragLayout dl) { 25 | this.dl = dl; 26 | } 27 | 28 | @Override 29 | public boolean onInterceptTouchEvent(MotionEvent event) { 30 | if (dl.getStatus() != DragLayout.Status.Close) { 31 | return true; 32 | } 33 | return super.onInterceptTouchEvent(event); 34 | } 35 | 36 | @Override 37 | public boolean onTouchEvent(MotionEvent event) { 38 | if (dl.getStatus() != DragLayout.Status.Close) { 39 | if (event.getAction() == MotionEvent.ACTION_UP) { 40 | dl.close(); 41 | } 42 | return true; 43 | } 44 | return super.onTouchEvent(event); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/widget/CustomVideoView.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.widget; 2 | 3 | import android.content.Context; 4 | import android.media.MediaPlayer; 5 | import android.util.AttributeSet; 6 | import android.view.KeyEvent; 7 | import android.widget.VideoView; 8 | 9 | /** 10 | * 当前类注释:自定义VideoView 实现全屏播放 11 | * ProjectName:App36Kr 12 | * Author:菜鸟窝 13 | * Description: 14 | * 菜鸟窝是一个只专注做Android开发技能的在线学习平台,课程以实战项目为主,对课程与服务”吹毛求疵”般的要求, 15 | * 打造极致课程,是菜鸟窝不变的承诺 16 | */ 17 | public class CustomVideoView extends VideoView { 18 | public CustomVideoView(Context context) { 19 | super(context); 20 | } 21 | public CustomVideoView(Context context, AttributeSet attrs) { 22 | super(context, attrs); 23 | } 24 | public CustomVideoView(Context context, AttributeSet attrs, int defStyle) { 25 | super(context, attrs, defStyle); 26 | } 27 | @Override 28 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 29 | //重点。 30 | int width = getDefaultSize(0, widthMeasureSpec); 31 | int height = getDefaultSize(0, heightMeasureSpec); 32 | setMeasuredDimension(width, height); 33 | } 34 | @Override 35 | public void setOnPreparedListener(MediaPlayer.OnPreparedListener l) { 36 | super.setOnPreparedListener(l); 37 | } 38 | @Override 39 | public boolean onKeyDown(int keyCode, KeyEvent event) { 40 | return super.onKeyDown(keyCode, event); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/cniao5/app36kr_cnk/widget/RoundAngleImageView.java: -------------------------------------------------------------------------------- 1 | package com.cniao5.app36kr_cnk.widget; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Bitmap; 6 | import android.graphics.Bitmap.Config; 7 | import android.graphics.Canvas; 8 | import android.graphics.Color; 9 | import android.graphics.Paint; 10 | import android.graphics.Path; 11 | import android.graphics.PorterDuff; 12 | import android.graphics.PorterDuffXfermode; 13 | import android.graphics.RectF; 14 | import android.util.AttributeSet; 15 | import android.widget.ImageView; 16 | 17 | import com.cniao5.app36kr_cnk.R; 18 | 19 | public class RoundAngleImageView extends ImageView { 20 | private Paint paint; 21 | private int roundWidth = 5; 22 | private int roundHeight = 5; 23 | private Paint paint2; 24 | 25 | public RoundAngleImageView(Context context, AttributeSet attrs, int defStyle) { 26 | super(context, attrs, defStyle); 27 | init(context, attrs); 28 | } 29 | 30 | public RoundAngleImageView(Context context, AttributeSet attrs) { 31 | super(context, attrs); 32 | init(context, attrs); 33 | } 34 | 35 | public RoundAngleImageView(Context context) { 36 | super(context); 37 | init(context, null); 38 | } 39 | 40 | private void init(Context context, AttributeSet attrs) { 41 | 42 | if(attrs != null) { 43 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundAngleImageView); 44 | roundWidth= a.getDimensionPixelSize(R.styleable.RoundAngleImageView_roundWidth, roundWidth); 45 | roundHeight= a.getDimensionPixelSize(R.styleable.RoundAngleImageView_roundHeight, roundHeight); 46 | }else { 47 | float density = context.getResources().getDisplayMetrics().density; 48 | roundWidth = (int) (roundWidth*density); 49 | roundHeight = (int) (roundHeight*density); 50 | } 51 | 52 | paint = new Paint(); 53 | paint.setColor(Color.WHITE); 54 | paint.setAntiAlias(true); 55 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 56 | 57 | paint2 = new Paint(); 58 | paint2.setXfermode(null); 59 | } 60 | 61 | @Override 62 | public void draw(Canvas canvas) { 63 | Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888); 64 | Canvas canvas2 = new Canvas(bitmap); 65 | super.draw(canvas2); 66 | drawLiftUp(canvas2); 67 | drawRightUp(canvas2); 68 | drawLiftDown(canvas2); 69 | drawRightDown(canvas2); 70 | canvas.drawBitmap(bitmap, 0, 0, paint2); 71 | bitmap.recycle(); 72 | } 73 | 74 | private void drawLiftUp(Canvas canvas) { 75 | Path path = new Path(); 76 | path.moveTo(0, roundHeight); 77 | path.lineTo(0, 0); 78 | path.lineTo(roundWidth, 0); 79 | path.arcTo(new RectF( 80 | 0, 81 | 0, 82 | roundWidth*2, 83 | roundHeight*2), 84 | -90, 85 | -90); 86 | path.close(); 87 | canvas.drawPath(path, paint); 88 | } 89 | 90 | private void drawLiftDown(Canvas canvas) { 91 | Path path = new Path(); 92 | path.moveTo(0, getHeight()-roundHeight); 93 | path.lineTo(0, getHeight()); 94 | path.lineTo(roundWidth, getHeight()); 95 | path.arcTo(new RectF( 96 | 0, 97 | getHeight()-roundHeight*2, 98 | 0+roundWidth*2, 99 | getHeight()), 100 | 90, 101 | 90); 102 | path.close(); 103 | canvas.drawPath(path, paint); 104 | } 105 | 106 | private void drawRightDown(Canvas canvas) { 107 | Path path = new Path(); 108 | path.moveTo(getWidth()-roundWidth, getHeight()); 109 | path.lineTo(getWidth(), getHeight()); 110 | path.lineTo(getWidth(), getHeight()-roundHeight); 111 | path.arcTo(new RectF( 112 | getWidth()-roundWidth*2, 113 | getHeight()-roundHeight*2, 114 | getWidth(), 115 | getHeight()), 0, 90); 116 | path.close(); 117 | canvas.drawPath(path, paint); 118 | } 119 | 120 | private void drawRightUp(Canvas canvas) { 121 | Path path = new Path(); 122 | path.moveTo(getWidth(), roundHeight); 123 | path.lineTo(getWidth(), 0); 124 | path.lineTo(getWidth()-roundWidth, 0); 125 | path.arcTo(new RectF( 126 | getWidth()-roundWidth*2, 127 | 0, 128 | getWidth(), 129 | 0+roundHeight*2), 130 | -90, 131 | 90); 132 | path.close(); 133 | canvas.drawPath(path, paint); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/bottom_line_blue.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/src/main/res/drawable-hdpi/bottom_line_blue.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/bottom_line_gray.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/src/main/res/drawable-hdpi/bottom_line_gray.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/defaultbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/src/main/res/drawable-hdpi/defaultbg.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/defaultbg_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/src/main/res/drawable-hdpi/defaultbg_h.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/head_bt_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/src/main/res/drawable-hdpi/head_bt_bg.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_data_loaded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/src/main/res/drawable-hdpi/ic_data_loaded.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/src/main/res/drawable-hdpi/icon_avatar.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_avatar_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/src/main/res/drawable-hdpi/icon_avatar_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/src/main/res/drawable-hdpi/icon_search.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_search_click.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/src/main/res/drawable-hdpi/icon_search_click.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_shezhi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/src/main/res/drawable-hdpi/icon_shezhi.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_shoucang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/src/main/res/drawable-hdpi/icon_shoucang.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_wodeguanzhu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/src/main/res/drawable-hdpi/icon_wodeguanzhu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_yijianfankui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/src/main/res/drawable-hdpi/icon_yijianfankui.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_zhanghaoxinxi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/src/main/res/drawable-hdpi/icon_zhanghaoxinxi.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/load_error_bak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yxs666/cniao5-news/b9d9ec83aa9869f99a77531a49ea2d15b462ebbf/app/src/main/res/drawable-hdpi/load_error_bak.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bigreddot.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_serach_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/reddot.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 15 | 20 | 21 | 22 | 23 | 27 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/empty.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 17 | 18 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/error.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 16 | 17 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/gallery_indicator_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 11 | 12 | 19 | 20 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/home_fragment_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 14 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_gallery_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_home_news_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 14 | 15 | 24 | 34 | 44 | 45 | 53 | 65 | 66 | 67 | 74 | 84 | 91 | 92 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_left_menu_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 15 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_text.xml: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/left_view_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 19 | 25 | 32 | 39 | 40 | 41 | 42 | 43 | 50 | 51 | -------------------------------------------------------------------------------- /app/src/main/res/layout/loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 15 | 16 | 22 | 27 | 28 | 29 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/layout/main_info_fragment_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 16 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/page_fragment_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/layout/top_bar_common_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 12 | 21 | 30 | 31 |