Repository: LRH1993/LiveCircle Branch: master Commit: 00da5281795f Files: 172 Total size: 385.8 KB Directory structure: gitextract_6rcgjzff/ ├── LiveCircle/ │ ├── .gitignore │ ├── .idea/ │ │ ├── compiler.xml │ │ ├── copyright/ │ │ │ └── profiles_settings.xml │ │ ├── encodings.xml │ │ ├── gradle.xml │ │ ├── inspectionProfiles/ │ │ │ ├── Project_Default.xml │ │ │ └── profiles_settings.xml │ │ ├── misc.xml │ │ ├── modules.xml │ │ └── runConfigurations.xml │ ├── app/ │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src/ │ │ ├── androidTest/ │ │ │ └── java/ │ │ │ └── com/ │ │ │ └── lvr/ │ │ │ └── livecircle/ │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main/ │ │ │ ├── AndroidManifest.xml │ │ │ ├── java/ │ │ │ │ └── com/ │ │ │ │ └── lvr/ │ │ │ │ └── livecircle/ │ │ │ │ ├── adapter/ │ │ │ │ │ ├── CardAdapter.java │ │ │ │ │ ├── HomeViewPagerAdapter.java │ │ │ │ │ ├── NewsChannelAdapter.java │ │ │ │ │ ├── NewsChannelGridAdapter.java │ │ │ │ │ ├── NewsListAdapter.java │ │ │ │ │ ├── OnNewsChannelListener.java │ │ │ │ │ └── PhotoListAdapter.java │ │ │ │ ├── api/ │ │ │ │ │ ├── ApiConstants.java │ │ │ │ │ ├── ApiService.java │ │ │ │ │ └── HostType.java │ │ │ │ ├── app/ │ │ │ │ │ ├── AppApplication.java │ │ │ │ │ ├── AppConstant.java │ │ │ │ │ └── AppManager.java │ │ │ │ ├── base/ │ │ │ │ │ ├── BaseActivity.java │ │ │ │ │ ├── BaseApplication.java │ │ │ │ │ ├── BaseFragment.java │ │ │ │ │ └── BaseFragmentAdapter.java │ │ │ │ ├── bean/ │ │ │ │ │ ├── ChannelBean.java │ │ │ │ │ ├── FabScrollBean.java │ │ │ │ │ ├── HeaderBean.java │ │ │ │ │ └── NewsInfo.java │ │ │ │ ├── client/ │ │ │ │ │ ├── BaseApiService.java │ │ │ │ │ ├── BaseInterceptor.java │ │ │ │ │ ├── BaseObserver.java │ │ │ │ │ ├── BaseResponse.java │ │ │ │ │ ├── CaheInterceptor.java │ │ │ │ │ ├── ExceptionHandle.java │ │ │ │ │ ├── IpResult.java │ │ │ │ │ ├── NetworkUtil.java │ │ │ │ │ ├── RetrofitClient.java │ │ │ │ │ └── RxDisposeManager.java │ │ │ │ ├── find/ │ │ │ │ │ └── FindFragment.java │ │ │ │ ├── home/ │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── SplashActivity.java │ │ │ │ ├── meitu/ │ │ │ │ │ ├── MeiTuFragment.java │ │ │ │ │ ├── model/ │ │ │ │ │ │ ├── PhotoModel.java │ │ │ │ │ │ ├── bean/ │ │ │ │ │ │ │ ├── GirlData.java │ │ │ │ │ │ │ └── PhotoGirl.java │ │ │ │ │ │ └── impl/ │ │ │ │ │ │ └── PhotoModelImpl.java │ │ │ │ │ ├── presenter/ │ │ │ │ │ │ ├── PhotoPresenter.java │ │ │ │ │ │ └── impl/ │ │ │ │ │ │ └── PhotoPresenterImpl.java │ │ │ │ │ └── view/ │ │ │ │ │ └── PhotoView.java │ │ │ │ ├── music/ │ │ │ │ │ └── MusicFragment.java │ │ │ │ ├── nearby/ │ │ │ │ │ └── NearByFragment.java │ │ │ │ ├── news/ │ │ │ │ │ ├── activity/ │ │ │ │ │ │ ├── NewsChannelActivity.java │ │ │ │ │ │ ├── NewsDetailActivity.java │ │ │ │ │ │ └── NewsPhotoDetailActivity.java │ │ │ │ │ ├── db/ │ │ │ │ │ │ └── NewsChannelTableManager.java │ │ │ │ │ ├── fragment/ │ │ │ │ │ │ └── NewsFragment.java │ │ │ │ │ ├── model/ │ │ │ │ │ │ ├── NewsChannelModel.java │ │ │ │ │ │ ├── NewsDetailModel.java │ │ │ │ │ │ ├── NewsModel.java │ │ │ │ │ │ ├── bean/ │ │ │ │ │ │ │ ├── NewsChannelTable.java │ │ │ │ │ │ │ ├── NewsDetail.java │ │ │ │ │ │ │ └── NewsPhotoDetail.java │ │ │ │ │ │ └── impl/ │ │ │ │ │ │ ├── NewsChannelModelImpl.java │ │ │ │ │ │ ├── NewsDetailModelImpl.java │ │ │ │ │ │ └── NewsModelImpl.java │ │ │ │ │ ├── presenter/ │ │ │ │ │ │ ├── NewPresenter.java │ │ │ │ │ │ ├── NewsChannelPresenter.java │ │ │ │ │ │ ├── NewsDetailPresenter.java │ │ │ │ │ │ └── impl/ │ │ │ │ │ │ ├── NewsChannelPresenterImpl.java │ │ │ │ │ │ ├── NewsDetailPresenterImpl.java │ │ │ │ │ │ └── NewsPresenterImpl.java │ │ │ │ │ └── view/ │ │ │ │ │ ├── NewsChannelView.java │ │ │ │ │ ├── NewsDetailView.java │ │ │ │ │ └── NewsView.java │ │ │ │ ├── recommend/ │ │ │ │ │ └── RecommendFragment.java │ │ │ │ ├── recycleviewcardgallery/ │ │ │ │ │ ├── CardAdapterHelper.java │ │ │ │ │ ├── CardLinearSnapHelper.java │ │ │ │ │ ├── CardScaleHelper.java │ │ │ │ │ └── SpeedRecyclerView.java │ │ │ │ ├── utils/ │ │ │ │ │ ├── ACache.java │ │ │ │ │ ├── CollectionUtils.java │ │ │ │ │ ├── DisplayUtil.java │ │ │ │ │ ├── GlideRoundTransformUtil.java │ │ │ │ │ ├── ImageLoaderUtils.java │ │ │ │ │ ├── StatusBarSetting.java │ │ │ │ │ ├── TUtil.java │ │ │ │ │ ├── TimeUtil.java │ │ │ │ │ └── ToastUitl.java │ │ │ │ ├── video/ │ │ │ │ │ └── VideoFragment.java │ │ │ │ └── widget/ │ │ │ │ ├── ClassicRefreshHeaderView.java │ │ │ │ ├── ItemDragHelperCallback.java │ │ │ │ ├── LoadMoreFooterView.java │ │ │ │ ├── LoadingDialog.java │ │ │ │ ├── LoadingTip.java │ │ │ │ ├── ScrollAwareFABBehavior.java │ │ │ │ ├── StatusBarView.java │ │ │ │ └── URLImageGetter.java │ │ │ └── res/ │ │ │ ├── anim/ │ │ │ │ ├── act_fade_in_center.xml │ │ │ │ ├── act_fade_out_center.xml │ │ │ │ ├── fade_in.xml │ │ │ │ ├── fade_out.xml │ │ │ │ ├── rotate_down.xml │ │ │ │ ├── rotate_up.xml │ │ │ │ ├── slide_in_left.xml │ │ │ │ ├── slide_in_right.xml │ │ │ │ ├── slide_out_left.xml │ │ │ │ └── slide_out_right.xml │ │ │ ├── drawable/ │ │ │ │ ├── loading_dialog_progressbar.xml │ │ │ │ ├── selector_gray.xml │ │ │ │ ├── shape_loading_dialog.xml │ │ │ │ └── tv_rounded_corners.xml │ │ │ ├── layout/ │ │ │ │ ├── activity_main.xml │ │ │ │ ├── activity_news_channel.xml │ │ │ │ ├── activity_news_detail.xml │ │ │ │ ├── activity_news_photo_detail.xml │ │ │ │ ├── activty_splash.xml │ │ │ │ ├── app_bar.xml │ │ │ │ ├── dialog_loading.xml │ │ │ │ ├── dialog_loading_tip.xml │ │ │ │ ├── fragment_find.xml │ │ │ │ ├── fragment_meitu.xml │ │ │ │ ├── fragment_music.xml │ │ │ │ ├── fragment_nearby.xml │ │ │ │ ├── fragment_news.xml │ │ │ │ ├── fragment_recommend.xml │ │ │ │ ├── fragment_video.xml │ │ │ │ ├── item_card_view.xml │ │ │ │ ├── item_channel_card.xml │ │ │ │ ├── item_content_news_detail.xml │ │ │ │ ├── item_foot_view.xml │ │ │ │ ├── item_grid_news_channel.xml │ │ │ │ ├── item_header_view.xml │ │ │ │ ├── item_news.xml │ │ │ │ ├── item_news_header.xml │ │ │ │ ├── item_news_photo.xml │ │ │ │ ├── item_photo_girl.xml │ │ │ │ ├── layout_irecyclerview_classic_refresh_header_view.xml │ │ │ │ ├── layout_irecyclerview_load_more_footer.xml │ │ │ │ ├── layout_irecyclerview_load_more_footer_error_view.xml │ │ │ │ ├── layout_irecyclerview_load_more_footer_loading_view.xml │ │ │ │ ├── layout_irecyclerview_load_more_footer_the_end_view.xml │ │ │ │ ├── layout_irecyclerview_load_more_footer_view.xml │ │ │ │ ├── layout_irecyclerview_refresh_header.xml │ │ │ │ ├── toast_custom.xml │ │ │ │ └── view_nav.xml │ │ │ ├── menu/ │ │ │ │ ├── menu_nav.xml │ │ │ │ └── menu_toolabr.xml │ │ │ ├── values/ │ │ │ │ ├── colors.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── ids.xml │ │ │ │ ├── news_channel_info.xml │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ ├── values-v19/ │ │ │ │ └── dimens.xml │ │ │ └── values-w820dp/ │ │ │ └── dimens.xml │ │ └── test/ │ │ └── java/ │ │ └── com/ │ │ └── lvr/ │ │ └── livecircle/ │ │ └── ExampleUnitTest.java │ ├── build.gradle │ ├── gradle/ │ │ └── wrapper/ │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradle.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle └── README.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: LiveCircle/.gitignore ================================================ *.iml .gradle /local.properties /.idea/workspace.xml /.idea/libraries .DS_Store /build /captures .externalNativeBuild ================================================ FILE: LiveCircle/.idea/compiler.xml ================================================ ================================================ FILE: LiveCircle/.idea/copyright/profiles_settings.xml ================================================ ================================================ FILE: LiveCircle/.idea/encodings.xml ================================================ ================================================ FILE: LiveCircle/.idea/gradle.xml ================================================ ================================================ FILE: LiveCircle/.idea/inspectionProfiles/Project_Default.xml ================================================ ================================================ FILE: LiveCircle/.idea/inspectionProfiles/profiles_settings.xml ================================================ ================================================ FILE: LiveCircle/.idea/misc.xml ================================================ 1.8 ================================================ FILE: LiveCircle/.idea/modules.xml ================================================ ================================================ FILE: LiveCircle/.idea/runConfigurations.xml ================================================ ================================================ FILE: LiveCircle/app/.gitignore ================================================ /build ================================================ FILE: LiveCircle/app/build.gradle ================================================ apply plugin: 'com.android.application' apply plugin: 'com.neenbedankt.android-apt' android { compileSdkVersion 25 buildToolsVersion "25.0.2" defaultConfig { applicationId "com.lvr.livecircle" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.1.0' testCompile 'junit:junit:4.12' compile 'com.android.support:design:25.1.0' //视图绑定 butterknife compile 'com.jakewharton:butterknife:8.4.0' apt 'com.jakewharton:butterknife-compiler:8.4.0' compile 'de.greenrobot:eventbus:3.0.0-beta1' //引入okhttp compile 'com.squareup.okhttp3:okhttp:3.5.0' //引入retrofit compile 'com.squareup.retrofit2:retrofit:2.1.0' //引入rxjava compile 'io.reactivex.rxjava2:rxjava:2.0.4' //引入Log拦截器,方便DEBUG模式输出log信息 compile 'com.squareup.okhttp3:logging-interceptor:3.5.0' //引入rxjava适配器,方便rxjava与retrofit的结合 compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' //引入json转换器,方便将返回的数据转换为json格式 compile 'com.squareup.retrofit2:converter-gson:2.1.0' //引入rxandroid compile 'io.reactivex.rxjava2:rxandroid:2.0.1' compile 'com.github.bumptech.glide:glide:3.7.0' compile 'com.android.support:cardview-v7:25.1.0' compile 'com.android.support:recyclerview-v7:25.1.0' compile 'com.github.Aspsine:IRecyclerView:0.0.5' } ================================================ FILE: LiveCircle/app/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in E:\AndroidStudio\SDKinstallpackage/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles # directive in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} ================================================ FILE: LiveCircle/app/src/androidTest/java/com/lvr/livecircle/ExampleInstrumentedTest.java ================================================ package com.lvr.livecircle; import android.content.Context; import android.support.test.InstrumentationRegistry; import android.support.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; import static org.junit.Assert.*; /** * Instrumentation test, which will execute on an Android device. * * @see Testing documentation */ @RunWith(AndroidJUnit4.class) public class ExampleInstrumentedTest { @Test public void useAppContext() throws Exception { // Context of the app under test. Context appContext = InstrumentationRegistry.getTargetContext(); assertEquals("com.lvr.livecircle", appContext.getPackageName()); } } ================================================ FILE: LiveCircle/app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/adapter/CardAdapter.java ================================================ package com.lvr.livecircle.adapter; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import com.lvr.livecircle.R; import com.lvr.livecircle.news.model.bean.NewsPhotoDetail; import com.lvr.livecircle.recycleviewcardgallery.CardAdapterHelper; import com.lvr.livecircle.utils.ImageLoaderUtils; import java.util.ArrayList; import java.util.List; /** * Created by lvr on 2017/2/6. */ public class CardAdapter extends RecyclerView.Adapter { private List mList = new ArrayList<>(); private CardAdapterHelper mCardAdapterHelper = new CardAdapterHelper(); private Context mContext; public CardAdapter(Context context,List mList) { this.mList = mList; this.mContext = context; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_card_view, parent, false); mCardAdapterHelper.onCreateViewHolder(parent, itemView); return new ViewHolder(itemView); } @Override public void onBindViewHolder(final ViewHolder holder, final int position) { mCardAdapterHelper.onBindViewHolder(holder.itemView, position, getItemCount()); ImageLoaderUtils.displayBigPhoto(mContext,holder.mImageView,mList.get(position).getImgSrc()); } @Override public int getItemCount() { return mList.size(); } public class ViewHolder extends RecyclerView.ViewHolder { public final ImageView mImageView; public ViewHolder(final View itemView) { super(itemView); mImageView = (ImageView) itemView.findViewById(R.id.imageView); } } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/adapter/HomeViewPagerAdapter.java ================================================ package com.lvr.livecircle.adapter; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import com.lvr.livecircle.base.BaseFragmentAdapter; import java.util.List; /** * Created by lvr on 2017/2/6. */ public class HomeViewPagerAdapter extends BaseFragmentAdapter { public HomeViewPagerAdapter(FragmentManager fm, List fragmentList, List mTitles) { super(fm, fragmentList, mTitles); } public HomeViewPagerAdapter(FragmentManager fm, List fragmentList) { super(fm, fragmentList); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/adapter/NewsChannelAdapter.java ================================================ package com.lvr.livecircle.adapter; import android.content.Context; import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import com.lvr.livecircle.R; import com.lvr.livecircle.bean.ChannelBean; import com.lvr.livecircle.news.model.bean.NewsChannelTable; import com.lvr.livecircle.widget.ItemDragHelperCallback; import java.util.Collections; import java.util.List; import de.greenrobot.event.EventBus; /** * Created by lvr on 2017/2/14. */ public class NewsChannelAdapter extends RecyclerView.Adapter implements ItemDragHelperCallback.OnItemMoveListener { private final Context context; private final LayoutInflater inflater; private List mTables; private ItemDragHelperCallback mItemDragHelperCallback; private OnItemClickListener mOnItemClickListener; public NewsChannelAdapter(Context context, List tables) { this.context = context; this.mTables = tables; this.inflater = LayoutInflater.from(context); } public void setItemDragHelperCallback(ItemDragHelperCallback itemDragHelperCallback) { mItemDragHelperCallback = itemDragHelperCallback; } public void setOnItemClickListener(OnItemClickListener onItemClickListener) { mOnItemClickListener = onItemClickListener; } @Override public ChannelViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new ChannelViewHolder(inflater.inflate(R.layout.item_channel_card, parent, false)); } @Override public void onBindViewHolder(ChannelViewHolder holder, int position) { NewsChannelTable table = mTables.get(position); holder.mTextView.setText(table.getNewsChannelName()); holder.mImageView.setImageResource(table.getImgRes()); handleLongPress(holder, table); handleOnClick(holder, table); } //处理点击事件 private void handleOnClick(final ChannelViewHolder holder, final NewsChannelTable table) { if (mOnItemClickListener != null) { holder.mLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (!table.getNewsChannelFixed()) { //对项目点击后增删操作的监听 mOnItemClickListener.onItemClick(view, holder.getLayoutPosition()); } } }); } } //处理长按事件 开启ItemDragHelperCallBack拖拽 private void handleLongPress(ChannelViewHolder holder, final NewsChannelTable table) { if (mItemDragHelperCallback != null) { holder.mLayout.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { mItemDragHelperCallback.setLongPressEnabled(table.getNewsChannelIndex() == 0 ? false : true); return false; } }); } } @Override public int getItemCount() { return mTables.size(); } @Override public boolean onItemMove(int fromPosition, int toPosition) { if (isChannelFixed(fromPosition, toPosition)) { return false; } //在我的频道子频道的移动 Collections.swap(getAdapterData(), fromPosition, toPosition); notifyItemMoved(fromPosition, toPosition); //通知顺序变换,存储,设置频道顺序,以及显示的顺序 System.out.println("发送移动的消息"); EventBus.getDefault().post(new ChannelBean(getAdapterData())); return true; } //不能移动头条 private boolean isChannelFixed(int fromPosition, int toPosition) { return fromPosition == 0 || toPosition == 0; } public class ChannelViewHolder extends RecyclerView.ViewHolder { private TextView mTextView; private ImageView mImageView; private CardView mCardView; private RelativeLayout mLayout; public ChannelViewHolder(View itemView) { super(itemView); mImageView = (ImageView) itemView.findViewById(R.id.iv_channel_logo); mTextView = (TextView) itemView.findViewById(R.id.tv_channel_name); mCardView = (CardView) itemView.findViewById(R.id.cardView); mLayout = (RelativeLayout) itemView.findViewById(R.id.rl_root); } } public List getAdapterData() { return mTables; } //Item点击事件的监听接口 public interface OnItemClickListener { void onItemClick(View view, int position); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/adapter/NewsChannelGridAdapter.java ================================================ package com.lvr.livecircle.adapter; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import com.lvr.livecircle.R; import com.lvr.livecircle.news.model.bean.NewsChannelTable; import java.util.List; /** * Created by lvr on 2017/2/7. */ public class NewsChannelGridAdapter extends BaseAdapter { private List mTables; private Context mContext; private LayoutInflater mInflater; public NewsChannelGridAdapter(List mTables, Context context) { this.mTables = mTables; this.mContext = context; mInflater = LayoutInflater.from(mContext); } @Override public int getCount() { return mTables.size(); } @Override public Object getItem(int i) { return mTables.get(i); } @Override public long getItemId(int i) { return i; } @Override public View getView(int position, View convertView, ViewGroup group) { View view = null; ViewHolder viewHolder; if(convertView==null){ viewHolder = new ViewHolder(); view = mInflater.inflate(R.layout.item_grid_news_channel,group,false); viewHolder.mImageView = (ImageView) view.findViewById(R.id.iv_channel_logo); viewHolder.mTextView= (TextView) view.findViewById(R.id.tv_channel_name); view.setTag(viewHolder); }else{ view = convertView; viewHolder = (ViewHolder) view.getTag(); } viewHolder.mImageView.setImageResource(mTables.get(position).getImgRes()); viewHolder.mTextView.setText(mTables.get(position).getNewsChannelName()); return view; } public static class ViewHolder { ImageView mImageView; TextView mTextView; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/adapter/NewsListAdapter.java ================================================ package com.lvr.livecircle.adapter; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.GridView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import com.lvr.livecircle.R; import com.lvr.livecircle.bean.NewsInfo; import com.lvr.livecircle.home.MainActivity; import com.lvr.livecircle.news.activity.NewsChannelActivity; import com.lvr.livecircle.news.activity.NewsDetailActivity; import com.lvr.livecircle.news.activity.NewsPhotoDetailActivity; import com.lvr.livecircle.news.model.bean.NewsChannelTable; import com.lvr.livecircle.news.model.bean.NewsPhotoDetail; import com.lvr.livecircle.utils.DisplayUtil; import com.lvr.livecircle.utils.ImageLoaderUtils; import com.lvr.livecircle.utils.ToastUitl; import java.util.ArrayList; import java.util.List; import static com.lvr.livecircle.R.id.news_summary_photo_iv_group; /** * Created by lvr on 2017/2/8. */ public class NewsListAdapter extends RecyclerView.Adapter { private final Context context; private final LayoutInflater inflater; private List list ; private List mTables; //新闻模式 private static final int TYPE_SINGLE = 0; //图集模式 private static final int TYPE_MULTI = 1; //头布局模式 private static final int TYPE_HEADER = 2; //尾布局模式 private static final int TYPE_FOOT = 3; //新闻频道切换监听 private OnNewsChannelListener mNewsChannelListener; public NewsListAdapter(Context context, List list, List tables) { this.context = context; this.list = list; this.mTables = tables; this.inflater = LayoutInflater.from(context); } @Override public int getItemViewType(int position) { NewsInfo info = list.get(position); if(info.getTitle().endsWith("头布局")){ return TYPE_HEADER; } if (!TextUtils.isEmpty(info.getDigest())) { return TYPE_SINGLE; } return TYPE_MULTI; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { switch (viewType) { case TYPE_SINGLE: return new SingleViewHolder(inflater.inflate(R.layout.item_news, parent, false)); case TYPE_MULTI: return new MultiViewHolder(inflater.inflate(R.layout.item_news_photo, parent, false)); case TYPE_HEADER: return new HeaderViewHolder(inflater.inflate(R.layout.item_news_header,parent,false)); } return null; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { //新闻模式 if (holder instanceof SingleViewHolder) { setNormalItemValues((SingleViewHolder) holder,position); }else if(holder instanceof MultiViewHolder){ setMultiItemValues((MultiViewHolder) holder,position); }else if(holder instanceof HeaderViewHolder){ setHeaderItemValues((HeaderViewHolder) holder); } } //设置头布局的值 private void setHeaderItemValues(HeaderViewHolder holder) { NewsChannelGridAdapter mAdapter = new NewsChannelGridAdapter(mTables, context); holder.mGridView.setAdapter(mAdapter); //解决GridView只显示一行的原因 主动设置GridView的高度 ViewGroup.LayoutParams params = holder.mGridView.getLayoutParams(); View view = mAdapter.getView(0, null, holder.mGridView); view.measure(0,0); int height =view.getMeasuredHeight(); int totalHeight = holder.mGridView.getVerticalSpacing() * 2 + height * 2; params.height = totalHeight; holder.mGridView.setLayoutParams(params); } @Override public int getItemCount() { return list.size(); } //新闻模式下item值的设置 private void setNormalItemValues(final SingleViewHolder holder, int position) { final NewsInfo newsInfo = list.get(position); String title = newsInfo.getTitle(); final String content = newsInfo.getDigest(); String time = newsInfo.getPtime(); String imgsrc = newsInfo.getImgsrc(); holder.mTitle.setText(title==null?"新闻头条":title); holder.mContent.setText(content); holder.mTime.setText(time); ImageLoaderUtils.display(context,holder.mImageView,imgsrc); holder.mLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { NewsDetailActivity.startAction(context,holder.mImageView,newsInfo.getPostid(),newsInfo.getImgsrc()); } }); } //图集模式下item值的设置 private void setMultiItemValues(MultiViewHolder holder, int position) { final NewsInfo newsInfo = list.get(position); String title = newsInfo.getTitle(); String time = newsInfo.getPtime(); holder.mTitle.setText(title==null?"新闻头条":title); holder.mTime.setText(time); setImageView(holder,newsInfo); holder.mRoot.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { NewsPhotoDetailActivity.startAction(context,getPhotoDetail(newsInfo)); } }); } private NewsPhotoDetail getPhotoDetail(NewsInfo info) { NewsPhotoDetail newsPhotoDetail = new NewsPhotoDetail(); newsPhotoDetail.setTitle(info.getTitle()); setPictures(info, newsPhotoDetail); return newsPhotoDetail; } private void setPictures(NewsInfo info, NewsPhotoDetail detail) { List pictureList = new ArrayList<>(); if (info.getAds() != null) { for (NewsInfo.AdsBean entity : info.getAds()) { setValuesAndAddToList(pictureList, entity.getTitle(), entity.getImgsrc()); } } else if (info.getImgextra() != null) { for (NewsInfo.ImgextraBean entity : info.getImgextra()) { setValuesAndAddToList(pictureList, null, entity.getImgsrc()); } } else { setValuesAndAddToList(pictureList, null, info.getImgsrc()); } detail.setPictures(pictureList); } private void setValuesAndAddToList(List list, String title, String imgsrc) { NewsPhotoDetail.Picture picture = new NewsPhotoDetail.Picture(); if (title != null) { picture.setTitle(title); } picture.setImgSrc(imgsrc); list.add(picture); } //根据图片的张数设置不同的显示模式 private void setImageView(MultiViewHolder holder, NewsInfo newsInfo) { //根据图片张数确定图片的高度 int PhotoThreeHeight = (int) DisplayUtil.dip2px(90); int PhotoTwoHeight = (int) DisplayUtil.dip2px(120); int PhotoOneHeight = (int) DisplayUtil.dip2px(150); //存放图片url String imgSrcLeft = null; String imgSrcMiddle = null; String imgSrcRight = null; LinearLayout layout = holder.mLayout; ViewGroup.LayoutParams params = layout.getLayoutParams(); //先从ads域中拿图片 if (newsInfo.getAds() != null) { List adsBeanList = newsInfo.getAds(); int size = adsBeanList.size(); if (size >= 3) { //图片数量大于3 只取前三个 imgSrcLeft = adsBeanList.get(0).getImgsrc(); imgSrcMiddle = adsBeanList.get(1).getImgsrc(); imgSrcRight = adsBeanList.get(2).getImgsrc(); params.height = PhotoThreeHeight; } else if (size >= 2) { //图片数量2个 imgSrcLeft = adsBeanList.get(0).getImgsrc(); imgSrcMiddle = adsBeanList.get(1).getImgsrc(); params.height = PhotoTwoHeight; } else if (size >= 1) { //图片数量1个 imgSrcLeft = adsBeanList.get(0).getImgsrc(); params.height = PhotoOneHeight; } //从imgextra域中拿图片 } else if (newsInfo.getImgextra() != null) { int size = newsInfo.getImgextra().size(); if (size >= 3) { imgSrcLeft = newsInfo.getImgextra().get(0).getImgsrc(); imgSrcMiddle = newsInfo.getImgextra().get(1).getImgsrc(); imgSrcRight = newsInfo.getImgextra().get(2).getImgsrc(); params.height = PhotoThreeHeight; } else if (size >= 2) { imgSrcLeft = newsInfo.getImgextra().get(0).getImgsrc(); imgSrcMiddle = newsInfo.getImgextra().get(1).getImgsrc(); params.height = PhotoTwoHeight; } else if (size >= 1) { imgSrcLeft = newsInfo.getImgextra().get(0).getImgsrc(); params.height = PhotoOneHeight; } } else { //从imgsrc域中拿图片 imgSrcLeft = newsInfo.getImgsrc(); params.height = PhotoOneHeight; } layout.setLayoutParams(params); setPhotoImageView(holder, imgSrcLeft, imgSrcMiddle, imgSrcRight); } //将拿到的图片加载显示 private void setPhotoImageView(MultiViewHolder holder, String left, String middle, String right) { if (left != null) { holder.mIvLeft.setVisibility(View.VISIBLE); ImageLoaderUtils.display(context,holder.mIvLeft,left); } else { holder.mIvLeft.setVisibility(View.GONE);//设置为Gone不占位 } if (middle != null) { holder.mIvMiddle.setVisibility(View.VISIBLE); ImageLoaderUtils.display(context,holder.mIvMiddle,middle); } else { holder.mIvMiddle.setVisibility(View.GONE);//设置为Gone不占位 } if (right != null) { holder.mIvRight.setVisibility(View.VISIBLE); ImageLoaderUtils.display(context,holder.mIvRight,right); } else { holder.mIvRight.setVisibility(View.GONE);//设置为Gone不占位 } } public class SingleViewHolder extends RecyclerView.ViewHolder{ private ImageView mImageView; private TextView mTitle; private TextView mContent; private TextView mTime; private RelativeLayout mLayout; public SingleViewHolder(View itemView) { super(itemView); mImageView = (ImageView) itemView.findViewById(R.id.news_summary_photo_iv); mTitle = (TextView) itemView.findViewById(R.id.news_summary_title_tv); mContent = (TextView) itemView.findViewById(R.id.news_summary_digest_tv); mTime = (TextView) itemView.findViewById(R.id.news_summary_ptime_tv); mLayout = (RelativeLayout) itemView.findViewById(R.id.rl_root); } } public class MultiViewHolder extends RecyclerView.ViewHolder{ private LinearLayout mLayout; private TextView mTitle; private TextView mTime; private ImageView mIvLeft; private ImageView mIvMiddle; private ImageView mIvRight; private LinearLayout mRoot; public MultiViewHolder(View itemView) { super(itemView); mLayout = (LinearLayout) itemView.findViewById(news_summary_photo_iv_group); mTitle = (TextView) itemView.findViewById(R.id.news_summary_title_tv); mTime = (TextView) itemView.findViewById(R.id.news_summary_ptime_tv); mIvLeft = (ImageView) itemView.findViewById(R.id.news_summary_photo_iv_left); mIvMiddle = (ImageView) itemView.findViewById(R.id.news_summary_photo_iv_middle); mIvRight = (ImageView) itemView.findViewById(R.id.news_summary_photo_iv_right); mRoot = (LinearLayout) itemView.findViewById(R.id.ll_root); } } public class HeaderViewHolder extends RecyclerView.ViewHolder{ private GridView mGridView; public HeaderViewHolder(View itemView) { super(itemView); mGridView = (GridView) itemView.findViewById(R.id.gv_news_channel); mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View v, int position, long id) { String name = mTables.get(position).getNewsChannelName(); if(name.contains("全部")){ ToastUitl.showShort("切换到新闻频道管理页面:"+name); NewsChannelActivity.startAction((MainActivity) context); }else{ ToastUitl.showShort("切换到新闻频道:"+name); mNewsChannelListener.changeChannelListener(mTables.get(position)); } } }); } } public void setNewsChannelListener(OnNewsChannelListener listener){ mNewsChannelListener = listener; } public List getAdapterData(){ return list; } public void setTables(List list){ mTables = list; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/adapter/OnNewsChannelListener.java ================================================ package com.lvr.livecircle.adapter; import com.lvr.livecircle.news.model.bean.NewsChannelTable; /** * Created by lvr on 2017/2/11. */ public interface OnNewsChannelListener { void changeChannelListener(NewsChannelTable newsChannelTable); } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/adapter/PhotoListAdapter.java ================================================ package com.lvr.livecircle.adapter; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import com.lvr.livecircle.R; import com.lvr.livecircle.meitu.model.bean.PhotoGirl; import com.lvr.livecircle.utils.ImageLoaderUtils; import java.util.List; /** * Created by lvr on 2017/2/20. */ public class PhotoListAdapter extends RecyclerView.Adapter { private Context mContext; private List mData; private final LayoutInflater inflater; public PhotoListAdapter(Context context, List list) { this.mContext = context; this.inflater = LayoutInflater.from(context); this.mData = list; } @Override public PhotoListAdapter.PhotoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new PhotoViewHolder(inflater.inflate(R.layout.item_photo_girl,parent,false)); } @Override public void onBindViewHolder(PhotoListAdapter.PhotoViewHolder holder, int position) { ImageLoaderUtils.display(mContext,holder.mImageView,mData.get(position).getUrl()); } @Override public int getItemCount() { return mData.size(); } public class PhotoViewHolder extends RecyclerView.ViewHolder{ private ImageView mImageView; public PhotoViewHolder(View itemView) { super(itemView); mImageView = (ImageView) itemView.findViewById(R.id.iv_photo); } } public List getAdapterData(){ return mData; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/api/ApiConstants.java ================================================ /* * Copyright (c) 2016 咖枯 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.lvr.livecircle.api; public class ApiConstants { // 头条TYPE public static final String HEADLINE_TYPE = "headline"; // 房产TYPE public static final String HOUSE_TYPE = "house"; // 其他TYPE public static final String OTHER_TYPE = "list"; // 头条id public static final String HEADLINE_ID = "T1348647909107"; // 房产id public static final String HOUSE_ID = "5YyX5Lqs"; /** * 视频 http://c.3g.163.com/nc/video/list/V9LG4CHOR/n/10-10.html */ public static final String Video = "nc/video/list/"; public static final String VIDEO_CENTER = "/n/"; public static final String VIDEO_END_URL = "-10.html"; // 热点视频 public static final String VIDEO_HOT_ID = "V9LG4B3A0"; // 娱乐视频 public static final String VIDEO_ENTERTAINMENT_ID = "V9LG4CHOR"; // 搞笑视频 public static final String VIDEO_FUN_ID = "V9LG4E6VR"; // 精品视频 public static final String VIDEO_CHOICE_ID = "00850FRB"; /** * 图片 * http://gank.io/api/data/福利/{size}/{page} */ public static final String PHOTO_HOST = "http://gank.io/api/"; /** * 新闻id获取类型 * * @param id 新闻id * @return 新闻类型 */ public static String getType(String id) { switch (id) { case HEADLINE_ID: return HEADLINE_TYPE; case HOUSE_ID: return HOUSE_TYPE; default: break; } return OTHER_TYPE; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/api/ApiService.java ================================================ package com.lvr.livecircle.api; import com.lvr.livecircle.bean.NewsInfo; import com.lvr.livecircle.meitu.model.bean.GirlData; import com.lvr.livecircle.news.model.bean.NewsDetail; import java.util.List; import java.util.Map; import io.reactivex.Observable; import okhttp3.ResponseBody; import retrofit2.http.GET; import retrofit2.http.Path; import retrofit2.http.Url; /** * Created by lvr on 2017/2/8. */ public interface ApiService { public static final String NEWS_BASE_URL = "http://c.m.163.com/nc/article/"; public static final String PHOTO_BASE_URL = "http://gank.io/api/data/福利/"; @GET("{type}/{id}/{startPage}-20.html") Observable>> getNewsList( @Path("type") String type, @Path("id") String id, @Path("startPage") int startPage); @GET("{postId}/full.html") Observable> getNewDetail( @Path("postId") String postId); @GET Observable getNewsBodyHtmlPhoto( @Url String photoPath); @GET("{size}/{page}") Observable getPhotoList(@Path("size") int size, @Path("page") int page); } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/api/HostType.java ================================================ /* * Copyright (c) 2016 咖枯 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.lvr.livecircle.api; public class HostType { /** * 多少种Host类型 */ public static final int TYPE_COUNT = 3; /** * 网易新闻视频的host */ public static final int NETEASE_NEWS_VIDEO = 1; /** * 新浪图片的host */ public static final int GANK_GIRL_PHOTO = 2; /** * 新闻详情html图片的host */ public static final int NEWS_DETAIL_HTML_PHOTO = 3; } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/app/AppApplication.java ================================================ package com.lvr.livecircle.app; import com.lvr.livecircle.base.BaseApplication; /** * APPLICATION */ public class AppApplication extends BaseApplication { @Override public void onCreate() { super.onCreate(); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/app/AppConstant.java ================================================ package com.lvr.livecircle.app; public class AppConstant { public static final String HOME_CURRENT_TAB_POSITION="HOME_CURRENT_TAB_POSITION"; public static final String MENU_SHOW_HIDE="MENU_SHOW_HIDE"; /* 新闻*/ public static final String NEWS_ID = "news_id"; public static final String NEWS_TYPE = "news_type"; public static final String CHANNEL_POSITION = "channel_position"; public static final String CHANNEL_MINE = "CHANNEL_MINE"; public static final String CHANNEL_MORE = "CHANNEL_MORE"; public static final String CHANNEL_SWAP = "CHANNEL_SWAP"; public static final String NEWS_CHANNEL_CHANGED = "NEWS_CHANNEL_CHANGED"; /* 视频*/ public static final String VIDEO_TYPE = "VIDEO_TYPE"; public static String NEWS_LIST_TO_TOP = "NEWS_LIST_TO_TOP";//列表返回顶部 public static String ZONE_PUBLISH_ADD = "ZONE_PUBLISH_ADD";//发布说说 public static String NEWS_POST_ID = "NEWS_POST_ID";//新闻详情id public static String NEWS_LINK = "NEWS_LINK"; public static String NEWS_TITLE = "NEWS_TITLE"; public static final String PHOTO_DETAIL_IMGSRC = "photo_detail_imgsrc"; public static final String PHOTO_DETAIL = "photo_detail"; public static final String PHOTO_TAB_CLICK = "PHOTO_TAB_CLICK"; public static final String NEWS_IMG_RES = "news_img_res"; public static final String TRANSITION_ANIMATION_NEWS_PHOTOS = "transition_animation_news_photos"; } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/app/AppManager.java ================================================ package com.lvr.livecircle.app; import android.app.Activity; import android.app.ActivityManager; import android.content.Context; import java.util.Stack; /** * activity管理 */ public class AppManager { private static Stack activityStack; private volatile static AppManager instance; private AppManager() { } /** * 单一实例 */ public static AppManager getAppManager() { if (instance == null) { synchronized (AppManager.class){ if(instance==null){ instance = new AppManager(); instance.activityStack = new Stack(); } } } return instance; } /** * 添加Activity到堆栈 */ public void addActivity(Activity activity) { if (activityStack == null) { activityStack = new Stack(); } activityStack.add(activity); } /** * 获取当前Activity(堆栈中最后一个压入的) */ public Activity currentActivity() { try { Activity activity = activityStack.lastElement(); return activity; } catch (Exception e) { // e.printStackTrace(); return null; } } /** * 获取当前Activity的前一个Activity */ public Activity preActivity() { int index = activityStack.size() - 2; if (index < 0) { return null; } Activity activity = activityStack.get(index); return activity; } /** * 结束当前Activity(堆栈中最后一个压入的) */ public void finishActivity() { Activity activity = activityStack.lastElement(); finishActivity(activity); } /** * 结束指定的Activity */ public void finishActivity(Activity activity) { if (activity != null) { activityStack.remove(activity); activity.finish(); activity = null; } } /** * 移除指定的Activity */ public void removeActivity(Activity activity) { if (activity != null) { activityStack.remove(activity); activity = null; } } /** * 结束指定类名的Activity */ public void finishActivity(Class cls) { try { for (Activity activity : activityStack) { if (activity.getClass().equals(cls)) { finishActivity(activity); } } } catch (Exception e) { e.printStackTrace(); } } /** * 结束所有Activity */ public void finishAllActivity() { for (int i = 0, size = activityStack.size(); i < size; i++) { if (null != activityStack.get(i)) { activityStack.get(i).finish(); } } activityStack.clear(); } /** * 返回到指定的activity * * @param cls */ public void returnToActivity(Class cls) { while (activityStack.size() != 0) if (activityStack.peek().getClass() == cls) { break; } else { finishActivity(activityStack.peek()); } } /** * 是否已经打开指定的activity * @param cls * @return */ public boolean isOpenActivity(Class cls) { if (activityStack!=null){ for (int i = 0, size = activityStack.size(); i < size; i++) { if (cls == activityStack.peek().getClass()) { return true; } } } return false; } /** * 退出应用程序 * * @param context 上下文 * @param isBackground 是否开开启后台运行 */ public void AppExit(Context context, Boolean isBackground) { try { finishAllActivity(); ActivityManager activityMgr = (ActivityManager) context .getSystemService(Context.ACTIVITY_SERVICE); activityMgr.restartPackage(context.getPackageName()); } catch (Exception e) { } finally { // 注意,如果您有后台程序运行,请不要支持此句子 if (!isBackground) { System.exit(0); } } } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/base/BaseActivity.java ================================================ package com.lvr.livecircle.base; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.Window; import com.lvr.livecircle.R; import com.lvr.livecircle.app.AppManager; import com.lvr.livecircle.utils.StatusBarSetting; import com.lvr.livecircle.utils.ToastUitl; import com.lvr.livecircle.widget.LoadingDialog; import butterknife.ButterKnife; import butterknife.Unbinder; /** * 基类 */ public abstract class BaseActivity extends AppCompatActivity { public Context mContext; private Unbinder mUnbinder; private int count;//记录开启进度条的情况 只能开一个 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); doBeforeSetcontentView(); setContentView(getLayoutId()); // 默认着色状态栏 SetStatusBarColor(); mUnbinder = ButterKnife.bind(this); mContext = this; this.initPresenter(); this.initView(); } /** * 设置layout前配置 */ private void doBeforeSetcontentView() { // 把actvity放到application栈中管理 AppManager.getAppManager().addActivity(this); // 无标题 requestWindowFeature(Window.FEATURE_NO_TITLE); // 设置竖屏 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } /********************* * 子类实现 *****************************/ //获取布局文件 public abstract int getLayoutId(); //简单页面无需mvp就不用管此方法即可,完美兼容各种实际场景的变通 public abstract void initPresenter(); //初始化view public abstract void initView(); /** * 着色状态栏(4.4以上系统有效) */ protected void SetStatusBarColor() { StatusBarSetting.setColor(this, getResources().getColor(R.color.colorPrimary)); } /** * 着色状态栏(4.4以上系统有效) */ protected void SetStatusBarColor(int color) { StatusBarSetting.setColor(this, color); } /** * 沉浸状态栏(4.4以上系统有效) */ protected void SetTranslanteBar() { StatusBarSetting.setTranslucent(this); } /** * 通过Class跳转界面 **/ public void startActivity(Class cls) { startActivity(cls, null); } /** * 通过Class跳转界面 **/ public void startActivityForResult(Class cls, int requestCode) { startActivityForResult(cls, null, requestCode); } /** * 含有Bundle通过Class跳转界面 **/ public void startActivityForResult(Class cls, Bundle bundle, int requestCode) { Intent intent = new Intent(); intent.setClass(this, cls); if (bundle != null) { intent.putExtras(bundle); } startActivityForResult(intent, requestCode); } /** * 含有Bundle通过Class跳转界面 **/ public void startActivity(Class cls, Bundle bundle) { Intent intent = new Intent(); intent.setClass(this, cls); if (bundle != null) { intent.putExtras(bundle); } startActivity(intent); } /** * 开启浮动加载进度条 */ public void startProgressDialog() { count++; if(count==1){ LoadingDialog.showDialogForLoading(this); } } /** * 开启浮动加载进度条 * * @param msg */ public void startProgressDialog(String msg) { count++; if(count==1){ LoadingDialog.showDialogForLoading(this, msg, true); } } /** * 停止浮动加载进度条 */ public void stopProgressDialog() { count--; if(count==0){ LoadingDialog.cancelDialogForLoading(); } } /** * 短暂显示Toast提示(来自String) **/ public void showShortToast(String text) { ToastUitl.showShort(text); } /** * 短暂显示Toast提示(id) **/ public void showShortToast(int resId) { ToastUitl.showShort(resId); } /** * 长时间显示Toast提示(来自res) **/ public void showLongToast(int resId) { ToastUitl.showLong(resId); } /** * 长时间显示Toast提示(来自String) **/ public void showLongToast(String text) { ToastUitl.showLong(text); } /** * 带图片的toast * * @param text * @param res */ public void showToastWithImg(String text, int res) { ToastUitl.showToastWithImg(text, res); } /** * 网络访问错误提醒 */ public void showNetErrorTip() { ToastUitl.showToastWithImg(getText(R.string.net_error).toString(), R.drawable.ic_wifi_off); } public void showNetErrorTip(String error) { ToastUitl.showToastWithImg(error, R.drawable.ic_wifi_off); } @Override protected void onResume() { super.onResume(); } @Override protected void onPause() { super.onPause(); } @Override protected void onDestroy() { super.onDestroy(); mUnbinder.unbind(); AppManager.getAppManager().finishActivity(this); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/base/BaseApplication.java ================================================ package com.lvr.livecircle.base; import android.app.Application; import android.content.Context; import android.content.res.Resources; /** * APPLICATION */ public class BaseApplication extends Application { private static BaseApplication baseApplication; @Override public void onCreate() { super.onCreate(); baseApplication = this; } public static Context getAppContext() { return baseApplication; } public static Resources getAppResources() { return baseApplication.getResources(); } @Override public void onTerminate() { super.onTerminate(); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/base/BaseFragment.java ================================================ package com.lvr.livecircle.base; import android.content.Intent; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.lvr.livecircle.utils.ToastUitl; import com.lvr.livecircle.widget.LoadingDialog; import butterknife.ButterKnife; import butterknife.Unbinder; public abstract class BaseFragment extends Fragment { protected View rootView; private Unbinder mUnbinder; private int count;//记录开启进度条的情况 只能开一个 //当前Fragment是否处于可见状态标志,防止因ViewPager的缓存机制而导致回调函数的触发 private boolean isFragmentVisible; //是否是第一次开启网络加载 public boolean isFirst; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (rootView == null) rootView = inflater.inflate(getLayoutResource(), container, false); mUnbinder = ButterKnife.bind(this, rootView); initView(); //可见,但是并没有加载过 if (isFragmentVisible && !isFirst) { onFragmentVisibleChange(true); } return rootView; } //获取布局文件 protected abstract int getLayoutResource(); //初始化view protected abstract void initView(); /** * 通过Class跳转界面 **/ public void startActivity(Class cls) { startActivity(cls, null); } /** * 通过Class跳转界面 **/ public void startActivityForResult(Class cls, int requestCode) { startActivityForResult(cls, null, requestCode); } /** * 含有Bundle通过Class跳转界面 **/ public void startActivityForResult(Class cls, Bundle bundle, int requestCode) { Intent intent = new Intent(); intent.setClass(getActivity(), cls); if (bundle != null) { intent.putExtras(bundle); } startActivityForResult(intent, requestCode); } /** * 含有Bundle通过Class跳转界面 **/ public void startActivity(Class cls, Bundle bundle) { Intent intent = new Intent(); intent.setClass(getActivity(), cls); if (bundle != null) { intent.putExtras(bundle); } startActivity(intent); } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isVisibleToUser) { isFragmentVisible = true; } if (rootView == null) { return; } //可见,并且没有加载过 if (!isFirst&&isFragmentVisible) { onFragmentVisibleChange(true); return; } //由可见——>不可见 已经加载过 if (isFragmentVisible) { onFragmentVisibleChange(false); isFragmentVisible = false; } } /** * 开启加载进度条 */ public void startProgressDialog() { count++; if (count == 1) { LoadingDialog.showDialogForLoading(getActivity()); } } /** * 开启加载进度条 * * @param msg */ public void startProgressDialog(String msg) { LoadingDialog.showDialogForLoading(getActivity(), msg, true); } /** * 停止加载进度条 */ public void stopProgressDialog() { count--; if (count == 0) { LoadingDialog.cancelDialogForLoading(); } } /** * 短暂显示Toast提示(来自String) **/ public void showShortToast(String text) { ToastUitl.showShort(text); } /** * 短暂显示Toast提示(id) **/ public void showShortToast(int resId) { ToastUitl.showShort(resId); } /** * 长时间显示Toast提示(来自res) **/ public void showLongToast(int resId) { ToastUitl.showLong(resId); } /** * 长时间显示Toast提示(来自String) **/ public void showLongToast(String text) { ToastUitl.showLong(text); } public void showToastWithImg(String text, int res) { ToastUitl.showToastWithImg(text, res); } /** * 网络访问错误提醒 */ public void showNetErrorTip() { } public void showNetErrorTip(String error) { } public void showLoading() { } public void stopLoading() { } @Override public void onDestroyView() { super.onDestroyView(); mUnbinder.unbind(); } /** * 当前fragment可见状态发生变化时会回调该方法 * 如果当前fragment是第一次加载,等待onCreateView后才会回调该方法,其它情况回调时机跟 {@link #setUserVisibleHint(boolean)}一致 * 在该回调方法中你可以做一些加载数据操作,甚至是控件的操作. * * @param isVisible true 不可见 -> 可见 * false 可见 -> 不可见 */ protected void onFragmentVisibleChange(boolean isVisible) { } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/base/BaseFragmentAdapter.java ================================================ package com.lvr.livecircle.base; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import com.lvr.livecircle.utils.CollectionUtils; import java.util.ArrayList; import java.util.List; public class BaseFragmentAdapter extends FragmentPagerAdapter { List fragmentList = new ArrayList(); private List mTitles; public BaseFragmentAdapter(FragmentManager fm, List fragmentList) { super(fm); this.fragmentList = fragmentList; } public BaseFragmentAdapter(FragmentManager fm, List fragmentList, List mTitles) { super(fm); this.fragmentList = fragmentList; this.mTitles = mTitles; } @Override public CharSequence getPageTitle(int position) { return !CollectionUtils.isNullOrEmpty(mTitles) ? mTitles.get(position) : ""; } @Override public Fragment getItem(int position) { return fragmentList.get(position); } @Override public int getCount() { return fragmentList.size(); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/bean/ChannelBean.java ================================================ package com.lvr.livecircle.bean; import com.lvr.livecircle.news.model.bean.NewsChannelTable; import java.util.List; /** * Created by lvr on 2017/2/14. */ //通知频道变换的Event类 public class ChannelBean { public List mList; public int fromPosition; public int toPosition; public ChannelBean(List list) { mList = list; } public List getList() { return mList; } public void setList(List list) { mList = list; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/bean/FabScrollBean.java ================================================ package com.lvr.livecircle.bean; /** * Created by lvr on 2017/2/12. */ public class FabScrollBean { private String scrollMsg; public int getPosition() { return position; } public void setPosition(int position) { this.position = position; } private int position; public FabScrollBean(String scrollMsg,int position) { this.scrollMsg = scrollMsg; this.position = position; } public String getScrollMsg() { return scrollMsg; } public void setScrollMsg(String scrollMsg) { this.scrollMsg = scrollMsg; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/bean/HeaderBean.java ================================================ package com.lvr.livecircle.bean; import com.lvr.livecircle.news.model.bean.NewsChannelTable; import java.util.List; /** * Created by lvr on 2017/2/14. */ public class HeaderBean { private List mList; public HeaderBean(List list) { mList = list; } public List getList() { return mList; } public void setList(List list) { mList = list; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/bean/NewsInfo.java ================================================ package com.lvr.livecircle.bean; import android.os.Parcel; import android.os.Parcelable; import java.util.ArrayList; import java.util.List; /** * Created by lvr on 2017/2/8. */ //使用GsonFormat插件 使用Parcelable插件 public class NewsInfo implements Parcelable { /** * postid : PHOT24589000100A * hasCover : false * hasHead : 1 * replyCount : 32056 * hasImg : 1 * digest : * hasIcon : false * docid : 9IG74V5H00963VRO_CCP0IVDUcaoruiupdateDoc * title : 韩民众举"包青天"头像 抗议总统弹劾案 * order : 1 * priority : 354 * lmodify : 2017-02-08 16:14:08 * boardid : photoview_bbs * ads : [{"title":"直击云南边境扫雷 地雷炮弹摆满地","tag":"photoset","imgsrc":"http://cms-bucket.nosdn.127.net/e4c85b6a0db74b139b0c40572181883a20170208163525.jpeg","subtitle":"","url":"00AP0001|2233612"},{"title":"特朗普任后首批被遣墨西哥移民回国","tag":"photoset","imgsrc":"http://cms-bucket.nosdn.127.net/40dd56cbd22043519fc7bdbb95cc954820170208164609.jpeg","subtitle":"","url":"00AO0001|2233614"},{"title":"巴西警察罢工引发骚乱 已致75人死亡","tag":"photoset","imgsrc":"http://cms-bucket.nosdn.127.net/0c27e0f72fab46c08c4399e6146cc4a120170208163826.jpeg","subtitle":"","url":"00AO0001|2233613"},{"title":"大圣驾车被交警拦下 车上坐一群\"妖怪\"","tag":"photoset","imgsrc":"http://cms-bucket.nosdn.127.net/376884a7cff14a95839f23a032c3f60620170208100814.jpeg","subtitle":"","url":"00AP0001|2233503"},{"title":"广东揭阳江中现观音像 村民打捞参拜","tag":"photoset","imgsrc":"http://cms-bucket.nosdn.127.net/f7fb6acf5e424a12aeaacb7b6192006320170208093602.jpeg","subtitle":"","url":"00AP0001|2233473"}] * photosetID : 00AO0001|2233609 * imgsum : 4 * topic_background : http://img2.cache.netease.com/m/newsapp/reading/cover1/C1348646712614.jpg * template : normal1 * votecount : 29790 * skipID : 00AO0001|2233609 * alias : Top News * skipType : photoset * cid : C1348646712614 * hasAD : 1 * imgextra : [{"imgsrc":"http://cms-bucket.nosdn.127.net/3e8167782a344c47886dd4b818274e3720170208161145.jpeg"},{"imgsrc":"http://cms-bucket.nosdn.127.net/1bef3f98431f4be780320ce58d7c68d920170208160645.jpeg"}] * source : 网易原创 * ename : androidnews * tname : 头条 * imgsrc : http://cms-bucket.nosdn.127.net/37148e8af39440be9b41606f72dc49d520170208161145.jpeg * ptime : 2017-02-08 16:07:25 */ private String postid; private boolean hasCover; private int hasHead; private int replyCount; private int hasImg; private String digest; private boolean hasIcon; private String docid; private String title; private int order; private int priority; private String lmodify; private String boardid; private String photosetID; private int imgsum; private String topic_background; private String template; private int votecount; private String skipID; private String alias; private String skipType; private String cid; private int hasAD; private String source; private String ename; private String tname; private String imgsrc; private String ptime; private List ads; private List imgextra; public String getPostid() { return postid; } public void setPostid(String postid) { this.postid = postid; } public boolean isHasCover() { return hasCover; } public void setHasCover(boolean hasCover) { this.hasCover = hasCover; } public int getHasHead() { return hasHead; } public void setHasHead(int hasHead) { this.hasHead = hasHead; } public int getReplyCount() { return replyCount; } public void setReplyCount(int replyCount) { this.replyCount = replyCount; } public int getHasImg() { return hasImg; } public void setHasImg(int hasImg) { this.hasImg = hasImg; } public String getDigest() { return digest; } public void setDigest(String digest) { this.digest = digest; } public boolean isHasIcon() { return hasIcon; } public void setHasIcon(boolean hasIcon) { this.hasIcon = hasIcon; } public String getDocid() { return docid; } public void setDocid(String docid) { this.docid = docid; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public int getOrder() { return order; } public void setOrder(int order) { this.order = order; } public int getPriority() { return priority; } public void setPriority(int priority) { this.priority = priority; } public String getLmodify() { return lmodify; } public void setLmodify(String lmodify) { this.lmodify = lmodify; } public String getBoardid() { return boardid; } public void setBoardid(String boardid) { this.boardid = boardid; } public String getPhotosetID() { return photosetID; } public void setPhotosetID(String photosetID) { this.photosetID = photosetID; } public int getImgsum() { return imgsum; } public void setImgsum(int imgsum) { this.imgsum = imgsum; } public String getTopic_background() { return topic_background; } public void setTopic_background(String topic_background) { this.topic_background = topic_background; } public String getTemplate() { return template; } public void setTemplate(String template) { this.template = template; } public int getVotecount() { return votecount; } public void setVotecount(int votecount) { this.votecount = votecount; } public String getSkipID() { return skipID; } public void setSkipID(String skipID) { this.skipID = skipID; } public String getAlias() { return alias; } public void setAlias(String alias) { this.alias = alias; } public String getSkipType() { return skipType; } public void setSkipType(String skipType) { this.skipType = skipType; } public String getCid() { return cid; } public void setCid(String cid) { this.cid = cid; } public int getHasAD() { return hasAD; } public void setHasAD(int hasAD) { this.hasAD = hasAD; } public String getSource() { return source; } public void setSource(String source) { this.source = source; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public String getTname() { return tname; } public void setTname(String tname) { this.tname = tname; } public String getImgsrc() { return imgsrc; } public void setImgsrc(String imgsrc) { this.imgsrc = imgsrc; } public String getPtime() { return ptime; } public void setPtime(String ptime) { this.ptime = ptime; } public List getAds() { return ads; } public void setAds(List ads) { this.ads = ads; } public List getImgextra() { return imgextra; } public void setImgextra(List imgextra) { this.imgextra = imgextra; } public static class AdsBean { /** * title : 直击云南边境扫雷 地雷炮弹摆满地 * tag : photoset * imgsrc : http://cms-bucket.nosdn.127.net/e4c85b6a0db74b139b0c40572181883a20170208163525.jpeg * subtitle : * url : 00AP0001|2233612 */ private String title; private String tag; private String imgsrc; private String subtitle; private String url; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getTag() { return tag; } public void setTag(String tag) { this.tag = tag; } public String getImgsrc() { return imgsrc; } public void setImgsrc(String imgsrc) { this.imgsrc = imgsrc; } public String getSubtitle() { return subtitle; } public void setSubtitle(String subtitle) { this.subtitle = subtitle; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } } public static class ImgextraBean { /** * imgsrc : http://cms-bucket.nosdn.127.net/3e8167782a344c47886dd4b818274e3720170208161145.jpeg */ private String imgsrc; public String getImgsrc() { return imgsrc; } public void setImgsrc(String imgsrc) { this.imgsrc = imgsrc; } } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.postid); dest.writeByte(this.hasCover ? (byte) 1 : (byte) 0); dest.writeInt(this.hasHead); dest.writeInt(this.replyCount); dest.writeInt(this.hasImg); dest.writeString(this.digest); dest.writeByte(this.hasIcon ? (byte) 1 : (byte) 0); dest.writeString(this.docid); dest.writeString(this.title); dest.writeInt(this.order); dest.writeInt(this.priority); dest.writeString(this.lmodify); dest.writeString(this.boardid); dest.writeString(this.photosetID); dest.writeInt(this.imgsum); dest.writeString(this.topic_background); dest.writeString(this.template); dest.writeInt(this.votecount); dest.writeString(this.skipID); dest.writeString(this.alias); dest.writeString(this.skipType); dest.writeString(this.cid); dest.writeInt(this.hasAD); dest.writeString(this.source); dest.writeString(this.ename); dest.writeString(this.tname); dest.writeString(this.imgsrc); dest.writeString(this.ptime); dest.writeList(this.ads); dest.writeList(this.imgextra); } public NewsInfo() { } protected NewsInfo(Parcel in) { this.postid = in.readString(); this.hasCover = in.readByte() != 0; this.hasHead = in.readInt(); this.replyCount = in.readInt(); this.hasImg = in.readInt(); this.digest = in.readString(); this.hasIcon = in.readByte() != 0; this.docid = in.readString(); this.title = in.readString(); this.order = in.readInt(); this.priority = in.readInt(); this.lmodify = in.readString(); this.boardid = in.readString(); this.photosetID = in.readString(); this.imgsum = in.readInt(); this.topic_background = in.readString(); this.template = in.readString(); this.votecount = in.readInt(); this.skipID = in.readString(); this.alias = in.readString(); this.skipType = in.readString(); this.cid = in.readString(); this.hasAD = in.readInt(); this.source = in.readString(); this.ename = in.readString(); this.tname = in.readString(); this.imgsrc = in.readString(); this.ptime = in.readString(); this.ads = new ArrayList(); in.readList(this.ads, AdsBean.class.getClassLoader()); this.imgextra = new ArrayList(); in.readList(this.imgextra, ImgextraBean.class.getClassLoader()); } public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override public NewsInfo createFromParcel(Parcel source) { return new NewsInfo(source); } @Override public NewsInfo[] newArray(int size) { return new NewsInfo[size]; } }; } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/client/BaseApiService.java ================================================ package com.lvr.livecircle.client; import java.util.Map; import io.reactivex.Observable; import okhttp3.RequestBody; import okhttp3.ResponseBody; import retrofit2.http.Body; import retrofit2.http.GET; import retrofit2.http.Multipart; import retrofit2.http.POST; import retrofit2.http.Part; import retrofit2.http.PartMap; import retrofit2.http.Path; import retrofit2.http.QueryMap; public interface BaseApiService { public static final String Base_URL = "http://ip.taobao.com/"; @GET("{url}") Observable> executeGet( @Path("url") String url, @QueryMap Map maps ); @POST("{url}") Observable> executePost( @Path("url") String url, @QueryMap Map maps); @POST("{url}") Observable json( @Path("url") String url, @Body RequestBody jsonStr); @Multipart @POST("{url}") Observable upLoadFile( @Path("url") String url, @Part("image\"; filename=\"image.jpg") RequestBody requestBody); @POST("{url}") Observable uploadFiles( @Path("url") String url, @Part("userName") String description, @PartMap() Map maps); } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/client/BaseInterceptor.java ================================================ package com.lvr.livecircle.client; import java.io.IOException; import java.util.Map; import java.util.Set; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; public class BaseInterceptor implements Interceptor { private Map headers; public BaseInterceptor(Map headers) { this.headers = headers; } @Override public Response intercept(Chain chain) throws IOException { Request.Builder builder = chain.request() .newBuilder(); if (headers != null && headers.size() > 0) { Set keys = headers.keySet(); for (String headerKey : keys) { builder.addHeader(headerKey, headers.get(headerKey)).build(); } } return chain.proceed(builder.build()); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/client/BaseObserver.java ================================================ package com.lvr.livecircle.client; import android.content.Context; import android.util.Log; import android.widget.Toast; import io.reactivex.Observer; import io.reactivex.disposables.Disposable; public abstract class BaseObserver implements Observer { private Context context; public BaseObserver(Context context) { this.context = context; } @Override public void onError(Throwable e) { Log.e("lvr", e.getMessage()); // todo error somthing if(e instanceof ExceptionHandle.ResponeThrowable){ onError((ExceptionHandle.ResponeThrowable)e); } else { onError(new ExceptionHandle.ResponeThrowable(e, ExceptionHandle.ERROR.UNKNOWN)); } } @Override public void onSubscribe(Disposable d) { Toast.makeText(context, "建立连接", Toast.LENGTH_SHORT).show(); //可以弹出Dialog 提示正在加载 showDialog(); } protected abstract void hideDialog(); protected abstract void showDialog(); @Override public void onComplete() { Toast.makeText(context, "请求完毕", Toast.LENGTH_SHORT).show(); //可以取消Dialog 加载完毕 hideDialog(); } public abstract void onError(ExceptionHandle.ResponeThrowable e); } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/client/BaseResponse.java ================================================ package com.lvr.livecircle.client; public class BaseResponse { private int code; private String msg; private T data; public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public T getData() { return data; } public void setData(T data) { this.data = data; } public boolean isOk() { return code == 0; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/client/CaheInterceptor.java ================================================ package com.lvr.livecircle.client; import android.content.Context; import android.util.Log; import java.io.IOException; import okhttp3.CacheControl; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; public class CaheInterceptor implements Interceptor { private Context context; public CaheInterceptor(Context context) { this.context = context; } @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); if (NetworkUtil.isNetworkAvailable(context)) { Response response = chain.proceed(request); // read from cache for 60 s int maxAge = 60; String cacheControl = request.cacheControl().toString(); Log.e("CacheInterceptor", "6s load cahe" + cacheControl); return response.newBuilder() .removeHeader("Pragma") .removeHeader("Cache-Control") .header("Cache-Control", "public, max-age=" + maxAge) .build(); } else { Log.e("CacheInterceptor", " no network load cahe"); request = request.newBuilder() .cacheControl(CacheControl.FORCE_CACHE) .build(); Response response = chain.proceed(request); //set cahe times is 3 days int maxStale = 60 * 60 * 24 * 3; return response.newBuilder() .removeHeader("Pragma") .removeHeader("Cache-Control") .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) .build(); } } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/client/ExceptionHandle.java ================================================ package com.lvr.livecircle.client; import android.net.ParseException; import com.google.gson.JsonParseException; import com.jakewharton.retrofit2.adapter.rxjava2.HttpException; import org.apache.http.conn.ConnectTimeoutException; import org.json.JSONException; import java.net.ConnectException; public class ExceptionHandle { private static final int UNAUTHORIZED = 401; private static final int FORBIDDEN = 403; private static final int NOT_FOUND = 404; private static final int REQUEST_TIMEOUT = 408; private static final int INTERNAL_SERVER_ERROR = 500; private static final int BAD_GATEWAY = 502; private static final int SERVICE_UNAVAILABLE = 503; private static final int GATEWAY_TIMEOUT = 504; public static ResponeThrowable handleException(Throwable e) { ResponeThrowable ex; if (e instanceof HttpException) { HttpException httpException = (HttpException) e; ex = new ResponeThrowable(e, ERROR.HTTP_ERROR); switch (httpException.code()) { case UNAUTHORIZED: case FORBIDDEN: case NOT_FOUND: case REQUEST_TIMEOUT: case GATEWAY_TIMEOUT: case INTERNAL_SERVER_ERROR: case BAD_GATEWAY: case SERVICE_UNAVAILABLE: default: ex.message = "网络错误"; break; } return ex; } else if (e instanceof ServerException) { ServerException resultException = (ServerException) e; ex = new ResponeThrowable(resultException, resultException.code); ex.message = resultException.message; return ex; } else if (e instanceof JsonParseException || e instanceof JSONException || e instanceof ParseException) { ex = new ResponeThrowable(e, ERROR.PARSE_ERROR); ex.message = "解析错误"; return ex; } else if (e instanceof ConnectException) { ex = new ResponeThrowable(e, ERROR.NETWORD_ERROR); ex.message = "连接失败"; return ex; } else if (e instanceof javax.net.ssl.SSLHandshakeException) { ex = new ResponeThrowable(e, ERROR.SSL_ERROR); ex.message = "证书验证失败"; return ex; } else if (e instanceof ConnectTimeoutException){ ex = new ResponeThrowable(e, ERROR.TIMEOUT_ERROR); ex.message = "连接超时"; return ex; } else if (e instanceof java.net.SocketTimeoutException) { ex = new ResponeThrowable(e, ERROR.TIMEOUT_ERROR); ex.message = "连接超时"; return ex; } else { ex = new ResponeThrowable(e, ERROR.UNKNOWN); ex.message = "未知错误"; return ex; } } /** * 约定异常 */ class ERROR { /** * 未知错误 */ public static final int UNKNOWN = 1000; /** * 解析错误 */ public static final int PARSE_ERROR = 1001; /** * 网络错误 */ public static final int NETWORD_ERROR = 1002; /** * 协议出错 */ public static final int HTTP_ERROR = 1003; /** * 证书出错 */ public static final int SSL_ERROR = 1005; /** * 连接超时 */ public static final int TIMEOUT_ERROR = 1006; } public static class ResponeThrowable extends Exception { public int code; public String message; public ResponeThrowable(Throwable throwable, int code) { super(throwable); this.code = code; } } public class ServerException extends RuntimeException { public int code; public String message; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/client/IpResult.java ================================================ package com.lvr.livecircle.client; public class IpResult { private String country; private String country_id; private String area; private String area_id; private String region; private String region_id; private String city; private String city_id; private String county; private String county_id; private String isp; private String isp_id; private String ip; public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public String getCountry_id() { return country_id; } public void setCountry_id(String country_id) { this.country_id = country_id; } public String getArea() { return area; } public void setArea(String area) { this.area = area; } public String getArea_id() { return area_id; } public void setArea_id(String area_id) { this.area_id = area_id; } public String getRegion() { return region; } public void setRegion(String region) { this.region = region; } public String getRegion_id() { return region_id; } public void setRegion_id(String region_id) { this.region_id = region_id; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getCity_id() { return city_id; } public void setCity_id(String city_id) { this.city_id = city_id; } public String getCounty() { return county; } public void setCounty(String county) { this.county = county; } public String getCounty_id() { return county_id; } public void setCounty_id(String county_id) { this.county_id = county_id; } public String getIsp() { return isp; } public void setIsp(String isp) { this.isp = isp; } public String getIsp_id() { return isp_id; } public void setIsp_id(String isp_id) { this.isp_id = isp_id; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } @Override public String toString() { return "IpResult{" + "country='" + country + '\'' + ", country_id='" + country_id + '\'' + ", area='" + area + '\'' + ", area_id='" + area_id + '\'' + ", region='" + region + '\'' + ", region_id='" + region_id + '\'' + ", city='" + city + '\'' + ", city_id='" + city_id + '\'' + ", county='" + county + '\'' + ", county_id='" + county_id + '\'' + ", isp='" + isp + '\'' + ", isp_id='" + isp_id + '\'' + ", ip='" + ip + '\'' + '}'; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/client/NetworkUtil.java ================================================ package com.lvr.livecircle.client; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.telephony.TelephonyManager; import java.io.IOException; import java.net.HttpURLConnection; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.net.URL; import java.util.Enumeration; public class NetworkUtil { public static int NET_CNNT_BAIDU_OK = 1; // NetworkAvailable public static int NET_CNNT_BAIDU_TIMEOUT = 2; // no NetworkAvailable public static int NET_NOT_PREPARE = 3; // Net no ready public static int NET_ERROR = 4; //net error private static int TIMEOUT = 3000; // TIMEOUT /** * check NetworkAvailable * @param context * @return */ public static boolean isNetworkAvailable(Context context) { ConnectivityManager manager = (ConnectivityManager) context.getApplicationContext().getSystemService( Context.CONNECTIVITY_SERVICE); if (null == manager) return false; NetworkInfo info = manager.getActiveNetworkInfo(); if (null == info || !info.isAvailable()) return false; return true; } /** * getLocalIpAddress * @return */ public static String getLocalIpAddress() { String ret = ""; try { for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { NetworkInterface intf = en.nextElement(); for (Enumeration enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) { InetAddress inetAddress = enumIpAddr.nextElement(); if (!inetAddress.isLoopbackAddress()) { ret = inetAddress.getHostAddress().toString(); } } } } catch (SocketException ex) { ex.printStackTrace(); } return ret; } /** * 返回当前网络状态 * * @param context * @return */ public static int getNetState(Context context) { try { ConnectivityManager connectivity = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); if (connectivity != null) { NetworkInfo networkinfo = connectivity.getActiveNetworkInfo(); if (networkinfo != null) { if (networkinfo.isAvailable() && networkinfo.isConnected()) { if (!connectionNetwork()) return NET_CNNT_BAIDU_TIMEOUT; else return NET_CNNT_BAIDU_OK; } else { return NET_NOT_PREPARE; } } } } catch (Exception e) { e.printStackTrace(); } return NET_ERROR; } /** *ping "http://www.baidu.com" * @return */ static private boolean connectionNetwork() { boolean result = false; HttpURLConnection httpUrl = null; try { httpUrl = (HttpURLConnection) new URL("http://www.baidu.com") .openConnection(); httpUrl.setConnectTimeout(TIMEOUT); httpUrl.connect(); result = true; } catch (IOException e) { } finally { if (null != httpUrl) { httpUrl.disconnect(); } httpUrl = null; } return result; } /** * check is3G * @param context * @return boolean */ public static boolean is3G(Context context) { ConnectivityManager connectivityManager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo(); if (activeNetInfo != null && activeNetInfo.getType() == ConnectivityManager.TYPE_MOBILE) { return true; } return false; } /** * isWifi * @param context * @return boolean */ public static boolean isWifi(Context context) { ConnectivityManager connectivityManager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo(); if (activeNetInfo != null && activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI) { return true; } return false; } /** * is2G * @param context * @return boolean */ public static boolean is2G(Context context) { ConnectivityManager connectivityManager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo(); if (activeNetInfo != null && (activeNetInfo.getSubtype() == TelephonyManager.NETWORK_TYPE_EDGE || activeNetInfo.getSubtype() == TelephonyManager.NETWORK_TYPE_GPRS || activeNetInfo .getSubtype() == TelephonyManager.NETWORK_TYPE_CDMA)) { return true; } return false; } /** * is wifi on */ public static boolean isWifiEnabled(Context context) { ConnectivityManager mgrConn = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); TelephonyManager mgrTel = (TelephonyManager) context .getSystemService(Context.TELEPHONY_SERVICE); return ((mgrConn.getActiveNetworkInfo() != null && mgrConn .getActiveNetworkInfo().getState() == NetworkInfo.State.CONNECTED) || mgrTel .getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/client/RetrofitClient.java ================================================ package com.lvr.livecircle.client; import android.content.Context; import android.text.TextUtils; import android.util.Log; import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; import java.io.File; import java.util.Map; import java.util.concurrent.TimeUnit; import io.reactivex.Observable; import io.reactivex.ObservableSource; import io.reactivex.ObservableTransformer; import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.functions.Function; import io.reactivex.schedulers.Schedulers; import okhttp3.Cache; import okhttp3.OkHttpClient; import okhttp3.RequestBody; import okhttp3.ResponseBody; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; /** * RetrofitClient */ public class RetrofitClient { private static final int DEFAULT_TIMEOUT = 20; private BaseApiService apiService; private static OkHttpClient okHttpClient; public static String baseUrl = BaseApiService.Base_URL; private static Context mContext; private static RetrofitClient sNewInstance; private static ErrorTransformer transformer = new ErrorTransformer(); private static Retrofit retrofit; private Cache cache = null; private File httpCacheDirectory; private static Retrofit.Builder builder = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .baseUrl(baseUrl); private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder() .addNetworkInterceptor( new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.HEADERS)) .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); private static Class aClass; //默认baseUrl的单例 private static class SingletonHolder { private static RetrofitClient INSTANCE = new RetrofitClient( mContext); } public static RetrofitClient getInstance(Context context) { if (context != null) { mContext = context; } return SingletonHolder.INSTANCE; } //自己提供url public static RetrofitClient getInstance(Context context, String url) { if (context != null) { mContext = context; } return new RetrofitClient(context, url); } //不仅有url还有headers public static RetrofitClient getInstance(Context context, String url, Map headers) { if (context != null) { mContext = context; } return new RetrofitClient(context, url, headers); } private RetrofitClient() { } private RetrofitClient(Context context) { this(context, baseUrl, null); } private RetrofitClient(Context context, String url) { this(context, url, null); } private RetrofitClient(Context context, String url, Map headers) { //url为空,则默认使用baseUrl if (TextUtils.isEmpty(url)) { url = baseUrl; } //缓存地址 if (httpCacheDirectory == null) { httpCacheDirectory = new File(mContext.getCacheDir(), "app_cache"); } try { if (cache == null) { cache = new Cache(httpCacheDirectory, 10 * 1024 * 1024); } } catch (Exception e) { Log.e("OKHttp", "Could not create http cache", e); } //okhttp创建了 okHttpClient = new OkHttpClient.Builder() .addNetworkInterceptor( new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)) .cache(cache) .addInterceptor(new BaseInterceptor(headers)) .addInterceptor(new CaheInterceptor(context)) .addNetworkInterceptor(new CaheInterceptor(context)) .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .build(); //retrofit创建了 retrofit = new Retrofit.Builder() .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .baseUrl(url) .build(); } public void get(String url, Map parameters, Observer observer) { apiService.executeGet(url, parameters) .compose(schedulersTransformer) .compose(transformer) .subscribe(observer); } public void post(String url, Map parameters, Observer observer) { apiService.executePost(url, parameters) .compose(schedulersTransformer) .compose(transformer) .subscribe(observer); } public void json(String url, RequestBody jsonStr, Observer observer) { apiService.json(url, jsonStr) .compose(schedulersTransformer) .compose(transformer) .subscribe(observer); } public void upload(String url, RequestBody requestBody, Observer observer) { apiService.upLoadFile(url, requestBody) .compose(schedulersTransformer) .compose(transformer) .subscribe(observer); } //处理线程调度的变换 public static ObservableTransformer schedulersTransformer = new ObservableTransformer() { @Override public ObservableSource apply(Observable upstream) { return ((Observable) upstream).subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } }; //处理错误的变换 private static class ErrorTransformer implements ObservableTransformer{ @Override public ObservableSource apply(Observable upstream) { //onErrorResumeNext当发生错误的时候,由另外一个Observable来代替当前的Observable并继续发射数据 return (Observable) upstream.map(new HandleFuc()).onErrorResumeNext(new HttpResponseFunc()); } } public static class HttpResponseFunc implements Function> { @Override public Observable apply(Throwable throwable) throws Exception { return Observable.error(ExceptionHandle.handleException(throwable)); } } public static class HandleFuc implements Function, T> { @Override public T apply(BaseResponse response) throws Exception { //response中code码不会0 出现错误 if (!response.isOk()) throw new RuntimeException(response.getCode() + "" + response.getMsg() != null ? response.getMsg() : ""); return response.getData(); } } /** * 创建默认url的api类 * @return ApiManager */ public RetrofitClient createBaseApi() { apiService = create(BaseApiService.class); return this; } /** * create you ApiService * Create an implementation of the API endpoints defined by the {@code service} interface. */ public T create(final Class service) { if (service == null) { throw new RuntimeException("Api service is null!"); } return retrofit.create(service); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/client/RxDisposeManager.java ================================================ package com.lvr.livecircle.client; import android.support.v4.util.ArrayMap; import java.util.Set; import io.reactivex.disposables.Disposable; /** * Created by lvr on 2017/2/9. */ public class RxDisposeManager { private static RxDisposeManager sInstance = null; private ArrayMap maps; public static RxDisposeManager get() { if (sInstance == null) { synchronized (RxDisposeManager.class) { if (sInstance == null) { sInstance = new RxDisposeManager(); } } } return sInstance; } private RxDisposeManager() { maps = new ArrayMap<>(); } public void add(Object tag, Disposable disposable) { maps.put(tag, disposable); } public void remove(Object tag) { if (!maps.isEmpty()) { maps.remove(tag); } } public void removeAll() { if (!maps.isEmpty()) { maps.clear(); } } public void cancel(Object tag) { if (maps.isEmpty()) { return; } if (maps.get(tag) == null) { return; } if (!maps.get(tag).isDisposed()) { maps.get(tag).dispose(); maps.remove(tag); } } public void cancelAll() { if (maps.isEmpty()) { return; } Set keys = maps.keySet(); for (Object apiKey : keys) { cancel(apiKey); } } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/find/FindFragment.java ================================================ package com.lvr.livecircle.find; import com.lvr.livecircle.R; import com.lvr.livecircle.base.BaseFragment; /** * Created by lvr on 2017/2/6. */ public class FindFragment extends BaseFragment { @Override protected int getLayoutResource() { return R.layout.fragment_find; } @Override protected void initView() { } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/home/MainActivity.java ================================================ package com.lvr.livecircle.home; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.NavigationView; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.support.v4.view.ViewPager; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.View; import android.widget.ImageView; import com.lvr.livecircle.R; import com.lvr.livecircle.adapter.HomeViewPagerAdapter; import com.lvr.livecircle.base.BaseActivity; import com.lvr.livecircle.bean.FabScrollBean; import com.lvr.livecircle.find.FindFragment; import com.lvr.livecircle.meitu.MeiTuFragment; import com.lvr.livecircle.music.MusicFragment; import com.lvr.livecircle.nearby.NearByFragment; import com.lvr.livecircle.news.fragment.NewsFragment; import com.lvr.livecircle.recommend.RecommendFragment; import com.lvr.livecircle.utils.StatusBarSetting; import com.lvr.livecircle.video.VideoFragment; import java.util.ArrayList; import java.util.Arrays; import butterknife.BindView; import de.greenrobot.event.EventBus; public class MainActivity extends BaseActivity { @BindView(R.id.toolbar) Toolbar mToolbar; @BindView(R.id.navigation) NavigationView mAmNv; @BindView(R.id.drawer_layout) DrawerLayout mAmDl; @BindView(R.id.tabs) TabLayout mTabs; @BindView(R.id.vp_moudle) ViewPager mVpMoudle; @BindView(R.id.fab) FloatingActionButton mFab; private View mView_nav; private ImageView mIv_photo; private String[] mMoudleName = {"推荐", "新闻", "音乐", "美图", "附近", "视频", "发现"}; private ArrayList mFragmentList = new ArrayList(); private NewsFragment mNewsFragment; private RecommendFragment mRecommendFragment; private MusicFragment mMusicFragment; private MeiTuFragment mMeiTuFragment; private NearByFragment mNearByFragment; private VideoFragment mVideoFragment; private FindFragment mFindFragment; private HomeViewPagerAdapter mAdapter; @Override public int getLayoutId() { return R.layout.activity_main; } @Override public void initPresenter() { } @Override public void initView() { StatusBarSetting.setColorForDrawerLayout(this, mAmDl, getResources().getColor(R.color.colorPrimary), StatusBarSetting.DEFAULT_STATUS_BAR_ALPHA); setToolBar(); setNavigationView(); mFab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { EventBus.getDefault().post(new FabScrollBean("滑动到顶端",mTabs.getSelectedTabPosition())); } }); mTabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { int position = tab.getPosition(); if(position==1||position==3){ mFab.setVisibility(View.VISIBLE); }else{ mFab.setVisibility(View.GONE); } } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } }); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //初始化frament initFragment(savedInstanceState); setViewPager(); } /** * 填充ViewPager内容 */ private void setViewPager() { mAdapter = new HomeViewPagerAdapter(getSupportFragmentManager(), mFragmentList, Arrays.asList(mMoudleName)); mVpMoudle.setAdapter(mAdapter); mTabs.setupWithViewPager(mVpMoudle); mTabs.setTabTextColors(getResources().getColor(R.color.white), getResources().getColor(R.color.black)); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); FragmentManager manager = getSupportFragmentManager(); if (mNewsFragment.isAdded()) { manager.putFragment(outState, "NewsFragment", mNewsFragment); } if (mFindFragment.isAdded()) { manager.putFragment(outState, "FindFragment", mFindFragment); } if (mVideoFragment.isAdded()) { manager.putFragment(outState, "VideoFragment", mVideoFragment); } if (mNearByFragment.isAdded()) { manager.putFragment(outState, "NearByFragment", mNearByFragment); } if (mMeiTuFragment.isAdded()) { manager.putFragment(outState, "MeiTuFragment", mMeiTuFragment); } if (mMusicFragment.isAdded()) { manager.putFragment(outState, "MusicFragment", mMusicFragment); } if (mRecommendFragment.isAdded()) { manager.putFragment(outState, "RecommendFragment", mRecommendFragment); } } /** * 初始化fragment的记忆状态 * * @param savedInstanceState */ private void initFragment(Bundle savedInstanceState) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); if (savedInstanceState != null) { mNewsFragment = (NewsFragment) getSupportFragmentManager().getFragment(savedInstanceState, "NewsFragment"); mRecommendFragment = (RecommendFragment) getSupportFragmentManager().getFragment(savedInstanceState, "RecommendFragment"); mFindFragment = (FindFragment) getSupportFragmentManager().getFragment(savedInstanceState, "FindFragment"); mVideoFragment = (VideoFragment) getSupportFragmentManager().getFragment(savedInstanceState, "VideoFragment"); mNearByFragment = (NearByFragment) getSupportFragmentManager().getFragment(savedInstanceState, "NearByFragment"); mMeiTuFragment = (MeiTuFragment) getSupportFragmentManager().getFragment(savedInstanceState, "MeiTuFragment"); mMusicFragment = (MusicFragment) getSupportFragmentManager().getFragment(savedInstanceState, "MusicFragment"); } else { mNewsFragment = new NewsFragment(); mRecommendFragment = new RecommendFragment(); mFindFragment = new FindFragment(); mVideoFragment = new VideoFragment(); mNearByFragment = new NearByFragment(); mMeiTuFragment = new MeiTuFragment(); mMusicFragment = new MusicFragment(); } mFragmentList.add(mRecommendFragment); mFragmentList.add(mNewsFragment); mFragmentList.add(mMusicFragment); mFragmentList.add(mMeiTuFragment); mFragmentList.add(mNearByFragment); mFragmentList.add(mVideoFragment); mFragmentList.add(mFindFragment); } /** * 设置导航页信息 */ private void setNavigationView() { //NavigationView初始化 mAmNv.setItemIconTintList(null); View headerView = mAmNv.getHeaderView(0); mIv_photo = (ImageView) headerView.findViewById(R.id.iv_user_photo); } /** * 设置状态栏 */ private void setToolBar() { setSupportActionBar(mToolbar); ActionBar actionBar = getSupportActionBar(); //菜单按钮可用 actionBar.setHomeButtonEnabled(true); //回退按钮可用 actionBar.setDisplayHomeAsUpEnabled(true); //将drawlayout与toolbar绑定在一起 ActionBarDrawerToggle abdt = new ActionBarDrawerToggle(this, mAmDl, mToolbar, R.string.app_name, R.string.app_name); abdt.syncState();//初始化状态 //设置drawlayout的监听事件 打开/关闭 mAmDl.setDrawerListener(abdt); //actionbar中的内容进行初始化 mToolbar.setTitle("Live圈");//设置标题 mToolbar.setTitleTextColor(getResources().getColor(R.color.white)); } /** * 入口 * * @param activity */ public static void startAction(Activity activity) { Intent intent = new Intent(activity, MainActivity.class); activity.startActivity(intent); activity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_toolabr, menu); return true; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/home/SplashActivity.java ================================================ package com.lvr.livecircle.home; import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.view.animation.AccelerateInterpolator; import android.widget.ImageView; import android.widget.TextView; import com.lvr.livecircle.R; import com.lvr.livecircle.base.BaseActivity; import butterknife.BindView; /** * Created by lvr on 2017/2/6. */ public class SplashActivity extends BaseActivity { @BindView(R.id.iv_logo) ImageView mIvLogo; @BindView(R.id.tv_name) TextView mTvName; @Override public int getLayoutId() { return R.layout.activty_splash; } @Override public void initPresenter() { } @Override public void initView() { SetTranslanteBar(); PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0.3f, 1f); PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.3f, 1f); PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.3f, 1f); ObjectAnimator objectAnimator1 = ObjectAnimator.ofPropertyValuesHolder(mTvName, alpha, scaleX, scaleY); ObjectAnimator objectAnimator2 = ObjectAnimator.ofPropertyValuesHolder(mIvLogo, alpha, scaleX, scaleY); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(objectAnimator1, objectAnimator2); animatorSet.setInterpolator(new AccelerateInterpolator()); animatorSet.setDuration(2000); animatorSet.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { } @Override public void onAnimationEnd(Animator animator) { MainActivity.startAction(SplashActivity.this); finish(); } @Override public void onAnimationCancel(Animator animator) { } @Override public void onAnimationRepeat(Animator animator) { } }); animatorSet.start(); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/meitu/MeiTuFragment.java ================================================ package com.lvr.livecircle.meitu; import android.content.Context; import android.support.v7.widget.StaggeredGridLayoutManager; import com.aspsine.irecyclerview.IRecyclerView; import com.aspsine.irecyclerview.OnLoadMoreListener; import com.aspsine.irecyclerview.OnRefreshListener; import com.lvr.livecircle.R; import com.lvr.livecircle.adapter.PhotoListAdapter; import com.lvr.livecircle.base.BaseFragment; import com.lvr.livecircle.bean.FabScrollBean; import com.lvr.livecircle.client.RxDisposeManager; import com.lvr.livecircle.meitu.model.bean.PhotoGirl; import com.lvr.livecircle.meitu.presenter.impl.PhotoPresenterImpl; import com.lvr.livecircle.meitu.view.PhotoView; import com.lvr.livecircle.widget.LoadMoreFooterView; import com.lvr.livecircle.widget.LoadingDialog; import java.util.List; import butterknife.BindView; import de.greenrobot.event.EventBus; import de.greenrobot.event.Subscribe; /** * Created by lvr on 2017/2/6. */ public class MeiTuFragment extends BaseFragment implements PhotoView, OnRefreshListener, OnLoadMoreListener { @BindView(R.id.recyclerView) IRecyclerView mRecyclerView; private Context mContext; private static int SIZE = 20; private int mStartPage = 1; private PhotoPresenterImpl mPresenter; private PhotoListAdapter mAdapter; private LoadMoreFooterView mFooterView; @Override protected int getLayoutResource() { return R.layout.fragment_meitu; } @Override protected void onFragmentVisibleChange(boolean isVisible) { if(isVisible){ //可见,并且是第一次加载 mPresenter.requestPhotoList(SIZE,mStartPage); LoadingDialog.showDialogForLoading(getActivity()); }else{ //取消加载 RxDisposeManager.get().cancel("photoList"); LoadingDialog.cancelDialogForLoading(); } } @Override protected void initView() { mContext = getActivity(); mPresenter = new PhotoPresenterImpl(this); StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); manager.setItemPrefetchEnabled(false); mRecyclerView.setLayoutManager(manager); mRecyclerView.setOnRefreshListener(this); mRecyclerView.setOnLoadMoreListener(this); mFooterView = (LoadMoreFooterView) mRecyclerView.getLoadMoreFooterView(); if (!EventBus.getDefault().isRegistered(this)) { EventBus.getDefault().register(this); } } @Subscribe public void onFabScrollEvent(FabScrollBean event) { if(event.getPosition()==3){ mRecyclerView.smoothScrollToPosition(0); } } @Override public void returnPhotoList(List photoGirlList) { if (!isFirst) { isFirst = true; LoadingDialog.cancelDialogForLoading(); mAdapter = new PhotoListAdapter(mContext, photoGirlList); mRecyclerView.setIAdapter(mAdapter); } else if (photoGirlList != null) { if (mStartPage == 1) { //刷新请求 mRecyclerView.setRefreshing(false); List data = mAdapter.getAdapterData(); data.clear(); data.addAll(photoGirlList); mAdapter.notifyDataSetChanged(); } else { //加载更多 List data = mAdapter.getAdapterData(); data.addAll(photoGirlList); mAdapter.notifyDataSetChanged(); } } else { mStartPage--; mFooterView.setStatus(LoadMoreFooterView.Status.THE_END); } } @Override public void showErrorTip() { if (mFooterView != null) { mFooterView.setStatus(LoadMoreFooterView.Status.ERROR); } } @Override public void onLoadMore() { mStartPage++; mPresenter.requestPhotoList(SIZE, mStartPage); mFooterView.setStatus(LoadMoreFooterView.Status.LOADING); } @Override public void onRefresh() { //发起请求 mRecyclerView.setRefreshing(true); mStartPage = 1; mPresenter.requestPhotoList(SIZE, mStartPage); mFooterView.setStatus(LoadMoreFooterView.Status.GONE); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/meitu/model/PhotoModel.java ================================================ package com.lvr.livecircle.meitu.model; import com.lvr.livecircle.meitu.model.bean.PhotoGirl; import java.util.List; import io.reactivex.Observable; /** * Created by lvr on 2017/2/20. */ public interface PhotoModel { Observable> getPhotoList(int size, int page); } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/meitu/model/bean/GirlData.java ================================================ package com.lvr.livecircle.meitu.model.bean; import java.util.List; /** * Created by lvr on 2017/2/20. */ public class GirlData { /** * error : false * results : [{"_id":"58a9752b421aa93d3d15aa31","createdAt":"2017-02-19T18:36:27.16Z","desc":"2-20","publishedAt":"2017-02-20T11:56:22.616Z","source":"chrome","type":"福利","url":"http://7xi8d6.com1.z0.glb.clouddn.com/2017-02-19-16789884_666922016823652_4719569931841044480_n.jpg","used":true,"who":"daimajia"},{"_id":"58a641a4421aa9662f429734","createdAt":"2017-02-17T08:19:48.413Z","desc":"2-17","publishedAt":"2017-02-17T11:31:19.996Z","source":"chrome","type":"福利","url":"http://7xi8d6.com1.z0.glb.clouddn.com/2017-02-17-16464474_721724277990542_654863958657728512_n.jpg","used":true,"who":"daimajia"},{"_id":"58a504d1421aa966366d05ce","createdAt":"2017-02-16T09:48:01.526Z","desc":"2-16","publishedAt":"2017-02-16T10:07:37.13Z","source":"chrome","type":"福利","url":"http://7xi8d6.com1.z0.glb.clouddn.com/2017-02-16-16790004_607292222809583_5160406710837313536_n.jpg","used":true,"who":"daimajia"},{"_id":"58a39d1c421aa966366d05c0","createdAt":"2017-02-15T08:13:16.351Z","desc":"2-15","publishedAt":"2017-02-15T11:24:04.127Z","source":"chrome","type":"福利","url":"http://7xi8d6.com1.z0.glb.clouddn.com/2017-02-15-16464434_414363458902323_3665858302006263808_n.jpg","used":true,"who":"daimajia"},{"_id":"58a24ce0421aa901ef40579f","createdAt":"2017-02-14T08:18:40.781Z","desc":"2-14","publishedAt":"2017-02-14T11:42:37.303Z","source":"chrome","type":"福利","url":"http://7xi8d6.com1.z0.glb.clouddn.com/2017-02-14-16123260_755771577930478_8918176595718438912_n.jpg","used":true,"who":"daimajia"},{"_id":"58a10619421aa901f7902c6a","createdAt":"2017-02-13T09:04:25.996Z","desc":"2-13","publishedAt":"2017-02-13T11:54:17.922Z","source":"chrome","type":"福利","url":"http://7xi8d6.com1.z0.glb.clouddn.com/2017-02-13-16464498_1247940031909047_2763412151866490880_n.jpg","used":true,"who":"daimajia"},{"_id":"589d31a2421aa9270bc7332e","createdAt":"2017-02-10T11:21:06.747Z","desc":"2-10","publishedAt":"2017-02-10T11:38:22.122Z","source":"chrome","type":"福利","url":"http://7xi8d6.com1.z0.glb.clouddn.com/2017-02-10-16465759_171779496648995_128281069584646144_n.jpg","used":true,"who":"代码家"},{"_id":"589bb252421aa92dc0dfd3bf","createdAt":"2017-02-09T08:05:38.361Z","desc":"2-9","publishedAt":"2017-02-09T11:46:26.70Z","source":"chrome","type":"福利","url":"http://7xi8d6.com1.z0.glb.clouddn.com/2017-02-09-16583339_172818256542563_353855393375453184_n.jpg","used":true,"who":"daimajia"},{"_id":"589a7161421aa92db8a0041b","createdAt":"2017-02-08T09:16:17.678Z","desc":"2-8","publishedAt":"2017-02-08T11:39:51.371Z","source":"chrome","type":"福利","url":"http://7xi8d6.com1.z0.glb.clouddn.com/2017-02-08-16230686_191036801373876_4789664128824246272_n.jpg","used":true,"who":"daimajia"},{"_id":"58993f2c421aa970b84523ab","createdAt":"2017-02-07T11:29:48.689Z","desc":"2-7","publishedAt":"2017-02-07T11:37:03.683Z","source":"chrome","type":"福利","url":"http://7xi8d6.com1.z0.glb.clouddn.com/2017-02-07-032924.jpg","used":true,"who":"daimajia"},{"_id":"5897d9e9421aa970bb154891","createdAt":"2017-02-06T10:05:29.443Z","desc":"2-6","publishedAt":"2017-02-06T11:36:12.36Z","source":"chrome","type":"福利","url":"http://7xi8d6.com1.z0.glb.clouddn.com/2017-02-06-16464762_1304611439576933_4803269855073533952_n.jpg","used":true,"who":"代码家"},{"_id":"58947b15421aa970bb154878","createdAt":"2017-02-03T20:44:05.311Z","desc":"2-4","publishedAt":"2017-02-04T11:47:42.336Z","source":"chrome","type":"福利","url":"http://7xi8d6.com1.z0.glb.clouddn.com/2017-02-03-123209.jpg","used":true,"who":"代码家"},{"_id":"5893f544421aa90e69b17f8c","createdAt":"2017-02-03T11:13:08.967Z","desc":"2-3","publishedAt":"2017-02-03T11:52:22.806Z","source":"chrome","type":"福利","url":"http://7xi8d6.com1.z0.glb.clouddn.com/16123958_1630476787257847_7576387494862651392_n.jpg","used":true,"who":"daimajia"},{"_id":"58857746421aa95eae2d92b3","createdAt":"2017-01-23T11:23:50.64Z","desc":"1-23","publishedAt":"2017-01-23T11:35:32.450Z","source":"chrome","type":"福利","url":"http://7xi8d6.com1.z0.glb.clouddn.com/16124047_121657248344062_4191645221970247680_n.jpg","used":true,"who":"代码家"},{"_id":"58841c08421aa95ea9de7a0c","createdAt":"2017-01-22T10:42:16.648Z","desc":"1-22","publishedAt":"2017-01-22T11:39:29.779Z","source":"chrome","type":"福利","url":"http://7xi8d6.com1.z0.glb.clouddn.com/16229501_482786908558452_6858241750058663936_n.jpg","used":true,"who":"daimajia"},{"_id":"58817e1e421aa9119735ac5f","createdAt":"2017-01-20T11:03:58.727Z","desc":"1-20","publishedAt":"2017-01-20T11:50:52.750Z","source":"chrome","type":"福利","url":"http://7xi8d6.com1.z0.glb.clouddn.com/2017-01-20-030332.jpg","used":true,"who":"daimajia"},{"_id":"58802bea421aa9119a6ca6ab","createdAt":"2017-01-19T11:00:58.838Z","desc":"1-19","publishedAt":"2017-01-19T11:40:09.118Z","source":"chrome","type":"福利","url":"http://7xi8d6.com1.z0.glb.clouddn.com/16124351_1863111260639981_4361246625721483264_n.jpg","used":true,"who":"daimajia"},{"_id":"587c6073421aa91194ca0e2c","createdAt":"2017-01-16T13:56:03.417Z","desc":"1-16","publishedAt":"2017-01-16T14:12:18.71Z","source":"chrome","type":"福利","url":"http://ww3.sinaimg.cn/large/610dc034gw1fbsfgssfrwj20u011h48y.jpg","used":true,"who":"daimajia"},{"_id":"5878471d421aa9119735ac13","createdAt":"2017-01-13T11:18:53.183Z","desc":"1-13","publishedAt":"2017-01-13T11:58:16.991Z","source":"chrome","type":"福利","url":"http://ww3.sinaimg.cn/large/610dc034gw1fbou2xsqpaj20u00u0q4h.jpg","used":true,"who":"daimajia"},{"_id":"5876e811421aa9315bfbe85f","createdAt":"2017-01-12T10:21:05.74Z","desc":"1-12","publishedAt":"2017-01-12T11:30:59.369Z","source":"chrome","type":"福利","url":"http://ww2.sinaimg.cn/large/0060lm7Tgw1fbnmsjogt9j30u00u0jvv.jpg","used":true,"who":"daimajia"}] */ private boolean error; private List results; public boolean isError() { return error; } public void setError(boolean error) { this.error = error; } public List getResults() { return results; } public void setResults(List results) { this.results = results; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/meitu/model/bean/PhotoGirl.java ================================================ package com.lvr.livecircle.meitu.model.bean; /** * Created by lvr on 2017/2/20. */ public class PhotoGirl { /** * _id : 58a9752b421aa93d3d15aa31 * createdAt : 2017-02-19T18:36:27.16Z * desc : 2-20 * publishedAt : 2017-02-20T11:56:22.616Z * source : chrome * type : 福利 * url : http://7xi8d6.com1.z0.glb.clouddn.com/2017-02-19-16789884_666922016823652_4719569931841044480_n.jpg * used : true * who : daimajia */ private String _id; private String createdAt; private String desc; private String publishedAt; private String source; private String type; private String url; private boolean used; private String who; public String get_id() { return _id; } public void set_id(String _id) { this._id = _id; } public String getCreatedAt() { return createdAt; } public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getPublishedAt() { return publishedAt; } public void setPublishedAt(String publishedAt) { this.publishedAt = publishedAt; } public String getSource() { return source; } public void setSource(String source) { this.source = source; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public boolean isUsed() { return used; } public void setUsed(boolean used) { this.used = used; } public String getWho() { return who; } public void setWho(String who) { this.who = who; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/meitu/model/impl/PhotoModelImpl.java ================================================ package com.lvr.livecircle.meitu.model.impl; import com.lvr.livecircle.api.ApiService; import com.lvr.livecircle.app.AppApplication; import com.lvr.livecircle.client.RetrofitClient; import com.lvr.livecircle.meitu.model.PhotoModel; import com.lvr.livecircle.meitu.model.bean.GirlData; import com.lvr.livecircle.meitu.model.bean.PhotoGirl; import java.util.List; import io.reactivex.Observable; import io.reactivex.functions.Function; /** * Created by lvr on 2017/2/20. */ public class PhotoModelImpl implements PhotoModel { @Override public Observable> getPhotoList(int size, int page) { RetrofitClient client = RetrofitClient.getInstance(AppApplication.getAppContext(), ApiService.PHOTO_BASE_URL); ApiService api = client.create(ApiService.class); return api.getPhotoList(size,page).map(new Function>() { @Override public List apply(GirlData data) throws Exception { return data.getResults(); } }).compose(RetrofitClient.schedulersTransformer); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/meitu/presenter/PhotoPresenter.java ================================================ package com.lvr.livecircle.meitu.presenter; /** * Created by lvr on 2017/2/20. */ public interface PhotoPresenter { void requestPhotoList(int size,int page); } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/meitu/presenter/impl/PhotoPresenterImpl.java ================================================ package com.lvr.livecircle.meitu.presenter.impl; import com.lvr.livecircle.client.RxDisposeManager; import com.lvr.livecircle.meitu.MeiTuFragment; import com.lvr.livecircle.meitu.model.bean.PhotoGirl; import com.lvr.livecircle.meitu.model.impl.PhotoModelImpl; import com.lvr.livecircle.meitu.presenter.PhotoPresenter; import java.util.List; import io.reactivex.Observer; import io.reactivex.disposables.Disposable; /** * Created by lvr on 2017/2/20. */ public class PhotoPresenterImpl implements PhotoPresenter { private PhotoModelImpl mModel; private MeiTuFragment mView; //是否开启了dialog private boolean showDialog; public PhotoPresenterImpl(MeiTuFragment mView) { this.mView = mView; this.mModel = new PhotoModelImpl(); } @Override public void requestPhotoList(int size, int page) { mModel.getPhotoList(size,page).subscribe(new Observer>() { @Override public void onSubscribe(Disposable d) { RxDisposeManager.get().add("photoList",d); } @Override public void onNext(List girls) { mView.returnPhotoList(girls); } @Override public void onError(Throwable e) { mView.showErrorTip(); } @Override public void onComplete() { } }); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/meitu/view/PhotoView.java ================================================ package com.lvr.livecircle.meitu.view; import com.lvr.livecircle.meitu.model.bean.PhotoGirl; import java.util.List; /** * Created by lvr on 2017/2/20. */ public interface PhotoView { void returnPhotoList(List photoGirlList); void showErrorTip(); } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/music/MusicFragment.java ================================================ package com.lvr.livecircle.music; import com.lvr.livecircle.R; import com.lvr.livecircle.base.BaseFragment; /** * Created by lvr on 2017/2/6. */ public class MusicFragment extends BaseFragment { @Override protected int getLayoutResource() { return R.layout.fragment_music; } @Override protected void initView() { } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/nearby/NearByFragment.java ================================================ package com.lvr.livecircle.nearby; import com.lvr.livecircle.R; import com.lvr.livecircle.base.BaseFragment; /** * Created by lvr on 2017/2/6. */ public class NearByFragment extends BaseFragment { @Override protected int getLayoutResource() { return R.layout.fragment_nearby; } @Override protected void initView() { } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/activity/NewsChannelActivity.java ================================================ package com.lvr.livecircle.news.activity; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Build; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.support.v7.widget.helper.ItemTouchHelper; import android.view.View; import com.lvr.livecircle.R; import com.lvr.livecircle.adapter.NewsChannelAdapter; import com.lvr.livecircle.base.BaseActivity; import com.lvr.livecircle.bean.ChannelBean; import com.lvr.livecircle.news.model.bean.NewsChannelTable; import com.lvr.livecircle.news.presenter.NewsChannelPresenter; import com.lvr.livecircle.news.presenter.impl.NewsChannelPresenterImpl; import com.lvr.livecircle.news.view.NewsChannelView; import com.lvr.livecircle.utils.ToastUitl; import com.lvr.livecircle.widget.ItemDragHelperCallback; import java.util.ArrayList; import java.util.List; import butterknife.BindView; import de.greenrobot.event.EventBus; import de.greenrobot.event.Subscribe; /** * 新闻频道管理页面 * Created by lvr on 2017/2/11. */ public class NewsChannelActivity extends BaseActivity implements NewsChannelView { @BindView(R.id.toolbar) Toolbar mToolbar; @BindView(R.id.news_channel_mine_rv) RecyclerView mNewsChannelMineRv; @BindView(R.id.news_channel_more_rv) RecyclerView mNewsChannelMoreRv; private NewsChannelPresenter mPresenter; private Context mContext; private NewsChannelAdapter mMineAdapter; private NewsChannelAdapter mMoreAdapter; @Override public int getLayoutId() { return R.layout.activity_news_channel; } @Override public void initPresenter() { mPresenter = new NewsChannelPresenterImpl(this); } @Override public void initView() { SetStatusBarColor(); mContext = this; mToolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { finishAfterTransition(); } else { finish(); } } }); mPresenter.lodeChannelsRequest(); if(!EventBus.getDefault().isRegistered(this)){ EventBus.getDefault().register(this); } } @Subscribe public void onChannelEvent(ChannelBean event){ List list = event.getList(); System.out.println("接收移动的消息"); mPresenter.onItemSwap((ArrayList) list); } /** * 入口 * * @param activity */ public static void startAction(Activity activity) { Intent intent = new Intent(activity, NewsChannelActivity.class); activity.startActivity(intent); activity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out); } @Override public void returnMineNewsChannels(List newsChannelsMine) { mMineAdapter = new NewsChannelAdapter(mContext, newsChannelsMine); mNewsChannelMineRv.setLayoutManager(new GridLayoutManager(this, 4, LinearLayoutManager.VERTICAL, false)); mNewsChannelMineRv.setItemAnimator(new DefaultItemAnimator()); mNewsChannelMineRv.setAdapter(mMineAdapter); //加载数据完毕后 设置监听,拖拽移动事件 和 点击事件 把ItemDragHelperCallback设置给RecyclerView使用 ItemDragHelperCallback callback = new ItemDragHelperCallback(mMineAdapter); ItemTouchHelper touchHelper = new ItemTouchHelper(callback); touchHelper.attachToRecyclerView(mNewsChannelMineRv); mMineAdapter.setItemDragHelperCallback(callback); mMineAdapter.setOnItemClickListener(new NewsChannelAdapter.OnItemClickListener() { @Override public void onItemClick(View view, int position) { NewsChannelTable newsChannel = mMineAdapter.getAdapterData().get(position); mMoreAdapter.getAdapterData().add(newsChannel); mMoreAdapter.notifyDataSetChanged(); mMineAdapter.getAdapterData().remove(position); mMineAdapter.notifyDataSetChanged(); //进行添加或删除操作后,要更新的列表 进行存储 mPresenter.onItemAddOrRemove((ArrayList) mMineAdapter.getAdapterData(), (ArrayList) mMoreAdapter.getAdapterData()); } }); } @Override public void returnMoreNewsChannels(List newsChannelsMore) { mMoreAdapter = new NewsChannelAdapter(mContext, newsChannelsMore); mNewsChannelMoreRv.setLayoutManager(new GridLayoutManager(this, 4, LinearLayoutManager.VERTICAL, false)); mNewsChannelMoreRv.setItemAnimator(new DefaultItemAnimator()); mNewsChannelMoreRv.setAdapter(mMoreAdapter); mMoreAdapter.setOnItemClickListener(new NewsChannelAdapter.OnItemClickListener() { @Override public void onItemClick(View view, int position) { if(mMineAdapter.getAdapterData().size()==7){ ToastUitl.showShort("最多只能添加7个"); }else{ NewsChannelTable newsChannel = mMoreAdapter.getAdapterData().get(position); mMoreAdapter.getAdapterData().remove(position); mMoreAdapter.notifyDataSetChanged(); mMineAdapter.getAdapterData().add(newsChannel); mMineAdapter.notifyDataSetChanged(); List data = mMineAdapter.getAdapterData(); for (NewsChannelTable table : data) { System.out.println(table); } //进行添加或删除操作后,要更新的列表 进行存储 mPresenter.onItemAddOrRemove((ArrayList) mMineAdapter.getAdapterData(), (ArrayList) mMoreAdapter.getAdapterData()); } } }); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/activity/NewsDetailActivity.java ================================================ package com.lvr.livecircle.news.activity; import android.app.Activity; import android.app.ActivityOptions; import android.content.Context; import android.content.Intent; import android.os.Build; import android.support.design.widget.AppBarLayout; import android.support.design.widget.CollapsingToolbarLayout; import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityOptionsCompat; import android.support.v4.content.ContextCompat; import android.support.v7.widget.Toolbar; import android.text.Html; import android.view.View; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import com.lvr.livecircle.R; import com.lvr.livecircle.app.AppConstant; import com.lvr.livecircle.base.BaseActivity; import com.lvr.livecircle.client.RetrofitClient; import com.lvr.livecircle.client.RxDisposeManager; import com.lvr.livecircle.news.model.bean.NewsDetail; import com.lvr.livecircle.news.presenter.impl.NewsDetailPresenterImpl; import com.lvr.livecircle.news.view.NewsDetailView; import com.lvr.livecircle.utils.ImageLoaderUtils; import com.lvr.livecircle.utils.StatusBarSetting; import com.lvr.livecircle.utils.TimeUtil; import com.lvr.livecircle.widget.URLImageGetter; import java.util.List; import java.util.concurrent.TimeUnit; import butterknife.BindView; import io.reactivex.Observable; import io.reactivex.Observer; import io.reactivex.disposables.Disposable; /** * 普通新闻详情 */ public class NewsDetailActivity extends BaseActivity implements NewsDetailView { @BindView(R.id.news_detail_photo_iv) ImageView mNewsDetailPhotoIv; @BindView(R.id.toolbar) Toolbar mToolbar; @BindView(R.id.toolbar_layout) CollapsingToolbarLayout mToolbarLayout; @BindView(R.id.app_bar) AppBarLayout mAppBar; @BindView(R.id.news_detail_from_tv) TextView mNewsDetailFromTv; @BindView(R.id.news_detail_body_tv) TextView mNewsDetailBodyTv; @BindView(R.id.progress_bar) ProgressBar mProgressBar; private String postId; private String mNewsTitle; private String mShareLink; private NewsDetailPresenterImpl mPresenter; private Context mContext; private URLImageGetter mUrlImageGetter; /** * 入口 * * @param mContext * @param postId */ public static void startAction(Context mContext, View view, String postId, String imgUrl) { Intent intent = new Intent(mContext, NewsDetailActivity.class); intent.putExtra(AppConstant.NEWS_POST_ID, postId); intent.putExtra(AppConstant.NEWS_IMG_RES, imgUrl); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { ActivityOptions options = ActivityOptions .makeSceneTransitionAnimation((Activity) mContext, view, AppConstant.TRANSITION_ANIMATION_NEWS_PHOTOS); mContext.startActivity(intent, options.toBundle()); } else { //让新的Activity从一个小的范围扩大到全屏 ActivityOptionsCompat options = ActivityOptionsCompat .makeScaleUpAnimation(view, view.getWidth() / 2, view.getHeight() / 2, 0, 0); ActivityCompat.startActivity((Activity) mContext, intent, options.toBundle()); } } @Override public int getLayoutId() { return R.layout.activity_news_detail; } @Override public void initPresenter() { mPresenter = new NewsDetailPresenterImpl(this); } @Override public void initView() { StatusBarSetting.setTranslucent(NewsDetailActivity.this); mContext = this; postId = getIntent().getStringExtra(AppConstant.NEWS_POST_ID); System.out.println(postId); mPresenter.requestDetailNews(postId); mToolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { finish(); } }); } @Override public void returnNewsDetail(NewsDetail detail) { System.out.println("返回的数据:"+detail); mShareLink = detail.getShareLink(); mNewsTitle = detail.getTitle(); String newsSource = detail.getSource(); String newsTime = TimeUtil.formatDate(detail.getPtime()); String newsBody = detail.getBody(); String NewsImgSrc = getImgSrcs(detail); setToolBarLayout(mNewsTitle); mNewsDetailFromTv.setText(getString(R.string.news_from, newsSource, newsTime)); setNewsDetailPhotoIv(NewsImgSrc); setNewsDetailBodyTv(detail, newsBody); } //设置新闻主体内容 private void setNewsDetailBodyTv(final NewsDetail detail, final String body) { Observable.timer(1, TimeUnit.MILLISECONDS) .compose(RetrofitClient.schedulersTransformer) .subscribe(new Observer() { @Override public void onSubscribe(Disposable d) { RxDisposeManager.get().add("newsBody",d); mProgressBar.setVisibility(View.GONE); } @Override public void onNext(Object o) { mProgressBar.setVisibility(View.VISIBLE); setBody(detail, body); } @Override public void onError(Throwable e) { mProgressBar.setVisibility(View.GONE); } @Override public void onComplete() { mProgressBar.setVisibility(View.GONE); } }); } private void setBody(NewsDetail detail, String body) { int imgTotal = detail.getImg().size(); if (isShowBody(body, imgTotal)) { mUrlImageGetter = new URLImageGetter(mNewsDetailBodyTv, body, imgTotal); mNewsDetailBodyTv.setText(Html.fromHtml(body, mUrlImageGetter, null)); } else { mNewsDetailBodyTv.setText(Html.fromHtml(body)); } } private boolean isShowBody(String body, int total) { return total >= 2 && body != null; } //加载图片 private void setNewsDetailPhotoIv(String src) { ImageLoaderUtils.displayBigPhoto(mContext,mNewsDetailPhotoIv,src); } //设置toolbar内容 private void setToolBarLayout(String title) { mToolbarLayout.setTitle(title); mToolbarLayout.setExpandedTitleColor(ContextCompat.getColor(this, R.color.white)); mToolbarLayout.setCollapsedTitleTextColor(ContextCompat.getColor(this, R.color.primary_text_white)); } //获取图片资源 private String getImgSrcs(NewsDetail newsDetail) { List imgSrcs = newsDetail.getImg(); String imgSrc; if (imgSrcs != null && imgSrcs.size() > 0) { imgSrc = imgSrcs.get(0).getSrc(); } else { imgSrc = getIntent().getStringExtra(AppConstant.NEWS_IMG_RES); } return imgSrc; } @Override protected void onDestroy() { super.onDestroy(); RxDisposeManager.get().cancel("newsBody"); RxDisposeManager.get().cancel("newsDetail"); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/activity/NewsPhotoDetailActivity.java ================================================ package com.lvr.livecircle.news.activity; import android.content.Context; import android.content.Intent; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import com.lvr.livecircle.R; import com.lvr.livecircle.adapter.CardAdapter; import com.lvr.livecircle.app.AppConstant; import com.lvr.livecircle.base.BaseActivity; import com.lvr.livecircle.news.model.bean.NewsPhotoDetail; import com.lvr.livecircle.recycleviewcardgallery.CardScaleHelper; import com.lvr.livecircle.recycleviewcardgallery.SpeedRecyclerView; import com.lvr.livecircle.utils.StatusBarSetting; import butterknife.BindView; /** * Created by lvr on 2017/2/11. */ public class NewsPhotoDetailActivity extends BaseActivity { @BindView(R.id.toolbar) Toolbar mToolbar; @BindView(R.id.blurView) ImageView mBlurView; @BindView(R.id.recyclerView) SpeedRecyclerView mRecyclerView; @BindView(R.id.photo_detail_title_tv) TextView mPhotoDetailTitleTv; private NewsPhotoDetail mNewsPhotoDetail; private CardScaleHelper mCardScaleHelper = null; private int mLastPos = -1; private Runnable mBlurRunnable; /** * 入口 * * @param context * @param mNewsPhotoDetail */ public static void startAction(Context context, NewsPhotoDetail mNewsPhotoDetail) { Intent intent = new Intent(context, NewsPhotoDetailActivity.class); intent.putExtra(AppConstant.PHOTO_DETAIL, mNewsPhotoDetail); context.startActivity(intent); } @Override public int getLayoutId() { return R.layout.activity_news_photo_detail; } @Override public void initPresenter() { } @Override public void initView() { StatusBarSetting.setColor(NewsPhotoDetailActivity.this,getResources().getColor(R.color.black)); mNewsPhotoDetail = getIntent().getParcelableExtra(AppConstant.PHOTO_DETAIL); System.out.println(mNewsPhotoDetail); mRecyclerView = (SpeedRecyclerView) findViewById(R.id.recyclerView); final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); mRecyclerView.setLayoutManager(linearLayoutManager); mRecyclerView.setAdapter(new CardAdapter(mContext,mNewsPhotoDetail.getPictures())); // mRecyclerView绑定scale效果 mCardScaleHelper = new CardScaleHelper(); mCardScaleHelper.setCurrentItemPos(0); mCardScaleHelper.attachToRecyclerView(mRecyclerView); String title = mNewsPhotoDetail.getPictures().get(0).getTitle()==null?"":mNewsPhotoDetail.getPictures().get(0).getTitle(); mPhotoDetailTitleTv.setText(1+"/"+mNewsPhotoDetail.getPictures().size()+" "+title); mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); int pos = mCardScaleHelper.getCurrentItemPos(); String title = mNewsPhotoDetail.getPictures().get(pos).getTitle() == null ? "" : mNewsPhotoDetail.getPictures().get(pos).getTitle(); if(mPhotoDetailTitleTv!=null){ mPhotoDetailTitleTv.setText(pos+1+"/"+mNewsPhotoDetail.getPictures().size()+" "+title); } } }); mToolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { finish(); } }); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/db/NewsChannelTableManager.java ================================================ /* * Copyright (c) 2016 咖枯 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.lvr.livecircle.news.db; import com.lvr.livecircle.R; import com.lvr.livecircle.api.ApiConstants; import com.lvr.livecircle.app.AppApplication; import com.lvr.livecircle.news.model.bean.NewsChannelTable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class NewsChannelTableManager { /** * 加载新闻类型 * * @return */ public static List loadNewsChannelsMore() { List channelName = Arrays.asList(AppApplication.getAppContext().getResources().getStringArray(R.array.news_channel_name)); List channelId = Arrays.asList(AppApplication.getAppContext().getResources().getStringArray(R.array.news_channel_id)); List channelImgRes = new ArrayList(); channelImgRes.add(R.drawable.news_house); channelImgRes.add(R.drawable.news_play); channelImgRes.add(R.drawable.news_movie); channelImgRes.add(R.drawable.news_car); channelImgRes.add(R.drawable.news_game); channelImgRes.add(R.drawable.news_education); channelImgRes.add(R.drawable.news_travel); channelImgRes.add(R.drawable.news_mobile); channelImgRes.add(R.drawable.news_social); ArrayList newsChannelTables = new ArrayList<>(); for (int i = 0; i < channelName.size(); i++) { NewsChannelTable entity = new NewsChannelTable(channelName.get(i), channelId.get(i) , ApiConstants.getType(channelId.get(i)), i <= 5, i, false, channelImgRes.get(i)); newsChannelTables.add(entity); } return newsChannelTables; } /** * 加载固定新闻类型 * * @return */ public static List loadNewsChannelsStatic() { List channelName = Arrays.asList(AppApplication.getAppContext().getResources().getStringArray(R.array.news_channel_name_static)); System.out.println(channelName); List channelId = Arrays.asList(AppApplication.getAppContext().getResources().getStringArray(R.array.news_channel_id_static)); List channelImgRes = new ArrayList(); channelImgRes.add(R.drawable.news_header); channelImgRes.add(R.drawable.news_tech); channelImgRes.add(R.drawable.news_fincial); channelImgRes.add(R.drawable.news_military); channelImgRes.add(R.drawable.news_sports); ArrayList newsChannelTables = new ArrayList<>(); for (int i = 0; i < channelName.size(); i++) { System.out.println(channelName.get(i)); System.out.println(channelId.get(i)); System.out.println(channelImgRes.get(i)); NewsChannelTable entity = new NewsChannelTable(channelName.get(i), channelId.get(i) , ApiConstants.getType(channelId.get(i)), i <= 5, i, i==0?true:false, channelImgRes.get(i)); newsChannelTables.add(entity); } return newsChannelTables; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/fragment/NewsFragment.java ================================================ package com.lvr.livecircle.news.fragment; import android.content.Context; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import com.lvr.livecircle.R; import com.lvr.livecircle.adapter.NewsListAdapter; import com.lvr.livecircle.adapter.OnNewsChannelListener; import com.lvr.livecircle.base.BaseFragment; import com.lvr.livecircle.bean.FabScrollBean; import com.lvr.livecircle.bean.HeaderBean; import com.lvr.livecircle.bean.NewsInfo; import com.lvr.livecircle.client.RxDisposeManager; import com.lvr.livecircle.news.model.bean.NewsChannelTable; import com.lvr.livecircle.news.presenter.impl.NewsPresenterImpl; import com.lvr.livecircle.news.view.NewsView; import com.lvr.livecircle.widget.LoadingTip; import java.util.ArrayList; import java.util.List; import butterknife.BindView; import de.greenrobot.event.EventBus; import de.greenrobot.event.Subscribe; /** * Created by lvr on 2017/2/6. */ public class NewsFragment extends BaseFragment implements NewsView, SwipeRefreshLayout.OnRefreshListener, OnNewsChannelListener { @BindView(R.id.recyclerView) RecyclerView mRecyclerView; @BindView(R.id.refreshLayout) SwipeRefreshLayout mRefreshLayout; @BindView(R.id.loadedTip) LoadingTip mLoadedTip; private NewsPresenterImpl mPresenter; private Context mContext; private List mTables = new ArrayList<>(); private List mInfos = new ArrayList<>(); private NewsListAdapter mNewsListAdapter; //当前加载新闻类型 private String cur_news_type = "headline"; //当前加载新闻类型的id private String cur_news_id = "T1348647909107"; //当前加载新闻页数 private int cur_news_page = 0; @Override protected int getLayoutResource() { return R.layout.fragment_news; } @Override protected void initView() { mContext = getActivity(); mPresenter = new NewsPresenterImpl(this); mRecyclerView.setHasFixedSize(true); mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); mRefreshLayout.setOnRefreshListener(this); //设置下拉刷新的按钮的颜色 mRefreshLayout.setColorSchemeResources(R.color.colorPrimary); setLoadMoreListener(); if (!EventBus.getDefault().isRegistered(this)) { EventBus.getDefault().register(this); } } @Override protected void onFragmentVisibleChange(boolean isVisible) { if (isVisible) { mPresenter.lodeMineChannelsRequest(); mPresenter.loadNewsListRequest(cur_news_type, cur_news_id, cur_news_page); }else{ RxDisposeManager.get().cancel("newschannel"); RxDisposeManager.get().cancel("newslist"); } } @Subscribe public void onFabScrollEvent(FabScrollBean event) { if(event.getPosition()==1){ mRecyclerView.smoothScrollToPosition(0); } } @Subscribe public void onHeaderEvent(HeaderBean event) { returnNewsChannel(event.getList()); } private void setLoadMoreListener() { mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { boolean isSlidingToLast = false; @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { LinearLayoutManager manager = (LinearLayoutManager) recyclerView.getLayoutManager(); // 当不滚动时 if (newState == RecyclerView.SCROLL_STATE_IDLE) { // 获取最后一个完全显示的item position int lastVisibleItem = manager.findLastCompletelyVisibleItemPosition(); int totalItemCount = manager.getItemCount(); // 判断是否滚动到底部并且是向下滑动 if (lastVisibleItem == (totalItemCount - 1) && isSlidingToLast) { cur_news_page += 20; System.out.println("加载页数:" + cur_news_page); mPresenter.loadNewsListRequest(cur_news_type, cur_news_id, cur_news_page); } } super.onScrollStateChanged(recyclerView, newState); } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); isSlidingToLast = dy > 0; } }); } @Override public void returnNewsChannel(List tables) { System.out.println(tables); System.out.println("频道个数:" + tables.size()); mTables.clear(); mTables.addAll(tables); addAllChannel(); if (mNewsListAdapter != null) { mNewsListAdapter.setTables(mTables); mNewsListAdapter.notifyItemChanged(0); } } @Override public void returnNewsList(List infos) { mInfos = infos; if (!isFirst) { isFirst = true; mNewsListAdapter = new NewsListAdapter(mContext, mInfos, mTables); mNewsListAdapter.setNewsChannelListener(this); mRecyclerView.setAdapter(mNewsListAdapter); } else if (cur_news_page == 0) { mRefreshLayout.setRefreshing(false); List data = mNewsListAdapter.getAdapterData(); data.clear(); data.addAll(infos); System.out.println("刷新后的数据:" + data.size()); mNewsListAdapter.notifyDataSetChanged(); } else if (cur_news_page > 0) { infos.remove(0); List data = mNewsListAdapter.getAdapterData(); data.addAll(infos); System.out.println("加载后的数据:" + data.size()); mNewsListAdapter.notifyDataSetChanged(); } } /** * 添加跳转到管理新闻频道的界面 */ private void addAllChannel() { if (mTables != null) { NewsChannelTable allChannel = new NewsChannelTable("全部", "", "", false, 0, true, R.drawable.news_all); mTables.add(allChannel); } } @Override public void showNetErrorTip() { super.showNetErrorTip(); mRefreshLayout.setRefreshing(false); mLoadedTip.setLoadingTip(LoadingTip.LoadStatus.error); } public void showLoading() { mLoadedTip.setLoadingTip(LoadingTip.LoadStatus.loading); } public void stopLoading() { mLoadedTip.setLoadingTip(LoadingTip.LoadStatus.finish); } @Override public void onRefresh() { cur_news_page = 0; mRefreshLayout.setRefreshing(true); mPresenter.loadNewsListRequest(cur_news_type, cur_news_id, cur_news_page); } @Override public void changeChannelListener(NewsChannelTable newsChannelTable) { String type = newsChannelTable.getNewsChannelType(); String id = newsChannelTable.getNewsChannelId(); cur_news_type = type; cur_news_id = id; cur_news_page = 0; System.out.println(cur_news_type); System.out.println(cur_news_id); mPresenter.loadNewsListRequest(cur_news_type, cur_news_id, cur_news_page); } @Override public void onDestroyView() { super.onDestroyView(); RxDisposeManager.get().cancel("newschannel"); RxDisposeManager.get().cancel("newslist"); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/model/NewsChannelModel.java ================================================ package com.lvr.livecircle.news.model; import com.lvr.livecircle.news.model.bean.NewsChannelTable; import java.util.ArrayList; import java.util.List; import io.reactivex.Observable; /** * Created by lvr on 2017/2/14. */ public interface NewsChannelModel { Observable> lodeMoreNewsChannels(); Observable swapDb(ArrayList newsChannelTableList); Observable updateDb(ArrayList mineChannelTableList, ArrayList moreChannelTableList); } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/model/NewsDetailModel.java ================================================ package com.lvr.livecircle.news.model; import com.lvr.livecircle.news.model.bean.NewsDetail; import io.reactivex.Observable; /** * Created by lvr on 2017/2/11. */ public interface NewsDetailModel { Observable getDetailNews(String postId); } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/model/NewsModel.java ================================================ package com.lvr.livecircle.news.model; import com.lvr.livecircle.bean.NewsInfo; import com.lvr.livecircle.news.model.bean.NewsChannelTable; import java.util.List; import io.reactivex.Observable; /** * Created by lvr on 2017/2/7. */ public interface NewsModel { Observable> requestNewsChannels(); Observable requestNewsList(String newsType, final String id, int startPage); } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/model/bean/NewsChannelTable.java ================================================ package com.lvr.livecircle.news.model.bean; import java.io.Serializable; public class NewsChannelTable implements Serializable { private String newsChannelName; private String newsChannelId; private String newsChannelType; private boolean newsChannelSelect; private int newsChannelIndex; private Boolean newsChannelFixed; private int ImgRes; public NewsChannelTable() { } public NewsChannelTable(String newsChannelName) { this.newsChannelName = newsChannelName; } public NewsChannelTable(String newsChannelName, String newsChannelId, String newsChannelType, boolean newsChannelSelect, int newsChannelIndex, Boolean newsChannelFixed,int imgRes) { this.ImgRes = imgRes; this.newsChannelName = newsChannelName; this.newsChannelId = newsChannelId; this.newsChannelType = newsChannelType; this.newsChannelSelect = newsChannelSelect; this.newsChannelIndex = newsChannelIndex; this.newsChannelFixed = newsChannelFixed; } public boolean isNewsChannelSelect() { return newsChannelSelect; } public void setImgRes(int imgRes) { ImgRes = imgRes; } public int getImgRes() { return ImgRes; } public String getNewsChannelName() { return newsChannelName; } public void setNewsChannelName(String newsChannelName) { this.newsChannelName = newsChannelName; } public String getNewsChannelId() { return newsChannelId; } public void setNewsChannelId(String newsChannelId) { this.newsChannelId = newsChannelId; } public String getNewsChannelType() { return newsChannelType; } public void setNewsChannelType(String newsChannelType) { this.newsChannelType = newsChannelType; } public boolean getNewsChannelSelect() { return newsChannelSelect; } public void setNewsChannelSelect(boolean newsChannelSelect) { this.newsChannelSelect = newsChannelSelect; } public int getNewsChannelIndex() { return newsChannelIndex; } public void setNewsChannelIndex(int newsChannelIndex) { this.newsChannelIndex = newsChannelIndex; } public Boolean getNewsChannelFixed() { return newsChannelFixed; } public void setNewsChannelFixed(Boolean newsChannelFixed) { this.newsChannelFixed = newsChannelFixed; } @Override public String toString() { return "NewsChannelTable{" + "newsChannelName='" + newsChannelName + '\'' + ", newsChannelId='" + newsChannelId + '\'' + ", newsChannelType='" + newsChannelType + '\'' + ", newsChannelSelect=" + newsChannelSelect + ", newsChannelIndex=" + newsChannelIndex + ", newsChannelFixed=" + newsChannelFixed + ", ImgRes=" + ImgRes + '}'; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/model/bean/NewsDetail.java ================================================ package com.lvr.livecircle.news.model.bean; import java.util.List; /** * Created by lvr on 2017/2/11. */ public class NewsDetail { /** * body :

  版权声明:本文版权为网易汽车所有,转载请注明出处。

  网易汽车9月13日报道近日,海外媒体曝光了一组本田新一代Freed的路试谍照,新车定位为MPV车型,基于飞度平台打造,将于今年9月内在日本发布。

  新车信息:

  ·新车基于飞度平台打造,同样采用了倾斜度较大的A柱加三角窗的设计,减少侧前方的盲区。较高的车顶和侧滑门的设计则凸显其MPV属性;

  ·内部采用平地板设计,无论是中控台下方还是后排地板均没有明显的突起,较高的平整度进一步提升空间利用率。同时,新车提供5座、6座以及7座三种座椅布局,满足不同消费者的需求;

  ·动力方面,新车将搭载1.5L汽油发动机和全新的SPORT HYBRID i-DCD油电混动系统,其中,油电混动车型将匹配7速双离合变速箱。

  点评:

  飞度本身就已经是“魔术空间”了,而基于飞度平台的Freed尺寸比飞度大不了多少却能得到比飞度大得多的空间,进一步提升实用性。只可惜目前并没有引入国内的计划。

  作者:沙墨瑀

* users : [] * ydbaike : [] * replyCount : 5651 * link : [] * img : [{"ref":"","pixel":"550*413","alt":"","src":"http://img4.cache.netease.com/auto/2016/9/6/20160906095943e0deb_550.jpg"},{"ref":"","pixel":"550*413","alt":"","src":"http://img1.cache.netease.com/auto/2016/9/6/20160906101623484a2_550.jpg"},{"ref":"","pixel":"550*413","alt":"","src":"http://img4.cache.netease.com/auto/2016/9/6/2016090610162781cd3_550.jpg"},{"ref":"","pixel":"550*243","alt":"","src":"http://img4.cache.netease.com/auto/2016/9/6/201609061016535ab4e_550.jpg"},{"ref":"","pixel":"550*413","alt":"","src":"http://img2.cache.netease.com/auto/2016/9/6/2016090610165690032_550.jpg"},{"ref":"","pixel":"550*246","alt":"","src":"http://img4.cache.netease.com/auto/2016/9/6/20160906101659aec96_550.jpg"}] * votes : [] * shareLink : https://c.m.163.com/news/a/C0Q6KKML00084TUO.html?spss=newsapp&spsw=1 * digest : 本田新一代Freed谍照曝光,基于飞度打造,空间更大。 * topiclist_news : [{"hasCover":false,"subnum":"超过1000万","alias":"Autos","tname":"汽车","ename":"qiche","tid":"T1348654060988","cid":"C1348652751993"}] * extraCard : {"title":"热车推荐","extraurl":"","list":[{"name":"雪铁龙C5","imgsrc":"http://img3.cache.netease.com/photo/0008/2014-08-25/300x225_A4GNKQRP29RB0008.png","digest":"直降5.6万↓","url":"http://auto.3g.163.com/citroen/2077/#khd002"},{"name":"名图","imgsrc":"http://img4.cache.netease.com/photo/0008/2016-07-26/300x225_BSTJ5R6I59TM0008.png","digest":"直降2.0万↓","url":"http://auto.3g.163.com/hyundai/17039/#khd002"},{"name":"全新英朗","imgsrc":"http://img3.cache.netease.com/photo/0008/2016-06-21/300x225_BQ3GFBRB3MQL0008.png","digest":"直降1.5万↓","url":"http://auto.3g.163.com/buick/10003/#khd002"}]} * dkeys : 本田,Freed,新车 * ec : 王海陆_NA1702 * topiclist : [{"hasCover":false,"subnum":"31.2万","alias":"未来汽车生活体验平台","tname":"网易汽车","ename":"wangyiqicheqiche","tid":"T1454656350893","cid":"C1374477981139"}] * docid : C0Q6KKML00084TUO * sourceinfo : {"alias":"未来汽车生活体验平台","ename":"wangyiqicheqiche","tname":"网易汽车","tid":"T1454656350893"} * picnews : true * title : 放大版的飞度 本田新一代Freed谍照曝光 * tid : * template : normal * threadVote : 13 * askbar : [{"title":"汽车媒体人 ","headpicurl":"http://dingyue.nosdn.127.net/6qrnKjR9P7VaWHw60hb8z52iUdJ4edQg4wE3XAm=Xqawu1471420744994.jpg","alias":"我是汽车媒体人张超,关于买车、换车、用车的相关问题,问我吧!","expertId":"EX1729495850059568996","name":"张超","concernCount":43570}] * threadAgainst : 10 * autoRecomends : [{"name":"雪铁龙C5","imgsrc":"http://img3.cache.netease.com/photo/0008/2014-08-25/300x225_A4GNKQRP29RB0008.png","chexi_id":"2077","youhui":5.6,"youhuinew":"直降5.6万↓","url":"http://auto.3g.163.com/citroen/2077/#khd002"},{"name":"名图","imgsrc":"http://img4.cache.netease.com/photo/0008/2016-07-26/300x225_BSTJ5R6I59TM0008.png","chexi_id":"17039","youhui":2,"youhuinew":"直降2.0万↓","url":"http://auto.3g.163.com/hyundai/17039/#khd002"},{"name":"全新英朗","imgsrc":"http://img3.cache.netease.com/photo/0008/2016-06-21/300x225_BQ3GFBRB3MQL0008.png","chexi_id":"10003","youhui":1.5,"youhuinew":"直降1.5万↓","url":"http://auto.3g.163.com/buick/10003/#khd002"}] * boboList : [] * replyBoard : auto_bbs * source : 网易汽车 * huati : [{"topicId":"SJ8240509424738212213","topicName":"本田"}] * hasNext : false * voicecomment : off * ptime : 2016-09-13 00:03:17 */ private String body; private int replyCount; private String shareLink; private String digest; private ExtraCardBean extraCard; private String dkeys; private String ec; private String docid; private SourceinfoBean sourceinfo; private boolean picnews; private String title; private String tid; private String template; private int threadVote; private int threadAgainst; private String replyBoard; private String source; private boolean hasNext; private String voicecomment; private String ptime; private List users; private List ydbaike; private List link; private List img; private List votes; private List topiclist_news; private List topiclist; private List askbar; private List autoRecomends; private List boboList; private List huati; public String getBody() { return body; } public void setBody(String body) { this.body = body; } public int getReplyCount() { return replyCount; } public void setReplyCount(int replyCount) { this.replyCount = replyCount; } public String getShareLink() { return shareLink; } public void setShareLink(String shareLink) { this.shareLink = shareLink; } public String getDigest() { return digest; } public void setDigest(String digest) { this.digest = digest; } public ExtraCardBean getExtraCard() { return extraCard; } public void setExtraCard(ExtraCardBean extraCard) { this.extraCard = extraCard; } public String getDkeys() { return dkeys; } public void setDkeys(String dkeys) { this.dkeys = dkeys; } public String getEc() { return ec; } public void setEc(String ec) { this.ec = ec; } public String getDocid() { return docid; } public void setDocid(String docid) { this.docid = docid; } public SourceinfoBean getSourceinfo() { return sourceinfo; } public void setSourceinfo(SourceinfoBean sourceinfo) { this.sourceinfo = sourceinfo; } public boolean isPicnews() { return picnews; } public void setPicnews(boolean picnews) { this.picnews = picnews; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getTid() { return tid; } public void setTid(String tid) { this.tid = tid; } public String getTemplate() { return template; } public void setTemplate(String template) { this.template = template; } public int getThreadVote() { return threadVote; } public void setThreadVote(int threadVote) { this.threadVote = threadVote; } public int getThreadAgainst() { return threadAgainst; } public void setThreadAgainst(int threadAgainst) { this.threadAgainst = threadAgainst; } public String getReplyBoard() { return replyBoard; } public void setReplyBoard(String replyBoard) { this.replyBoard = replyBoard; } public String getSource() { return source; } public void setSource(String source) { this.source = source; } public boolean isHasNext() { return hasNext; } public void setHasNext(boolean hasNext) { this.hasNext = hasNext; } public String getVoicecomment() { return voicecomment; } public void setVoicecomment(String voicecomment) { this.voicecomment = voicecomment; } public String getPtime() { return ptime; } public void setPtime(String ptime) { this.ptime = ptime; } public List getUsers() { return users; } public void setUsers(List users) { this.users = users; } public List getYdbaike() { return ydbaike; } public void setYdbaike(List ydbaike) { this.ydbaike = ydbaike; } public List getLink() { return link; } public void setLink(List link) { this.link = link; } public List getImg() { return img; } public void setImg(List img) { this.img = img; } public List getVotes() { return votes; } public void setVotes(List votes) { this.votes = votes; } public List getTopiclist_news() { return topiclist_news; } public void setTopiclist_news(List topiclist_news) { this.topiclist_news = topiclist_news; } public List getTopiclist() { return topiclist; } public void setTopiclist(List topiclist) { this.topiclist = topiclist; } public List getAskbar() { return askbar; } public void setAskbar(List askbar) { this.askbar = askbar; } public List getAutoRecomends() { return autoRecomends; } public void setAutoRecomends(List autoRecomends) { this.autoRecomends = autoRecomends; } public List getBoboList() { return boboList; } public void setBoboList(List boboList) { this.boboList = boboList; } public List getHuati() { return huati; } public void setHuati(List huati) { this.huati = huati; } public static class ExtraCardBean { @Override public String toString() { return "ExtraCardBean{" + "title='" + title + '\'' + ", extraurl='" + extraurl + '\'' + ", list=" + list + '}'; } /** * title : 热车推荐 * extraurl : * list : [{"name":"雪铁龙C5","imgsrc":"http://img3.cache.netease.com/photo/0008/2014-08-25/300x225_A4GNKQRP29RB0008.png","digest":"直降5.6万↓","url":"http://auto.3g.163.com/citroen/2077/#khd002"},{"name":"名图","imgsrc":"http://img4.cache.netease.com/photo/0008/2016-07-26/300x225_BSTJ5R6I59TM0008.png","digest":"直降2.0万↓","url":"http://auto.3g.163.com/hyundai/17039/#khd002"},{"name":"全新英朗","imgsrc":"http://img3.cache.netease.com/photo/0008/2016-06-21/300x225_BQ3GFBRB3MQL0008.png","digest":"直降1.5万↓","url":"http://auto.3g.163.com/buick/10003/#khd002"}] */ private String title; private String extraurl; private List list; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getExtraurl() { return extraurl; } public void setExtraurl(String extraurl) { this.extraurl = extraurl; } public List getList() { return list; } public void setList(List list) { this.list = list; } public static class ListBean { @Override public String toString() { return "ListBean{" + "name='" + name + '\'' + ", imgsrc='" + imgsrc + '\'' + ", digest='" + digest + '\'' + ", url='" + url + '\'' + '}'; } /** * name : 雪铁龙C5 * imgsrc : http://img3.cache.netease.com/photo/0008/2014-08-25/300x225_A4GNKQRP29RB0008.png * digest : 直降5.6万↓ * url : http://auto.3g.163.com/citroen/2077/#khd002 */ private String name; private String imgsrc; private String digest; private String url; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getImgsrc() { return imgsrc; } public void setImgsrc(String imgsrc) { this.imgsrc = imgsrc; } public String getDigest() { return digest; } public void setDigest(String digest) { this.digest = digest; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } } } public static class SourceinfoBean { @Override public String toString() { return "SourceinfoBean{" + "alias='" + alias + '\'' + ", ename='" + ename + '\'' + ", tname='" + tname + '\'' + ", tid='" + tid + '\'' + '}'; } /** * alias : 未来汽车生活体验平台 * ename : wangyiqicheqiche * tname : 网易汽车 * tid : T1454656350893 */ private String alias; private String ename; private String tname; private String tid; public String getAlias() { return alias; } public void setAlias(String alias) { this.alias = alias; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public String getTname() { return tname; } public void setTname(String tname) { this.tname = tname; } public String getTid() { return tid; } public void setTid(String tid) { this.tid = tid; } } public static class ImgBean { /** * ref : * pixel : 550*413 * alt : * src : http://img4.cache.netease.com/auto/2016/9/6/20160906095943e0deb_550.jpg */ private String ref; private String pixel; private String alt; private String src; public String getRef() { return ref; } public void setRef(String ref) { this.ref = ref; } public String getPixel() { return pixel; } public void setPixel(String pixel) { this.pixel = pixel; } public String getAlt() { return alt; } public void setAlt(String alt) { this.alt = alt; } public String getSrc() { return src; } public void setSrc(String src) { this.src = src; } } public static class TopiclistNewsBean { @Override public String toString() { return "TopiclistNewsBean{" + "hasCover=" + hasCover + ", subnum='" + subnum + '\'' + ", alias='" + alias + '\'' + ", tname='" + tname + '\'' + ", ename='" + ename + '\'' + ", tid='" + tid + '\'' + ", cid='" + cid + '\'' + '}'; } /** * hasCover : false * subnum : 超过1000万 * alias : Autos * tname : 汽车 * ename : qiche * tid : T1348654060988 * cid : C1348652751993 */ private boolean hasCover; private String subnum; private String alias; private String tname; private String ename; private String tid; private String cid; public boolean isHasCover() { return hasCover; } public void setHasCover(boolean hasCover) { this.hasCover = hasCover; } public String getSubnum() { return subnum; } public void setSubnum(String subnum) { this.subnum = subnum; } public String getAlias() { return alias; } public void setAlias(String alias) { this.alias = alias; } public String getTname() { return tname; } public void setTname(String tname) { this.tname = tname; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public String getTid() { return tid; } public void setTid(String tid) { this.tid = tid; } public String getCid() { return cid; } public void setCid(String cid) { this.cid = cid; } } public static class TopiclistBean { @Override public String toString() { return "TopiclistBean{" + "hasCover=" + hasCover + ", subnum='" + subnum + '\'' + ", alias='" + alias + '\'' + ", tname='" + tname + '\'' + ", ename='" + ename + '\'' + ", tid='" + tid + '\'' + ", cid='" + cid + '\'' + '}'; } /** * hasCover : false * subnum : 31.2万 * alias : 未来汽车生活体验平台 * tname : 网易汽车 * ename : wangyiqicheqiche * tid : T1454656350893 * cid : C1374477981139 */ private boolean hasCover; private String subnum; private String alias; private String tname; private String ename; private String tid; private String cid; public boolean isHasCover() { return hasCover; } public void setHasCover(boolean hasCover) { this.hasCover = hasCover; } public String getSubnum() { return subnum; } public void setSubnum(String subnum) { this.subnum = subnum; } public String getAlias() { return alias; } public void setAlias(String alias) { this.alias = alias; } public String getTname() { return tname; } public void setTname(String tname) { this.tname = tname; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public String getTid() { return tid; } public void setTid(String tid) { this.tid = tid; } public String getCid() { return cid; } public void setCid(String cid) { this.cid = cid; } } public static class AskbarBean { @Override public String toString() { return "AskbarBean{" + "title='" + title + '\'' + ", headpicurl='" + headpicurl + '\'' + ", alias='" + alias + '\'' + ", expertId='" + expertId + '\'' + ", name='" + name + '\'' + ", concernCount=" + concernCount + '}'; } /** * title : 汽车媒体人 * headpicurl : http://dingyue.nosdn.127.net/6qrnKjR9P7VaWHw60hb8z52iUdJ4edQg4wE3XAm=Xqawu1471420744994.jpg * alias : 我是汽车媒体人张超,关于买车、换车、用车的相关问题,问我吧! * expertId : EX1729495850059568996 * name : 张超 * concernCount : 43570 */ private String title; private String headpicurl; private String alias; private String expertId; private String name; private int concernCount; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getHeadpicurl() { return headpicurl; } public void setHeadpicurl(String headpicurl) { this.headpicurl = headpicurl; } public String getAlias() { return alias; } public void setAlias(String alias) { this.alias = alias; } public String getExpertId() { return expertId; } public void setExpertId(String expertId) { this.expertId = expertId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getConcernCount() { return concernCount; } public void setConcernCount(int concernCount) { this.concernCount = concernCount; } } public static class AutoRecomendsBean { @Override public String toString() { return "AutoRecomendsBean{" + "name='" + name + '\'' + ", imgsrc='" + imgsrc + '\'' + ", chexi_id='" + chexi_id + '\'' + ", youhui=" + youhui + ", youhuinew='" + youhuinew + '\'' + ", url='" + url + '\'' + '}'; } /** * name : 雪铁龙C5 * imgsrc : http://img3.cache.netease.com/photo/0008/2014-08-25/300x225_A4GNKQRP29RB0008.png * chexi_id : 2077 * youhui : 5.6 * youhuinew : 直降5.6万↓ * url : http://auto.3g.163.com/citroen/2077/#khd002 */ private String name; private String imgsrc; private String chexi_id; private double youhui; private String youhuinew; private String url; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getImgsrc() { return imgsrc; } public void setImgsrc(String imgsrc) { this.imgsrc = imgsrc; } public String getChexi_id() { return chexi_id; } public void setChexi_id(String chexi_id) { this.chexi_id = chexi_id; } public double getYouhui() { return youhui; } public void setYouhui(double youhui) { this.youhui = youhui; } public String getYouhuinew() { return youhuinew; } public void setYouhuinew(String youhuinew) { this.youhuinew = youhuinew; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } } public static class HuatiBean { /** * topicId : SJ8240509424738212213 * topicName : 本田 */ private String topicId; private String topicName; public String getTopicId() { return topicId; } public void setTopicId(String topicId) { this.topicId = topicId; } public String getTopicName() { return topicName; } public void setTopicName(String topicName) { this.topicName = topicName; } @Override public String toString() { return "HuatiBean{" + "topicId='" + topicId + '\'' + ", topicName='" + topicName + '\'' + '}'; } } @Override public String toString() { return "NewsDetail{" + "body='" + body + '\'' + ", replyCount=" + replyCount + ", shareLink='" + shareLink + '\'' + ", digest='" + digest + '\'' + ", extraCard=" + extraCard + ", dkeys='" + dkeys + '\'' + ", ec='" + ec + '\'' + ", docid='" + docid + '\'' + ", sourceinfo=" + sourceinfo + ", picnews=" + picnews + ", title='" + title + '\'' + ", tid='" + tid + '\'' + ", template='" + template + '\'' + ", threadVote=" + threadVote + ", threadAgainst=" + threadAgainst + ", replyBoard='" + replyBoard + '\'' + ", source='" + source + '\'' + ", hasNext=" + hasNext + ", voicecomment='" + voicecomment + '\'' + ", ptime='" + ptime + '\'' + ", users=" + users + ", ydbaike=" + ydbaike + ", link=" + link + ", img=" + img + ", votes=" + votes + ", topiclist_news=" + topiclist_news + ", topiclist=" + topiclist + ", askbar=" + askbar + ", autoRecomends=" + autoRecomends + ", boboList=" + boboList + ", huati=" + huati + '}'; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/model/bean/NewsPhotoDetail.java ================================================ package com.lvr.livecircle.news.model.bean; import android.os.Parcel; import android.os.Parcelable; import java.util.ArrayList; import java.util.List; /** * Created by lvr on 2017/2/11. */ public class NewsPhotoDetail implements Parcelable{ private String title; private List pictures; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public List getPictures() { return pictures; } public void setPictures(List pictures) { this.pictures = pictures; } public static class Picture implements Parcelable { private String title; public String getImgSrc() { return imgSrc; } public void setImgSrc(String imgSrc) { this.imgSrc = imgSrc; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } private String imgSrc; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.title); dest.writeString(this.imgSrc); } public Picture() { } protected Picture(Parcel in) { this.title = in.readString(); this.imgSrc = in.readString(); } public static final Creator CREATOR = new Creator() { @Override public Picture createFromParcel(Parcel source) { return new Picture(source); } @Override public Picture[] newArray(int size) { return new Picture[size]; } }; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.title); dest.writeList(this.pictures); } public NewsPhotoDetail() { } protected NewsPhotoDetail(Parcel in) { this.title = in.readString(); this.pictures = new ArrayList<>(); in.readList(this.pictures, Picture.class.getClassLoader()); } public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override public NewsPhotoDetail createFromParcel(Parcel source) { return new NewsPhotoDetail(source); } @Override public NewsPhotoDetail[] newArray(int size) { return new NewsPhotoDetail[size]; } }; @Override public String toString() { return "NewsPhotoDetail{" + "title='" + title + '\'' + ", pictures=" + pictures + '}'; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/model/impl/NewsChannelModelImpl.java ================================================ package com.lvr.livecircle.news.model.impl; import com.lvr.livecircle.app.AppApplication; import com.lvr.livecircle.app.AppConstant; import com.lvr.livecircle.client.RetrofitClient; import com.lvr.livecircle.news.db.NewsChannelTableManager; import com.lvr.livecircle.news.model.NewsChannelModel; import com.lvr.livecircle.news.model.bean.NewsChannelTable; import com.lvr.livecircle.utils.ACache; import java.util.ArrayList; import java.util.List; import io.reactivex.Observable; import io.reactivex.ObservableEmitter; import io.reactivex.ObservableOnSubscribe; /** * Created by lvr on 2017/2/14. */ public class NewsChannelModelImpl implements NewsChannelModel { @Override public Observable> lodeMoreNewsChannels() { return Observable.create(new ObservableOnSubscribe>() { @Override public void subscribe(ObservableEmitter> e) throws Exception { ArrayList newsChannelTableList = (ArrayList) ACache.get(AppApplication.getAppContext()).getAsObject(AppConstant.CHANNEL_MORE); if(newsChannelTableList==null){ newsChannelTableList = (ArrayList) NewsChannelTableManager.loadNewsChannelsMore(); ACache.get(AppApplication.getAppContext()).put(AppConstant.CHANNEL_MORE,newsChannelTableList); } e.onNext(newsChannelTableList); e.onComplete(); } }).compose(RetrofitClient.schedulersTransformer); } @Override public Observable swapDb(final ArrayList newsChannelTableList) { return Observable.create(new ObservableOnSubscribe() { @Override public void subscribe(ObservableEmitter e) throws Exception { //交换过的列表进行缓存 ACache.get(AppApplication.getAppContext()).put(AppConstant.CHANNEL_MINE,newsChannelTableList); e.onNext(""); e.onComplete(); } }).compose(RetrofitClient.schedulersTransformer); } @Override public Observable updateDb(final ArrayList mineChannelTableList, final ArrayList moreChannelTableList) { return Observable.create(new ObservableOnSubscribe() { @Override public void subscribe(ObservableEmitter e) throws Exception { ACache.get(AppApplication.getAppContext()).put(AppConstant.CHANNEL_MINE,mineChannelTableList); ACache.get(AppApplication.getAppContext()).put(AppConstant.CHANNEL_MORE,moreChannelTableList); e.onNext(""); e.onComplete(); } }).compose(RetrofitClient.schedulersTransformer); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/model/impl/NewsDetailModelImpl.java ================================================ package com.lvr.livecircle.news.model.impl; import com.lvr.livecircle.api.ApiService; import com.lvr.livecircle.app.AppApplication; import com.lvr.livecircle.client.RetrofitClient; import com.lvr.livecircle.news.model.NewsDetailModel; import com.lvr.livecircle.news.model.bean.NewsDetail; import java.util.List; import java.util.Map; import io.reactivex.Observable; import io.reactivex.functions.Function; /** * Created by lvr on 2017/2/11. */ public class NewsDetailModelImpl implements NewsDetailModel { @Override public Observable getDetailNews(final String postId) { RetrofitClient retrofitClient = RetrofitClient.getInstance(AppApplication.getAppContext(), ApiService.NEWS_BASE_URL); ApiService api = retrofitClient.create(ApiService.class); return api.getNewDetail(postId).map(new Function, Object>() { @Override public Object apply(Map map) throws Exception { NewsDetail newsDetail = map.get(postId); //把body中空的图片连接换成img中的 changeNewsDetail(newsDetail); return newsDetail; } }).compose(RetrofitClient.schedulersTransformer); } private void changeNewsDetail(NewsDetail newsDetail) { List imgSrcs = newsDetail.getImg(); if (isChange(imgSrcs)) { String newsBody = newsDetail.getBody(); newsBody = changeNewsBody(imgSrcs, newsBody); newsDetail.setBody(newsBody); } } private boolean isChange(List imgSrcs) { return imgSrcs != null && imgSrcs.size() >= 2; } private String changeNewsBody(List imgSrcs, String newsBody) { for (int i = 0; i < imgSrcs.size(); i++) { String oldChars = ""; String newChars; if (i == 0) { newChars = ""; } else { newChars = ""; } newsBody = newsBody.replace(oldChars, newChars); } return newsBody; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/model/impl/NewsModelImpl.java ================================================ package com.lvr.livecircle.news.model.impl; import com.lvr.livecircle.api.ApiConstants; import com.lvr.livecircle.api.ApiService; import com.lvr.livecircle.app.AppApplication; import com.lvr.livecircle.app.AppConstant; import com.lvr.livecircle.bean.NewsInfo; import com.lvr.livecircle.client.RetrofitClient; import com.lvr.livecircle.news.db.NewsChannelTableManager; import com.lvr.livecircle.news.model.NewsModel; import com.lvr.livecircle.news.model.bean.NewsChannelTable; import com.lvr.livecircle.utils.ACache; import com.lvr.livecircle.utils.TimeUtil; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Map; import io.reactivex.Observable; import io.reactivex.ObservableEmitter; import io.reactivex.ObservableOnSubscribe; import io.reactivex.ObservableSource; import io.reactivex.functions.Function; import io.reactivex.schedulers.Schedulers; /** * Created by lvr on 2017/2/7. */ public class NewsModelImpl implements NewsModel { @Override public Observable> requestNewsChannels() { return Observable.create(new ObservableOnSubscribe>() { @Override public void subscribe(ObservableEmitter> e) throws Exception { ArrayList newsChannelTableList = (ArrayList) ACache.get(AppApplication.getAppContext()).getAsObject(AppConstant.CHANNEL_MINE); if(newsChannelTableList==null){ newsChannelTableList= (ArrayList) NewsChannelTableManager.loadNewsChannelsStatic(); ACache.get(AppApplication.getAppContext()).put(AppConstant.CHANNEL_MINE,newsChannelTableList); } e.onNext(newsChannelTableList); e.onComplete(); } }).subscribeOn(Schedulers.io()); } @Override public Observable requestNewsList(String newsType, final String id, int startPage) { RetrofitClient retrofitClient = RetrofitClient.getInstance(AppApplication.getAppContext(), ApiService.NEWS_BASE_URL); ApiService api = retrofitClient.create(ApiService.class); return api.getNewsList(newsType,id,startPage).flatMap(new Function>, ObservableSource>() { @Override public ObservableSource apply(Map> map) throws Exception { //房产类型的信息 if (id.endsWith(ApiConstants.HOUSE_ID)) { return Observable.fromIterable(map.get("北京")); }else{ return Observable.fromIterable(map.get(id)); } } }).map(new Function() {//转换时间格式 @Override public NewsInfo apply(NewsInfo info) throws Exception { String ptime = TimeUtil.formatDate(info.getPtime()); info.setPtime(ptime); return info; } }).distinct().sorted(new Comparator() { @Override public int compare(NewsInfo info, NewsInfo t1) { return t1.getPtime().compareTo(info.getPtime()); } }).compose(RetrofitClient.schedulersTransformer);//线程调度 } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/presenter/NewPresenter.java ================================================ package com.lvr.livecircle.news.presenter; /** * Created by lvr on 2017/2/7. */ public interface NewPresenter { void lodeMineChannelsRequest(); void loadNewsListRequest(String newsType, final String id, int startPage); } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/presenter/NewsChannelPresenter.java ================================================ package com.lvr.livecircle.news.presenter; import com.lvr.livecircle.news.model.bean.NewsChannelTable; import java.util.ArrayList; /** * Created by lvr on 2017/2/14. */ public interface NewsChannelPresenter { void lodeChannelsRequest(); void onItemSwap(ArrayList newsChannelTableList); void onItemAddOrRemove(ArrayList mineChannelTableList, ArrayList moreChannelTableList); } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/presenter/NewsDetailPresenter.java ================================================ package com.lvr.livecircle.news.presenter; /** * Created by lvr on 2017/2/11. */ public interface NewsDetailPresenter { void requestDetailNews(String postId); } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/presenter/impl/NewsChannelPresenterImpl.java ================================================ package com.lvr.livecircle.news.presenter.impl; import com.lvr.livecircle.bean.HeaderBean; import com.lvr.livecircle.client.RxDisposeManager; import com.lvr.livecircle.news.activity.NewsChannelActivity; import com.lvr.livecircle.news.model.bean.NewsChannelTable; import com.lvr.livecircle.news.model.impl.NewsChannelModelImpl; import com.lvr.livecircle.news.model.impl.NewsModelImpl; import com.lvr.livecircle.news.presenter.NewsChannelPresenter; import java.util.ArrayList; import java.util.List; import de.greenrobot.event.EventBus; import io.reactivex.Observable; import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; /** * Created by lvr on 2017/2/14. */ public class NewsChannelPresenterImpl implements NewsChannelPresenter { private NewsChannelActivity mView; private NewsChannelModelImpl mModel; private NewsModelImpl mNewsModel; public NewsChannelPresenterImpl(NewsChannelActivity activity) { this.mView = activity; this.mModel = new NewsChannelModelImpl(); this.mNewsModel = new NewsModelImpl(); } @Override public void lodeChannelsRequest() { Observable> observable = mNewsModel.requestNewsChannels(); observable.observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer>() { @Override public void onSubscribe(Disposable d) { RxDisposeManager.get().add("newsMinechannel", d); } @Override public void onNext(List tables) { mView.returnMineNewsChannels(tables); } @Override public void onError(Throwable e) { } @Override public void onComplete() { } }); Observable> moreObservable = mModel.lodeMoreNewsChannels(); moreObservable.subscribe(new Observer>() { @Override public void onSubscribe(Disposable d) { RxDisposeManager.get().add("newsMorechannel", d); } @Override public void onNext(List tables) { mView.returnMoreNewsChannels(tables); } @Override public void onError(Throwable e) { } @Override public void onComplete() { } }); } @Override public void onItemSwap(final ArrayList newsChannelTableList) { mModel.swapDb(newsChannelTableList).subscribe(new Observer() { @Override public void onSubscribe(Disposable d) { EventBus.getDefault().post(new HeaderBean(newsChannelTableList)); } @Override public void onNext(String s) { } @Override public void onError(Throwable e) { } @Override public void onComplete() { } }); } @Override public void onItemAddOrRemove(final ArrayList mineChannelTableList, ArrayList moreChannelTableList) { mModel.updateDb(mineChannelTableList,moreChannelTableList).subscribe(new Observer() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(String s) { //发送消息 通知NewsFragment更改头布局信息 EventBus.getDefault().post(new HeaderBean(mineChannelTableList)); } @Override public void onError(Throwable e) { } @Override public void onComplete() { } }); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/presenter/impl/NewsDetailPresenterImpl.java ================================================ package com.lvr.livecircle.news.presenter.impl; import com.lvr.livecircle.client.RxDisposeManager; import com.lvr.livecircle.news.activity.NewsDetailActivity; import com.lvr.livecircle.news.model.bean.NewsDetail; import com.lvr.livecircle.news.model.impl.NewsDetailModelImpl; import com.lvr.livecircle.widget.LoadingDialog; import io.reactivex.Observable; import io.reactivex.Observer; import io.reactivex.disposables.Disposable; /** * Created by lvr on 2017/2/11. */ public class NewsDetailPresenterImpl implements com.lvr.livecircle.news.presenter.NewsDetailPresenter { private NewsDetailModelImpl mModel; private NewsDetailActivity mView; //是否开启了dialog private boolean showDialog; public NewsDetailPresenterImpl(NewsDetailActivity view) { mView = view; mModel = new NewsDetailModelImpl(); } @Override public void requestDetailNews(String postId) { Observable observable = mModel.getDetailNews(postId); observable.subscribe(new Observer() { @Override public void onSubscribe(Disposable d) { RxDisposeManager.get().add("newsDetail", d); if(!showDialog){ showDialog = true; LoadingDialog.showDialogForLoading(mView); } } @Override public void onNext(NewsDetail detail) { mView.returnNewsDetail(detail); } @Override public void onError(Throwable e) { if(showDialog){ showDialog = false; LoadingDialog.cancelDialogForLoading(); } mView.showNetErrorTip(); } @Override public void onComplete() { if(showDialog){ showDialog = false; LoadingDialog.cancelDialogForLoading(); } } }); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/presenter/impl/NewsPresenterImpl.java ================================================ package com.lvr.livecircle.news.presenter.impl; import com.lvr.livecircle.bean.HeaderBean; import com.lvr.livecircle.bean.NewsInfo; import com.lvr.livecircle.client.RxDisposeManager; import com.lvr.livecircle.news.fragment.NewsFragment; import com.lvr.livecircle.news.model.bean.NewsChannelTable; import com.lvr.livecircle.news.model.impl.NewsModelImpl; import com.lvr.livecircle.news.presenter.NewPresenter; import java.util.ArrayList; import java.util.List; import de.greenrobot.event.Subscribe; import io.reactivex.Observable; import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; /** * Created by lvr on 2017/2/11. */ public class NewsPresenterImpl implements NewPresenter { private NewsFragment mNewsView; private NewsModelImpl mNewsModel; private List mInfos; public NewsPresenterImpl(NewsFragment view) { this.mNewsView = view; this.mNewsModel = new NewsModelImpl(); } @Override public void lodeMineChannelsRequest() { Observable> observable = mNewsModel.requestNewsChannels(); observable.observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer>() { @Override public void onSubscribe(Disposable d) { RxDisposeManager.get().add("newschannel", d); } @Override public void onNext(List tables) { mNewsView.returnNewsChannel(tables); } @Override public void onError(Throwable e) { } @Override public void onComplete() { } }); } @Override public void loadNewsListRequest(String newsType, final String id, int startPage) { mInfos = new ArrayList<>(); NewsInfo newsInfo = new NewsInfo(); newsInfo.setTitle("头布局"); mInfos.add(newsInfo); Observable observable = mNewsModel.requestNewsList(newsType, id, startPage); observable.subscribe(new Observer() { @Override public void onSubscribe(Disposable d) { RxDisposeManager.get().add("newslist", d); mNewsView.showLoading(); } @Override public void onNext(NewsInfo info) { mInfos.add(info); } @Override public void onError(Throwable e) { System.out.println(e.getMessage()); System.out.println(e.getStackTrace()); mNewsView.showNetErrorTip(); } @Override public void onComplete() { mNewsView.stopLoading(); mNewsView.returnNewsList(mInfos); } }); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/view/NewsChannelView.java ================================================ package com.lvr.livecircle.news.view; import com.lvr.livecircle.news.model.bean.NewsChannelTable; import java.util.List; /** * Created by lvr on 2017/2/14. */ public interface NewsChannelView { void returnMineNewsChannels(List newsChannelsMine); void returnMoreNewsChannels(List newsChannelsMore); } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/view/NewsDetailView.java ================================================ package com.lvr.livecircle.news.view; import com.lvr.livecircle.news.model.bean.NewsDetail; /** * Created by lvr on 2017/2/11. */ public interface NewsDetailView { void returnNewsDetail(NewsDetail detail); } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/news/view/NewsView.java ================================================ package com.lvr.livecircle.news.view; import com.lvr.livecircle.bean.NewsInfo; import com.lvr.livecircle.news.model.bean.NewsChannelTable; import java.util.List; /** * Created by lvr on 2017/2/7. */ public interface NewsView { void returnNewsChannel(List tables); void returnNewsList(List info); } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/recommend/RecommendFragment.java ================================================ package com.lvr.livecircle.recommend; import com.lvr.livecircle.R; import com.lvr.livecircle.base.BaseFragment; /** * Created by lvr on 2017/2/6. */ public class RecommendFragment extends BaseFragment { @Override protected int getLayoutResource() { return R.layout.fragment_recommend; } @Override protected void initView() { } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/recycleviewcardgallery/CardAdapterHelper.java ================================================ package com.lvr.livecircle.recycleviewcardgallery; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; import com.lvr.livecircle.utils.DisplayUtil; /** * adapter中调用onCreateViewHolder, onBindViewHolder * Created by jameson on 9/1/16. */ public class CardAdapterHelper { private int mPagePadding = 15; private int mShowLeftCardWidth = 15; public void onCreateViewHolder(ViewGroup parent, View itemView) { RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) itemView.getLayoutParams(); lp.width = parent.getWidth() - DisplayUtil.dip2px( 2 * (mPagePadding + mShowLeftCardWidth)); itemView.setLayoutParams(lp); } public void onBindViewHolder(View itemView, final int position, int itemCount) { int padding = DisplayUtil.dip2px(mPagePadding); itemView.setPadding(padding, 0, padding, 0); int leftMarin = position == 0 ? padding + DisplayUtil.dip2px( mShowLeftCardWidth) : 0; int rightMarin = position == itemCount - 1 ? padding + DisplayUtil.dip2px(mShowLeftCardWidth) : 0; setViewMargin(itemView, leftMarin, 0, rightMarin, 0); } private void setViewMargin(View view, int left, int top, int right, int bottom) { ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams(); if (lp.leftMargin != left || lp.topMargin != top || lp.rightMargin != right || lp.bottomMargin != bottom) { lp.setMargins(left, top, right, bottom); view.setLayoutParams(lp); } } public void setPagePadding(int pagePadding) { mPagePadding = pagePadding; } public void setShowLeftCardWidth(int showLeftCardWidth) { mShowLeftCardWidth = showLeftCardWidth; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/recycleviewcardgallery/CardLinearSnapHelper.java ================================================ package com.lvr.livecircle.recycleviewcardgallery; import android.support.annotation.NonNull; import android.support.v7.widget.LinearSnapHelper; import android.support.v7.widget.RecyclerView; import android.view.View; /** * 防止卡片在第一页和最后一页因无法"居中"而一直循环调用onScrollStateChanged-->SnapHelper.snapToTargetExistingView-->onScrollStateChanged * Created by jameson on 9/3/16. */ public class CardLinearSnapHelper extends LinearSnapHelper { public boolean mNoNeedToScroll = false; @Override public int[] calculateDistanceToFinalSnap(@NonNull RecyclerView.LayoutManager layoutManager, @NonNull View targetView) { if (mNoNeedToScroll) { return new int[]{0, 0}; } else { return super.calculateDistanceToFinalSnap(layoutManager, targetView); } } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/recycleviewcardgallery/CardScaleHelper.java ================================================ package com.lvr.livecircle.recycleviewcardgallery; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.View; import com.lvr.livecircle.utils.DisplayUtil; /** * Created by jameson on 8/30/16. */ public class CardScaleHelper { private RecyclerView mRecyclerView; private Context mContext; private float mScale = 0.9f; // 两边视图scale private int mPagePadding = 15; // 卡片的padding, 卡片间的距离等于2倍的mPagePadding private int mShowLeftCardWidth = 15; // 左边卡片显示大小 private int mCardWidth; // 卡片宽度 private int mOnePageWidth; // 滑动一页的距离 private int mCardGalleryWidth; private int mCurrentItemPos; private int mCurrentItemOffset; private CardLinearSnapHelper mLinearSnapHelper = new CardLinearSnapHelper(); public void attachToRecyclerView(final RecyclerView mRecyclerView) { this.mRecyclerView = mRecyclerView; mContext = mRecyclerView.getContext(); mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (newState == RecyclerView.SCROLL_STATE_IDLE) { mLinearSnapHelper.mNoNeedToScroll = mCurrentItemOffset == 0 || mCurrentItemOffset == getDestItemOffset(mRecyclerView.getAdapter().getItemCount() - 1); } else { mLinearSnapHelper.mNoNeedToScroll = false; } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); // dx>0则表示右滑, dx<0表示左滑, dy<0表示上滑, dy>0表示下滑 mCurrentItemOffset += dx; computeCurrentItemPos(); onScrolledChangedCallback(); } }); initWidth(); mLinearSnapHelper.attachToRecyclerView(mRecyclerView); } /** * 初始化卡片宽度 */ private void initWidth() { mRecyclerView.post(new Runnable() { @Override public void run() { mCardGalleryWidth = mRecyclerView.getWidth(); mCardWidth = mCardGalleryWidth - DisplayUtil.dip2px(2 * (mPagePadding + mShowLeftCardWidth)); mOnePageWidth = mCardWidth; mRecyclerView.smoothScrollToPosition(mCurrentItemPos); onScrolledChangedCallback(); } }); } public void setCurrentItemPos(int currentItemPos) { this.mCurrentItemPos = currentItemPos; } public int getCurrentItemPos() { return mCurrentItemPos; } private int getDestItemOffset(int destPos) { return mOnePageWidth * destPos; } /** * 计算mCurrentItemOffset */ private void computeCurrentItemPos() { if (mOnePageWidth <= 0) return; boolean pageChanged = false; // 滑动超过一页说明已翻页 if (Math.abs(mCurrentItemOffset - mCurrentItemPos * mOnePageWidth) >= mOnePageWidth) { pageChanged = true; } if (pageChanged) { int tempPos = mCurrentItemPos; mCurrentItemPos = mCurrentItemOffset / mOnePageWidth; } } /** * RecyclerView位移事件监听, view大小随位移事件变化 */ private void onScrolledChangedCallback() { int offset = mCurrentItemOffset - mCurrentItemPos * mOnePageWidth; float percent = (float) Math.max(Math.abs(offset) * 1.0 / mOnePageWidth, 0.0001); View leftView = null; View currentView; View rightView = null; if (mCurrentItemPos > 0) { leftView = mRecyclerView.getLayoutManager().findViewByPosition(mCurrentItemPos - 1); } currentView = mRecyclerView.getLayoutManager().findViewByPosition(mCurrentItemPos); if (mCurrentItemPos < mRecyclerView.getAdapter().getItemCount() - 1) { rightView = mRecyclerView.getLayoutManager().findViewByPosition(mCurrentItemPos + 1); } if (leftView != null) { // y = (1 - mScale)x + mScale leftView.setScaleY((1 - mScale) * percent + mScale); } if (currentView != null) { // y = (mScale - 1)x + 1 currentView.setScaleY((mScale - 1) * percent + 1); } if (rightView != null) { // y = (1 - mScale)x + mScale rightView.setScaleY((1 - mScale) * percent + mScale); } } public void setScale(float scale) { mScale = scale; } public void setPagePadding(int pagePadding) { mPagePadding = pagePadding; } public void setShowLeftCardWidth(int showLeftCardWidth) { mShowLeftCardWidth = showLeftCardWidth; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/recycleviewcardgallery/SpeedRecyclerView.java ================================================ package com.lvr.livecircle.recycleviewcardgallery; import android.content.Context; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; /** * 控制fling速度的RecyclerView * * Created by jameson on 9/1/16. */ public class SpeedRecyclerView extends RecyclerView { private static final float FLING_SCALE_DOWN_FACTOR = 0.5f; // 减速因子 private static final int FLING_MAX_VELOCITY = 8000; // 最大顺时滑动速度 public SpeedRecyclerView(Context context) { super(context); } public SpeedRecyclerView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public SpeedRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean fling(int velocityX, int velocityY) { velocityX = solveVelocity(velocityX); velocityY = solveVelocity(velocityY); return super.fling(velocityX, velocityY); } private int solveVelocity(int velocity) { if (velocity > 0) { return Math.min(velocity, FLING_MAX_VELOCITY); } else { return Math.max(velocity, -FLING_MAX_VELOCITY); } } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/utils/ACache.java ================================================ package com.lvr.livecircle.utils; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.PixelFormat; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import org.json.JSONArray; import org.json.JSONObject; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.RandomAccessFile; import java.io.Serializable; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; /** * 本地文件缓存工具类 */ /********************使用例子********************/ /* 支持对象、数组、json、字符串(对象要序列化Serializable) ACache.get(AppApplication.getAppContext()).put(AppConstant.CHANNEL_MINE,mineChannelTableList); ACache.get(AppApplication.getAppContext()).get(AppConstant.CHANNEL_MINE); */ public class ACache { public static final int TIME_HOUR = 60 * 60; public static final int TIME_DAY = TIME_HOUR * 24; private static final int MAX_SIZE = 1000 * 1000 * 50; // 50 mb private static final int MAX_COUNT = Integer.MAX_VALUE; // 不限制存放数据的数量 private static Map mInstanceMap = new HashMap(); private ACacheManager mCache; public static ACache get(Context ctx) { return get(ctx, "ACache"); } public static ACache get(Context ctx, String cacheName) { File f = new File(ctx.getCacheDir(), cacheName); return get(f, MAX_SIZE, MAX_COUNT); } public static ACache get(File cacheDir) { return get(cacheDir, MAX_SIZE, MAX_COUNT); } public static ACache get(Context ctx, long max_zise, int max_count) { File f = new File(ctx.getCacheDir(), "ACache"); return get(f, max_zise, max_count); } public static ACache get(File cacheDir, long max_zise, int max_count) { ACache manager = mInstanceMap.get(cacheDir.getAbsoluteFile() + myPid()); if (manager == null) { manager = new ACache(cacheDir, max_zise, max_count); mInstanceMap.put(cacheDir.getAbsolutePath() + myPid(), manager); } return manager; } private static String myPid() { return "_" + android.os.Process.myPid(); } private ACache(File cacheDir, long max_size, int max_count) { if (!cacheDir.exists() && !cacheDir.mkdirs()) { throw new RuntimeException("can't make dirs in " + cacheDir.getAbsolutePath()); } mCache = new ACacheManager(cacheDir, max_size, max_count); } // ======================================= // ============ String数据 读写 ============== // ======================================= /** * 保存 String数据 到 缓存中 * * @param key * 保存的key * @param value * 保存的String数据 */ public void put(String key, String value) { File file = mCache.newFile(key); BufferedWriter out = null; try { out = new BufferedWriter(new FileWriter(file), 1024); out.write(value); } catch (IOException e) { e.printStackTrace(); } finally { if (out != null) { try { out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } } mCache.put(file); } } /** * 保存 String数据 到 缓存中 * * @param key * 保存的key * @param value * 保存的String数据 * @param saveTime * 保存的时间,单位:秒 */ public void put(String key, String value, int saveTime) { put(key, Utils.newStringWithDateInfo(saveTime, value)); } /** * 读取 String数据 * * @param key * @return String 数据 */ public String getAsString(String key) { File file = mCache.get(key); if (!file.exists()) return null; boolean removeFile = false; BufferedReader in = null; try { in = new BufferedReader(new FileReader(file)); String readString = ""; String currentLine; while ((currentLine = in.readLine()) != null) { readString += currentLine; } if (!Utils.isDue(readString)) { return Utils.clearDateInfo(readString); } else { removeFile = true; return null; } } catch (IOException e) { e.printStackTrace(); return null; } finally { if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if (removeFile) remove(key); } } // ======================================= // ============= JSONObject 数据 读写 ============== // ======================================= /** * 保存 JSONObject数据 到 缓存中 * * @param key * 保存的key * @param value * 保存的JSON数据 */ public void put(String key, JSONObject value) { put(key, value.toString()); } /** * 保存 JSONObject数据 到 缓存中 * * @param key * 保存的key * @param value * 保存的JSONObject数据 * @param saveTime * 保存的时间,单位:秒 */ public void put(String key, JSONObject value, int saveTime) { put(key, value.toString(), saveTime); } /** * 读取JSONObject数据 * * @param key * @return JSONObject数据 */ public JSONObject getAsJSONObject(String key) { String JSONString = getAsString(key); try { JSONObject obj = new JSONObject(JSONString); return obj; } catch (Exception e) { e.printStackTrace(); return null; } } // ======================================= // ============ JSONArray 数据 读写 ============= // ======================================= /** * 保存 JSONArray数据 到 缓存中 * * @param key * 保存的key * @param value * 保存的JSONArray数据 */ public void put(String key, JSONArray value) { put(key, value.toString()); } /** * 保存 JSONArray数据 到 缓存中 * * @param key * 保存的key * @param value * 保存的JSONArray数据 * @param saveTime * 保存的时间,单位:秒 */ public void put(String key, JSONArray value, int saveTime) { put(key, value.toString(), saveTime); } /** * 读取JSONArray数据 * * @param key * @return JSONArray数据 */ public JSONArray getAsJSONArray(String key) { String JSONString = getAsString(key); try { JSONArray obj = new JSONArray(JSONString); return obj; } catch (Exception e) { e.printStackTrace(); return null; } } // ======================================= // ============== byte 数据 读写 ============= // ======================================= /** * 保存 byte数据 到 缓存中 * * @param key * 保存的key * @param value * 保存的数据 */ public void put(String key, byte[] value) { File file = mCache.newFile(key); FileOutputStream out = null; try { out = new FileOutputStream(file); out.write(value); } catch (Exception e) { e.printStackTrace(); } finally { if (out != null) { try { out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } } mCache.put(file); } } /** * 保存 byte数据 到 缓存中 * * @param key * 保存的key * @param value * 保存的数据 * @param saveTime * 保存的时间,单位:秒 */ public void put(String key, byte[] value, int saveTime) { put(key, Utils.newByteArrayWithDateInfo(saveTime, value)); } /** * 获取 byte 数据 * * @param key * @return byte 数据 */ public byte[] getAsBinary(String key) { RandomAccessFile RAFile = null; boolean removeFile = false; try { File file = mCache.get(key); if (!file.exists()) return null; RAFile = new RandomAccessFile(file, "r"); byte[] byteArray = new byte[(int) RAFile.length()]; RAFile.read(byteArray); if (!Utils.isDue(byteArray)) { return Utils.clearDateInfo(byteArray); } else { removeFile = true; return null; } } catch (Exception e) { e.printStackTrace(); return null; } finally { if (RAFile != null) { try { RAFile.close(); } catch (IOException e) { e.printStackTrace(); } } if (removeFile) remove(key); } } // ======================================= // ============= 序列化 数据 读写 =============== // ======================================= /** * 保存 Serializable数据 到 缓存中 * * @param key * 保存的key * @param value * 保存的value */ public void put(String key, Serializable value) { put(key, value, -1); } /** * 保存 Serializable数据到 缓存中 * * @param key * 保存的key * @param value * 保存的value * @param saveTime * 保存的时间,单位:秒 */ public void put(String key, Serializable value, int saveTime) { ByteArrayOutputStream baos = null; ObjectOutputStream oos = null; try { baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(baos); oos.writeObject(value); byte[] data = baos.toByteArray(); if (saveTime != -1) { put(key, data, saveTime); } else { put(key, data); } } catch (Exception e) { e.printStackTrace(); } finally { try { oos.close(); } catch (IOException e) { } } } /** * 读取 Serializable数据 * * @param key * @return Serializable 数据 */ public Object getAsObject(String key) { byte[] data = getAsBinary(key); if (data != null) { ByteArrayInputStream bais = null; ObjectInputStream ois = null; try { bais = new ByteArrayInputStream(data); ois = new ObjectInputStream(bais); Object reObject = ois.readObject(); return reObject; } catch (Exception e) { e.printStackTrace(); return null; } finally { try { if (bais != null) bais.close(); } catch (IOException e) { e.printStackTrace(); } try { if (ois != null) ois.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } // ======================================= // ============== bitmap 数据 读写 ============= // ======================================= /** * 保存 bitmap 到 缓存中 * * @param key * 保存的key * @param value * 保存的bitmap数据 */ public void put(String key, Bitmap value) { put(key, Utils.Bitmap2Bytes(value)); } /** * 保存 bitmap 到 缓存中 * * @param key * 保存的key * @param value * 保存的 bitmap 数据 * @param saveTime * 保存的时间,单位:秒 */ public void put(String key, Bitmap value, int saveTime) { put(key, Utils.Bitmap2Bytes(value), saveTime); } /** * 读取 bitmap 数据 * * @param key * @return bitmap 数据 */ public Bitmap getAsBitmap(String key) { if (getAsBinary(key) == null) { return null; } return Utils.Bytes2Bimap(getAsBinary(key)); } // ======================================= // ============= drawable 数据 读写 ============= // ======================================= /** * 保存 drawable 到 缓存中 * * @param key * 保存的key * @param value * 保存的drawable数据 */ public void put(String key, Drawable value) { put(key, Utils.drawable2Bitmap(value)); } /** * 保存 drawable 到 缓存中 * * @param key * 保存的key * @param value * 保存的 drawable 数据 * @param saveTime * 保存的时间,单位:秒 */ public void put(String key, Drawable value, int saveTime) { put(key, Utils.drawable2Bitmap(value), saveTime); } /** * 读取 Drawable 数据 * * @param key * @return Drawable 数据 */ public Drawable getAsDrawable(String key) { if (getAsBinary(key) == null) { return null; } return Utils.bitmap2Drawable(Utils.Bytes2Bimap(getAsBinary(key))); } /** * 获取缓存文件 * * @param key * @return value 缓存的文件 */ public File file(String key) { File f = mCache.newFile(key); if (f.exists()) return f; return null; } /** * 移除某个key * * @param key * @return 是否移除成功 */ public boolean remove(String key) { return mCache.remove(key); } /** * 清除所有数据 */ public void clear() { mCache.clear(); } /** * @title 缓存管理器 * @author 杨福海(michael) www.yangfuhai.com * @version 1.0 */ public class ACacheManager { private final AtomicLong cacheSize; private final AtomicInteger cacheCount; private final long sizeLimit; private final int countLimit; private final Map lastUsageDates = Collections .synchronizedMap(new HashMap()); protected File cacheDir; private ACacheManager(File cacheDir, long sizeLimit, int countLimit) { this.cacheDir = cacheDir; this.sizeLimit = sizeLimit; this.countLimit = countLimit; cacheSize = new AtomicLong(); cacheCount = new AtomicInteger(); calculateCacheSizeAndCacheCount(); } /** * 计算 cacheSize和cacheCount */ private void calculateCacheSizeAndCacheCount() { new Thread(new Runnable() { @Override public void run() { int size = 0; int count = 0; File[] cachedFiles = cacheDir.listFiles(); if (cachedFiles != null) { for (File cachedFile : cachedFiles) { size += calculateSize(cachedFile); count += 1; lastUsageDates.put(cachedFile, cachedFile.lastModified()); } cacheSize.set(size); cacheCount.set(count); } } }).start(); } private void put(File file) { int curCacheCount = cacheCount.get(); while (curCacheCount + 1 > countLimit) { long freedSize = removeNext(); cacheSize.addAndGet(-freedSize); curCacheCount = cacheCount.addAndGet(-1); } cacheCount.addAndGet(1); long valueSize = calculateSize(file); long curCacheSize = cacheSize.get(); while (curCacheSize + valueSize > sizeLimit) { long freedSize = removeNext(); curCacheSize = cacheSize.addAndGet(-freedSize); } cacheSize.addAndGet(valueSize); Long currentTime = System.currentTimeMillis(); file.setLastModified(currentTime); lastUsageDates.put(file, currentTime); } private File get(String key) { File file = newFile(key); Long currentTime = System.currentTimeMillis(); file.setLastModified(currentTime); lastUsageDates.put(file, currentTime); return file; } private File newFile(String key) { return new File(cacheDir, key.hashCode() + ""); } private boolean remove(String key) { File image = get(key); return image.delete(); } private void clear() { lastUsageDates.clear(); cacheSize.set(0); File[] files = cacheDir.listFiles(); if (files != null) { for (File f : files) { f.delete(); } } } /** * 移除旧的文件 * * @return */ private long removeNext() { if (lastUsageDates.isEmpty()) { return 0; } Long oldestUsage = null; File mostLongUsedFile = null; Set> entries = lastUsageDates.entrySet(); synchronized (lastUsageDates) { for (Entry entry : entries) { if (mostLongUsedFile == null) { mostLongUsedFile = entry.getKey(); oldestUsage = entry.getValue(); } else { Long lastValueUsage = entry.getValue(); if (lastValueUsage < oldestUsage) { oldestUsage = lastValueUsage; mostLongUsedFile = entry.getKey(); } } } } long fileSize = calculateSize(mostLongUsedFile); if (mostLongUsedFile.delete()) { lastUsageDates.remove(mostLongUsedFile); } return fileSize; } private long calculateSize(File file) { return file.length(); } } /** * @title 时间计算工具类 * @author 杨福海(michael) www.yangfuhai.com * @version 1.0 */ private static class Utils { /** * 判断缓存的String数据是否到期 * * @param str * @return true:到期了 false:还没有到期 */ private static boolean isDue(String str) { return isDue(str.getBytes()); } /** * 判断缓存的byte数据是否到期 * * @param data * @return true:到期了 false:还没有到期 */ private static boolean isDue(byte[] data) { String[] strs = getDateInfoFromDate(data); if (strs != null && strs.length == 2) { String saveTimeStr = strs[0]; while (saveTimeStr.startsWith("0")) { saveTimeStr = saveTimeStr .substring(1, saveTimeStr.length()); } long saveTime = Long.valueOf(saveTimeStr); long deleteAfter = Long.valueOf(strs[1]); if (System.currentTimeMillis() > saveTime + deleteAfter * 1000) { return true; } } return false; } private static String newStringWithDateInfo(int second, String strInfo) { return createDateInfo(second) + strInfo; } private static byte[] newByteArrayWithDateInfo(int second, byte[] data2) { byte[] data1 = createDateInfo(second).getBytes(); byte[] retdata = new byte[data1.length + data2.length]; System.arraycopy(data1, 0, retdata, 0, data1.length); System.arraycopy(data2, 0, retdata, data1.length, data2.length); return retdata; } private static String clearDateInfo(String strInfo) { if (strInfo != null && hasDateInfo(strInfo.getBytes())) { strInfo = strInfo.substring(strInfo.indexOf(mSeparator) + 1, strInfo.length()); } return strInfo; } private static byte[] clearDateInfo(byte[] data) { if (hasDateInfo(data)) { return copyOfRange(data, indexOf(data, mSeparator) + 1, data.length); } return data; } private static boolean hasDateInfo(byte[] data) { return data != null && data.length > 15 && data[13] == '-' && indexOf(data, mSeparator) > 14; } private static String[] getDateInfoFromDate(byte[] data) { if (hasDateInfo(data)) { String saveDate = new String(copyOfRange(data, 0, 13)); String deleteAfter = new String(copyOfRange(data, 14, indexOf(data, mSeparator))); return new String[]{saveDate, deleteAfter}; } return null; } private static int indexOf(byte[] data, char c) { for (int i = 0; i < data.length; i++) { if (data[i] == c) { return i; } } return -1; } private static byte[] copyOfRange(byte[] original, int from, int to) { int newLength = to - from; if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); byte[] copy = new byte[newLength]; System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength)); return copy; } private static final char mSeparator = ' '; private static String createDateInfo(int second) { String currentTime = System.currentTimeMillis() + ""; while (currentTime.length() < 13) { currentTime = "0" + currentTime; } return currentTime + "-" + second + mSeparator; } /* * Bitmap → byte[] */ private static byte[] Bitmap2Bytes(Bitmap bm) { if (bm == null) { return null; } ByteArrayOutputStream baos = new ByteArrayOutputStream(); bm.compress(Bitmap.CompressFormat.PNG, 100, baos); return baos.toByteArray(); } /* * byte[] → Bitmap */ private static Bitmap Bytes2Bimap(byte[] b) { if (b.length == 0) { return null; } return BitmapFactory.decodeByteArray(b, 0, b.length); } /* * Drawable → Bitmap */ private static Bitmap drawable2Bitmap(Drawable drawable) { if (drawable == null) { return null; } // 取 drawable 的长宽 int w = drawable.getIntrinsicWidth(); int h = drawable.getIntrinsicHeight(); // 取 drawable 的颜色格式 Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; // 建立对应 bitmap Bitmap bitmap = Bitmap.createBitmap(w, h, config); // 建立对应 bitmap 的画布 Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, w, h); // 把 drawable 内容画到画布中 drawable.draw(canvas); return bitmap; } /* * Bitmap → Drawable */ @SuppressWarnings("deprecation") private static Drawable bitmap2Drawable(Bitmap bm) { if (bm == null) { return null; } return new BitmapDrawable(bm); } } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/utils/CollectionUtils.java ================================================ package com.lvr.livecircle.utils; import java.util.Collection; /** * 集合操作工具类 * */ public class CollectionUtils { /** * 判断集合是否为null或者0个元素 * * @param c * @return */ public static boolean isNullOrEmpty(Collection c) { if (null == c || c.isEmpty()) { return true; } return false; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/utils/DisplayUtil.java ================================================ package com.lvr.livecircle.utils; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Rect; import android.util.DisplayMetrics; import android.view.View; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.WindowManager; import android.widget.LinearLayout; import com.lvr.livecircle.app.AppApplication; /** * 屏幕相关的辅助类 */ public class DisplayUtil { private DisplayUtil() { /* cannot be instantiated */ throw new UnsupportedOperationException("cannot be instantiated"); } /** * 将px值转换为dip或dp值,保证尺寸大小不变 * * @param pxValue * (DisplayMetrics类中属性density) * @return */ public static int px2dip(float pxValue) { final float scale = AppApplication.getAppContext().getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); } /** * 将dip或dp值转换为px值,保证尺寸大小不变 * * @param dipValue * (DisplayMetrics类中属性density) * @return */ public static int dip2px( float dipValue) { final float scale = AppApplication.getAppContext().getResources().getDisplayMetrics().density; return (int) (dipValue * scale + 0.5f); } /** * 将px值转换为sp值,保证文字大小不变 * * @param pxValue * (DisplayMetrics类中属性scaledDensity) * @return */ public static int px2sp(float pxValue) { final float fontScale = AppApplication.getAppContext().getResources().getDisplayMetrics().scaledDensity; return (int) (pxValue / fontScale + 0.5f); } /** * 将sp值转换为px值,保证文字大小不变 * * @param spValue * (DisplayMetrics类中属性scaledDensity) * @return */ public static int sp2px(float spValue) { final float fontScale = AppApplication.getAppContext().getResources().getDisplayMetrics().scaledDensity; return (int) (spValue * fontScale + 0.5f); } /** * 直接获取控件的宽、高 * @param view * @return int[] */ public static int[] getWidgetWH(final View view){ ViewTreeObserver vto2 = view.getViewTreeObserver(); vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { view.getViewTreeObserver().removeGlobalOnLayoutListener(this); } }); return new int[]{view.getWidth(),view.getHeight()}; } /** * 直接获取控件的宽、高 * @param view * @return int[] */ public static int getViewHeight(final View view){ ViewTreeObserver vto2 = view.getViewTreeObserver(); vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { view.getViewTreeObserver().removeGlobalOnLayoutListener(this); } }); return view.getHeight(); } /** * 直接获取控件的宽、高 * @param view * @return int[] */ public static int getViewWidth(final View view){ ViewTreeObserver vto2 = view.getViewTreeObserver(); vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { view.getViewTreeObserver().removeGlobalOnLayoutListener(this); } }); return view.getWidth(); } /** * 获得屏幕宽度 * * @param context * @return */ public static int getScreenWidth(Context context) { WindowManager wm = (WindowManager) context .getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); return outMetrics.widthPixels; } /** * 获得屏幕高度 * * @param context * @return */ public static int getScreenHeight(Context context) { WindowManager wm = (WindowManager) context .getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); return outMetrics.heightPixels; } /** * 获得状态栏的高度 * 注意:该方法只能在Activity类中使用,在测试模式下失败 * @param context * @return */ public static int getStatusBarHeight(Context context) { int statusBarHeight = -1; try { Class clazz = Class.forName("com.android.internal.R$dimen"); Object object = clazz.newInstance(); int height = Integer.parseInt(clazz.getField("status_bar_height") .get(object).toString()); statusBarHeight = context.getResources().getDimensionPixelSize(height); } catch (Exception e) { e.printStackTrace(); } return statusBarHeight; } /** * 获取控件的宽 * @param view * @return */ public static int getWidgetWidth(View view){ int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); view.measure(w, h);//先度量 int width = view.getMeasuredWidth(); return width; } /** * 获取控件的高 * @param view * @return */ public static int getWidgetHeight(View view){ int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); view.measure(w, h);//先度量 int height = view.getMeasuredHeight(); return height; } /** * 设置控件宽 * @param view * @param width */ public static void setWidgetWidth(View view, int width){ LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams(); params.width = width; view.setLayoutParams(params); } /** * 设置控件高 * @param view * @param height */ public static void setWidgetHeight(View view, int height){ LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams(); params.height = height; view.setLayoutParams(params); } //---------------------------------------------- /** * 获取当前屏幕截图,包含状态栏(这个方法没测试通过) * * @param activity * @return Bitmap */ public static Bitmap snapShotWithStatusBar(Activity activity) { View view = activity.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bmp = view.getDrawingCache(); int width = getScreenWidth(activity); int height = getScreenHeight(activity); Bitmap bp = null; bp = Bitmap.createBitmap(bmp, 0, 0, width, height); view.destroyDrawingCache(); return bp; } /** * 获取当前屏幕截图,不包含状态栏(这个方法没测试通过) * * @param activity * @return Bitmap */ public static Bitmap snapShotWithoutStatusBar(Activity activity) { View view = activity.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bmp = view.getDrawingCache(); Rect frame = new Rect(); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); int statusBarHeight = frame.top; int width = getScreenWidth(activity); int height = getScreenHeight(activity); Bitmap bp = null; bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height - statusBarHeight); view.destroyDrawingCache(); return bp; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/utils/GlideRoundTransformUtil.java ================================================ package com.lvr.livecircle.utils; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Paint; import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; /** * description:glide转换圆角图片 * Created by xsf * on 2016.04.15:17 */ public class GlideRoundTransformUtil extends BitmapTransformation { public GlideRoundTransformUtil(Context context) { super(context); } @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) { return circleCrop(pool, toTransform); } private static Bitmap circleCrop(BitmapPool pool, Bitmap source) { if (source == null) return null; int size = Math.min(source.getWidth(), source.getHeight()); int x = (source.getWidth() - size) / 2; int y = (source.getHeight() - size) / 2; // TODO this could be acquired from the pool too Bitmap squared = Bitmap.createBitmap(source, x, y, size, size); Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888); if (result == null) { result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); } Canvas canvas = new Canvas(result); Paint paint = new Paint(); paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP)); paint.setAntiAlias(true); float r = size / 2f; canvas.drawCircle(r, r, r, paint); return result; } @Override public String getId() { return getClass().getName(); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/utils/ImageLoaderUtils.java ================================================ package com.lvr.livecircle.utils; import android.content.Context; import android.widget.ImageView; import com.bumptech.glide.Glide; import com.bumptech.glide.load.DecodeFormat; import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.lvr.livecircle.R; import java.io.File; /** * Description : 图片加载工具类 使用glide框架封装 */ public class ImageLoaderUtils { public static void display(Context context, ImageView imageView, String url, int placeholder, int error) { if (imageView == null) { throw new IllegalArgumentException("argument error"); } Glide.with(context).load(url).placeholder(placeholder) .error(error).crossFade().into(imageView); } public static void display(Context context, ImageView imageView, String url) { if (imageView == null) { throw new IllegalArgumentException("argument error"); } Glide.with(context).load(url) .diskCacheStrategy(DiskCacheStrategy.ALL) .centerCrop() .placeholder(R.drawable.ic_image_loading) .error(R.drawable.ic_empty_picture) .crossFade().into(imageView); } public static void display(Context context, ImageView imageView, File url) { if (imageView == null) { throw new IllegalArgumentException("argument error"); } Glide.with(context).load(url) .diskCacheStrategy(DiskCacheStrategy.ALL) .centerCrop() .placeholder(R.drawable.ic_image_loading) .error(R.drawable.ic_empty_picture) .crossFade().into(imageView); } public static void displaySmallPhoto(Context context, ImageView imageView, String url) { if (imageView == null) { throw new IllegalArgumentException("argument error"); } Glide.with(context).load(url).asBitmap() .diskCacheStrategy(DiskCacheStrategy.ALL) .placeholder(R.drawable.ic_image_loading) .error(R.drawable.ic_empty_picture) .thumbnail(0.5f) .into(imageView); } public static void displayBigPhoto(Context context, ImageView imageView, String url) { if (imageView == null) { throw new IllegalArgumentException("argument error"); } Glide.with(context).load(url).asBitmap() .format(DecodeFormat.PREFER_ARGB_8888) .diskCacheStrategy(DiskCacheStrategy.ALL) .placeholder(R.drawable.ic_image_loading) .error(R.drawable.ic_empty_picture) .into(imageView); } public static void display(Context context, ImageView imageView, int url) { if (imageView == null) { throw new IllegalArgumentException("argument error"); } Glide.with(context).load(url) .diskCacheStrategy(DiskCacheStrategy.ALL) .centerCrop() .placeholder(R.drawable.ic_image_loading) .error(R.drawable.ic_empty_picture) .crossFade().into(imageView); } public static void displayRound(Context context, ImageView imageView, String url) { if (imageView == null) { throw new IllegalArgumentException("argument error"); } Glide.with(context).load(url) .diskCacheStrategy(DiskCacheStrategy.ALL) .error(R.drawable.toux2) .centerCrop().transform(new GlideRoundTransformUtil(context)).into(imageView); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/utils/StatusBarSetting.java ================================================ package com.lvr.livecircle.utils; import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.graphics.Color; import android.os.Build; import android.support.annotation.ColorInt; import android.support.design.widget.CoordinatorLayout; import android.support.v4.widget.DrawerLayout; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.LinearLayout; import com.lvr.livecircle.R; import com.lvr.livecircle.widget.StatusBarView; /** * Created by lvr on 2017/2/7. */ public class StatusBarSetting { public static final int DEFAULT_STATUS_BAR_ALPHA = 112; public static final int FAKE_STATUS_BAR_VIEW_ID = R.id.statusbarutil_fake_status_bar_view; public static final int FAKE_TRANSLUCENT_VIEW_ID = R.id.statusbarutil_translucent_view; private static final int COLOR_TRANSLUCENT = Color.parseColor("#00000000"); /** * 设置状态栏颜色 * * @param activity 需要设置的 activity * @param color 状态栏颜色值 */ public static void setColor(Activity activity, @ColorInt int color) { setColor(activity, color, DEFAULT_STATUS_BAR_ALPHA); } /** * 设置状态栏颜色 * * @param activity 需要设置的activity * @param color 状态栏颜色值 * @param statusBarAlpha 状态栏透明度 */ public static void setColor(Activity activity, @ColorInt int color, int statusBarAlpha) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); activity.getWindow().setStatusBarColor(calculateStatusColor(color, statusBarAlpha)); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView(); View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID); if (fakeStatusBarView != null) { if (fakeStatusBarView.getVisibility() == View.GONE) { fakeStatusBarView.setVisibility(View.VISIBLE); } fakeStatusBarView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha)); } else { decorView.addView(createStatusBarView(activity, color, statusBarAlpha)); } setRootView(activity); } } /** * 为滑动返回界面设置状态栏颜色 * * @param activity 需要设置的activity * @param color 状态栏颜色值 */ public static void setColorForSwipeBack(Activity activity, int color) { setColorForSwipeBack(activity, color, DEFAULT_STATUS_BAR_ALPHA); } /** * 为滑动返回界面设置状态栏颜色 * * @param activity 需要设置的activity * @param color 状态栏颜色值 * @param statusBarAlpha 状态栏透明度 */ public static void setColorForSwipeBack(Activity activity, @ColorInt int color, int statusBarAlpha) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { ViewGroup contentView = ((ViewGroup) activity.findViewById(android.R.id.content)); View rootView = contentView.getChildAt(0); int statusBarHeight = getStatusBarHeight(activity); if (rootView != null && rootView instanceof CoordinatorLayout) { final CoordinatorLayout coordinatorLayout = (CoordinatorLayout) rootView; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { coordinatorLayout.setFitsSystemWindows(false); contentView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha)); boolean isNeedRequestLayout = contentView.getPaddingTop() < statusBarHeight; if (isNeedRequestLayout) { contentView.setPadding(0, statusBarHeight, 0, 0); coordinatorLayout.post(new Runnable() { @Override public void run() { coordinatorLayout.requestLayout(); } }); } } else { coordinatorLayout.setStatusBarBackgroundColor(calculateStatusColor(color, statusBarAlpha)); } } else { contentView.setPadding(0, statusBarHeight, 0, 0); contentView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha)); } setTransparentForWindow(activity); } } /** * 设置状态栏纯色 不加半透明效果 * * @param activity 需要设置的 activity * @param color 状态栏颜色值 */ public static void setColorNoTranslucent(Activity activity, @ColorInt int color) { setColor(activity, color, 0); } /** * 设置状态栏颜色(5.0以下无半透明效果,不建议使用) * * @param activity 需要设置的 activity * @param color 状态栏颜色值 */ @Deprecated public static void setColorDiff(Activity activity, @ColorInt int color) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return; } transparentStatusBar(activity); ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content); // 移除半透明矩形,以免叠加 View fakeStatusBarView = contentView.findViewById(FAKE_STATUS_BAR_VIEW_ID); if (fakeStatusBarView != null) { if (fakeStatusBarView.getVisibility() == View.GONE) { fakeStatusBarView.setVisibility(View.VISIBLE); } fakeStatusBarView.setBackgroundColor(color); } else { contentView.addView(createStatusBarView(activity, color)); } setRootView(activity); } /** * 使状态栏半透明 * * 适用于图片作为背景的界面,此时需要图片填充到状态栏 * * @param activity 需要设置的activity */ public static void setTranslucent(Activity activity) { setTranslucent(activity, DEFAULT_STATUS_BAR_ALPHA); } /** * 使状态栏半透明 * * 适用于图片作为背景的界面,此时需要图片填充到状态栏 * * @param activity 需要设置的activity * @param statusBarAlpha 状态栏透明度 */ public static void setTranslucent(Activity activity, int statusBarAlpha) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return; } setTransparent(activity); addTranslucentView(activity, statusBarAlpha); } /** * 针对根布局是 CoordinatorLayout, 使状态栏半透明 * * 适用于图片作为背景的界面,此时需要图片填充到状态栏 * * @param activity 需要设置的activity * @param statusBarAlpha 状态栏透明度 */ public static void setTranslucentForCoordinatorLayout(Activity activity, int statusBarAlpha) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return; } transparentStatusBar(activity); addTranslucentView(activity, statusBarAlpha); } /** * 设置状态栏全透明 * * @param activity 需要设置的activity */ public static void setTransparent(Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return; } transparentStatusBar(activity); setRootView(activity); } /** * 使状态栏透明(5.0以上半透明效果,不建议使用) * * 适用于图片作为背景的界面,此时需要图片填充到状态栏 * * @param activity 需要设置的activity */ @Deprecated public static void setTranslucentDiff(Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // 设置状态栏透明 activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); setRootView(activity); } } /** * 为DrawerLayout 布局设置状态栏变色 * * @param activity 需要设置的activity * @param drawerLayout DrawerLayout * @param color 状态栏颜色值 */ public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) { setColorForDrawerLayout(activity, drawerLayout, color, DEFAULT_STATUS_BAR_ALPHA); } /** * 为DrawerLayout 布局设置状态栏颜色,纯色 * * @param activity 需要设置的activity * @param drawerLayout DrawerLayout * @param color 状态栏颜色值 */ public static void setColorNoTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) { setColorForDrawerLayout(activity, drawerLayout, color, 0); } /** * 为DrawerLayout 布局设置状态栏变色 * * @param activity 需要设置的activity * @param drawerLayout DrawerLayout * @param color 状态栏颜色值 * @param statusBarAlpha 状态栏透明度 */ public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color, int statusBarAlpha) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); activity.getWindow().setStatusBarColor(Color.TRANSPARENT); } else { activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); } // 生成一个状态栏大小的矩形 // 添加 statusBarView 到布局中 ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0); View fakeStatusBarView = contentLayout.findViewById(FAKE_STATUS_BAR_VIEW_ID); if (fakeStatusBarView != null) { if (fakeStatusBarView.getVisibility() == View.GONE) { fakeStatusBarView.setVisibility(View.VISIBLE); } fakeStatusBarView.setBackgroundColor(color); } else { contentLayout.addView(createStatusBarView(activity, color), 0); } // 内容布局不是 LinearLayout 时,设置padding top if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) { contentLayout.getChildAt(1) .setPadding(contentLayout.getPaddingLeft(), getStatusBarHeight(activity) + contentLayout.getPaddingTop(), contentLayout.getPaddingRight(), contentLayout.getPaddingBottom()); } // 设置属性 setDrawerLayoutProperty(drawerLayout, contentLayout); addTranslucentView(activity, statusBarAlpha); } /** * 设置 DrawerLayout 属性 * * @param drawerLayout DrawerLayout * @param drawerLayoutContentLayout DrawerLayout 的内容布局 */ private static void setDrawerLayoutProperty(DrawerLayout drawerLayout, ViewGroup drawerLayoutContentLayout) { ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1); drawerLayout.setFitsSystemWindows(false); drawerLayoutContentLayout.setFitsSystemWindows(false); drawerLayoutContentLayout.setClipToPadding(true); drawer.setFitsSystemWindows(false); } /** * 为DrawerLayout 布局设置状态栏变色(5.0以下无半透明效果,不建议使用) * * @param activity 需要设置的activity * @param drawerLayout DrawerLayout * @param color 状态栏颜色值 */ @Deprecated public static void setColorForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); // 生成一个状态栏大小的矩形 ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0); View fakeStatusBarView = contentLayout.findViewById(FAKE_STATUS_BAR_VIEW_ID); if (fakeStatusBarView != null) { if (fakeStatusBarView.getVisibility() == View.GONE) { fakeStatusBarView.setVisibility(View.VISIBLE); } fakeStatusBarView.setBackgroundColor(calculateStatusColor(color, DEFAULT_STATUS_BAR_ALPHA)); } else { // 添加 statusBarView 到布局中 contentLayout.addView(createStatusBarView(activity, color), 0); } // 内容布局不是 LinearLayout 时,设置padding top if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) { contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0); } // 设置属性 setDrawerLayoutProperty(drawerLayout, contentLayout); } } /** * 为 DrawerLayout 布局设置状态栏透明 * * @param activity 需要设置的activity * @param drawerLayout DrawerLayout */ public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) { setTranslucentForDrawerLayout(activity, drawerLayout, DEFAULT_STATUS_BAR_ALPHA); } /** * 为 DrawerLayout 布局设置状态栏透明 * * @param activity 需要设置的activity * @param drawerLayout DrawerLayout */ public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout, int statusBarAlpha) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return; } setTransparentForDrawerLayout(activity, drawerLayout); addTranslucentView(activity, statusBarAlpha); } /** * 为 DrawerLayout 布局设置状态栏透明 * * @param activity 需要设置的activity * @param drawerLayout DrawerLayout */ public static void setTransparentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); activity.getWindow().setStatusBarColor(Color.TRANSPARENT); } else { activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); } ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0); // 内容布局不是 LinearLayout 时,设置padding top if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) { contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0); } // 设置属性 setDrawerLayoutProperty(drawerLayout, contentLayout); } /** * 为 DrawerLayout 布局设置状态栏透明(5.0以上半透明效果,不建议使用) * * @param activity 需要设置的activity * @param drawerLayout DrawerLayout */ @Deprecated public static void setTranslucentForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // 设置状态栏透明 activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); // 设置内容布局属性 ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0); contentLayout.setFitsSystemWindows(true); contentLayout.setClipToPadding(true); // 设置抽屉布局属性 ViewGroup vg = (ViewGroup) drawerLayout.getChildAt(1); vg.setFitsSystemWindows(false); // 设置 DrawerLayout 属性 drawerLayout.setFitsSystemWindows(false); } } /** * 为头部是 ImageView 的界面设置状态栏全透明 * * @param activity 需要设置的activity * @param needOffsetView 需要向下偏移的 View */ public static void setTransparentForImageView(Activity activity, View needOffsetView) { setTranslucentForImageView(activity, 0, needOffsetView); } /** * 为头部是 ImageView 的界面设置状态栏透明(使用默认透明度) * * @param activity 需要设置的activity * @param needOffsetView 需要向下偏移的 View */ public static void setTranslucentForImageView(Activity activity, View needOffsetView) { setTranslucentForImageView(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView); } /** * 为头部是 ImageView 的界面设置状态栏透明 * * @param activity 需要设置的activity * @param statusBarAlpha 状态栏透明度 * @param needOffsetView 需要向下偏移的 View */ public static void setTranslucentForImageView(Activity activity, int statusBarAlpha, View needOffsetView) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return; } setTransparentForWindow(activity); addTranslucentView(activity, statusBarAlpha); if (needOffsetView != null) { ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) needOffsetView.getLayoutParams(); layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin + getStatusBarHeight(activity), layoutParams.rightMargin, layoutParams.bottomMargin); } } /** * 为 fragment 头部是 ImageView 的设置状态栏透明 * * @param activity fragment 对应的 activity * @param needOffsetView 需要向下偏移的 View */ public static void setTranslucentForImageViewInFragment(Activity activity, View needOffsetView) { setTranslucentForImageViewInFragment(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView); } /** * 为 fragment 头部是 ImageView 的设置状态栏透明 * * @param activity fragment 对应的 activity * @param needOffsetView 需要向下偏移的 View */ public static void setTransparentForImageViewInFragment(Activity activity, View needOffsetView) { setTranslucentForImageViewInFragment(activity, 0, needOffsetView); } /** * 为 fragment 头部是 ImageView 的设置状态栏透明 * * @param activity fragment 对应的 activity * @param statusBarAlpha 状态栏透明度 * @param needOffsetView 需要向下偏移的 View */ public static void setTranslucentForImageViewInFragment(Activity activity, int statusBarAlpha, View needOffsetView) { setTranslucentForImageView(activity, statusBarAlpha, needOffsetView); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { clearPreviousSetting(activity); } } /** * 隐藏伪状态栏 View * * @param activity 调用的 Activity */ public static void hideFakeStatusBarView(Activity activity) { ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView(); View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID); if (fakeStatusBarView != null) { fakeStatusBarView.setVisibility(View.GONE); } View fakeTranslucentView = decorView.findViewById(FAKE_TRANSLUCENT_VIEW_ID); if (fakeTranslucentView != null) { fakeTranslucentView.setVisibility(View.GONE); } } /////////////////////////////////////////////////////////////////////////////////// @TargetApi(Build.VERSION_CODES.KITKAT) private static void clearPreviousSetting(Activity activity) { ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView(); View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID); if (fakeStatusBarView != null) { decorView.removeView(fakeStatusBarView); ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0); rootView.setPadding(0, 0, 0, 0); } } /** * 添加半透明矩形条 * * @param activity 需要设置的 activity * @param statusBarAlpha 透明值 */ private static void addTranslucentView(Activity activity, int statusBarAlpha) { ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content); View fakeTranslucentView = contentView.findViewById(FAKE_TRANSLUCENT_VIEW_ID); if (fakeTranslucentView != null) { if (fakeTranslucentView.getVisibility() == View.GONE) { fakeTranslucentView.setVisibility(View.VISIBLE); } fakeTranslucentView.setBackgroundColor(Color.argb(statusBarAlpha, 0, 0, 0)); } else { contentView.addView(createTranslucentStatusBarView(activity, statusBarAlpha)); } } /** * 生成一个和状态栏大小相同的彩色矩形条 * * @param activity 需要设置的 activity * @param color 状态栏颜色值 * @return 状态栏矩形条 */ private static StatusBarView createStatusBarView(Activity activity, @ColorInt int color) { return createStatusBarView(activity, color, 0); } /** * 生成一个和状态栏大小相同的半透明矩形条 * * @param activity 需要设置的activity * @param color 状态栏颜色值 * @param alpha 透明值 * @return 状态栏矩形条 */ private static StatusBarView createStatusBarView(Activity activity, @ColorInt int color, int alpha) { // 绘制一个和状态栏一样高的矩形 StatusBarView statusBarView = new StatusBarView(activity); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity)); statusBarView.setLayoutParams(params); statusBarView.setBackgroundColor(calculateStatusColor(color, alpha)); statusBarView.setId(FAKE_STATUS_BAR_VIEW_ID); return statusBarView; } /** * 设置根布局参数 */ private static void setRootView(Activity activity) { ViewGroup parent = (ViewGroup) activity.findViewById(android.R.id.content); for (int i = 0, count = parent.getChildCount(); i < count; i++) { View childView = parent.getChildAt(i); if (childView instanceof ViewGroup) { childView.setFitsSystemWindows(true); ((ViewGroup) childView).setClipToPadding(true); } } } /** * 设置透明 */ private static void setTransparentForWindow(Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { activity.getWindow().setStatusBarColor(Color.TRANSPARENT); activity.getWindow() .getDecorView() .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { activity.getWindow() .setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); } } /** * 使状态栏透明 */ @TargetApi(Build.VERSION_CODES.KITKAT) private static void transparentStatusBar(Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); activity.getWindow().setStatusBarColor(Color.TRANSPARENT); } else { activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); } } /** * 创建半透明矩形 View * * @param alpha 透明值 * @return 半透明 View */ private static StatusBarView createTranslucentStatusBarView(Activity activity, int alpha) { // 绘制一个和状态栏一样高的矩形 StatusBarView statusBarView = new StatusBarView(activity); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity)); statusBarView.setLayoutParams(params); statusBarView.setBackgroundColor(Color.argb(alpha, 0, 0, 0)); statusBarView.setId(FAKE_TRANSLUCENT_VIEW_ID); return statusBarView; } /** * 获取状态栏高度 * * @param context context * @return 状态栏高度 */ private static int getStatusBarHeight(Context context) { // 获得状态栏高度 int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); return context.getResources().getDimensionPixelSize(resourceId); } /** * 计算状态栏颜色 * * @param color color值 * @param alpha alpha值 * @return 最终的状态栏颜色 */ private static int calculateStatusColor(@ColorInt int color, int alpha) { if (alpha == 0) { return color; } float a = 1 - alpha / 255f; int red = color >> 16 & 0xff; int green = color >> 8 & 0xff; int blue = color & 0xff; red = (int) (red * a + 0.5); green = (int) (green * a + 0.5); blue = (int) (blue * a + 0.5); return 0xff << 24 | red << 16 | green << 8 | blue; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/utils/TUtil.java ================================================ package com.lvr.livecircle.utils; import java.lang.reflect.ParameterizedType; /** * 类转换初始化 */ public class TUtil { public static T getT(Object o, int i) { try { return ((Class) ((ParameterizedType) (o.getClass() .getGenericSuperclass())).getActualTypeArguments()[i]) .newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassCastException e) { e.printStackTrace(); } return null; } public static Class forName(String className) { try { return Class.forName(className); } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/utils/TimeUtil.java ================================================ /* * */ package com.lvr.livecircle.utils; import android.annotation.SuppressLint; import android.text.TextUtils; import android.util.Log; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.Locale; /** * 描述:日期处理类. * */ @SuppressWarnings("all") public class TimeUtil { /** * one day millisecond count */ public static final long ONE_DAY_MILLISECONDS = 1000 * 3600 * 24; public static final long ONE_HOUR_MILLISECONDS = 1000 * 3600; public static final long ONE_MIN_MILLISECONDS = 1000 * 60; /** * 时间日期格式化到年月日时分秒. */ public static String dateFormatYMDHMS = "yyyy-MM-dd HH:mm:ss"; public static String dateFormatYMDHMS_f = "yyyyMMddHHmmss"; public static String dateFormatMDHM = "MM-dd HH:mm"; public static String dateFormat = "yyyy-MM-dd HH:mm"; /** * 时间日期格式化到年月日. */ public static String dateFormatYMD = "yyyy-MM-dd"; /** * 时间日期格式化到年月日时分.中文显示 */ public static String dateFormatYMDHMofChinese = "yyyy年MM月dd日 HH:mm"; /** * 时间日期格式化到年月日.中文显示 */ public static String dateFormatYMDofChinese = "yyyy年MM月dd日"; /** * 时间日期格式化到月日.中文显示 */ public static String dateFormatMDofChinese = "MM月dd日"; /** * 时间日期格式化到月.中文显示 */ public static String dateFormatMofChinese = "MM月"; /** * 时间日期格式化到年月. */ public static String dateFormatYM = "yyyy-MM"; /** * 时间日期格式化到年月日时分. */ public static String dateFormatYMDHM = "yyyy-MM-dd HH:mm"; /** * 时间日期格式化到月日. */ public static String dateFormatMD = "MM/dd"; public static String dateFormatM_D = "MM-dd"; public static String dateFormatM = "MM月"; public static String dateFormatD = "dd"; public static String dateFormatM2 = "MM"; public static String dateFormatMDHMofChinese = "MM月dd日HH时mm分"; public static String dateFormatHMofChinese = "HH时mm分"; /** * 时分秒. */ public static String dateFormatHMS = "HH:mm:ss"; /** * 时分. */ public static String dateFormatHM = "HH:mm"; /** * 上午/下午时分 */ public static String dateFormatAHM = "aHH:mm"; public static String dateFormatYMDE = "yyyy/MM/dd E"; public static String dateFormatYMD2 = "yyyy/MM/dd"; private final static ThreadLocal dateFormater = new ThreadLocal() { @SuppressLint("SimpleDateFormat") @Override protected SimpleDateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); } }; @SuppressLint("SimpleDateFormat") private final static ThreadLocal dateFormater2 = new ThreadLocal() { @Override protected SimpleDateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd"); } }; /** * 时间戳转特定格式时间 * @param dataFormat * @param timeStamp * @return */ public static String formatData(String dataFormat, long timeStamp) { if (timeStamp == 0) { return ""; } timeStamp = timeStamp * 1000; SimpleDateFormat format = new SimpleDateFormat(dataFormat); return format.format(new Date(timeStamp)); } /** * 将毫秒转换成秒 * * @param time * @return */ public static int convertToSecond(Long time) { Date date = new Date(); date.setTime(time); return date.getSeconds(); } /** * 描述:String类型的日期时间转化为Date类型. * * @param strDate String形式的日期时间 * @param format 格式化字符串,如:"yyyy-MM-dd HH:mm:ss" * @return Date Date类型日期时间 */ public static Date getDateByFormat(String strDate, String format) { SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); Date date = null; try { date = mSimpleDateFormat.parse(strDate); } catch (ParseException e) { e.printStackTrace(); } return date; } /** * 描述:获取偏移之后的Date. * * @param date 日期时间 * @param calendarField Calendar属性,对应offset的值, 如(Calendar.DATE,表示+offset天,Calendar.HOUR_OF_DAY,表示+offset小时) * @param offset 偏移(值大于0,表示+,值小于0,表示-) * @return Date 偏移之后的日期时间 */ public Date getDateByOffset(Date date, int calendarField, int offset) { Calendar c = new GregorianCalendar(); try { c.setTime(date); c.add(calendarField, offset); } catch (Exception e) { e.printStackTrace(); } return c.getTime(); } /** * 描述:获取指定日期时间的字符串(可偏移). * * @param strDate String形式的日期时间 * @param format 格式化字符串,如:"yyyy-MM-dd HH:mm:ss" * @param calendarField Calendar属性,对应offset的值, 如(Calendar.DATE,表示+offset天,Calendar.HOUR_OF_DAY,表示+offset小时) * @param offset 偏移(值大于0,表示+,值小于0,表示-) * @return String String类型的日期时间 */ public static String getStringByOffset(String strDate, String format, int calendarField, int offset) { String mDateTime = null; try { Calendar c = new GregorianCalendar(); SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); c.setTime(mSimpleDateFormat.parse(strDate)); c.add(calendarField, offset); mDateTime = mSimpleDateFormat.format(c.getTime()); } catch (ParseException e) { e.printStackTrace(); } return mDateTime; } /** * 描述:Date类型转化为String类型(可偏移). * * @param date the date * @param format the format * @param calendarField the calendar field * @param offset the offset * @return String String类型日期时间 */ public static String getStringByOffset(Date date, String format, int calendarField, int offset) { String strDate = null; try { Calendar c = new GregorianCalendar(); SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); c.setTime(date); c.add(calendarField, offset); strDate = mSimpleDateFormat.format(c.getTime()); } catch (Exception e) { e.printStackTrace(); } return strDate; } /** * from yyyy-MM-dd HH:mm:ss to MM-dd HH:mm */ public static String formatDate(String before) { String after; try { Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()) .parse(before); after = new SimpleDateFormat("MM-dd HH:mm", Locale.getDefault()).format(date); } catch (ParseException e) { return before; } return after; } /** * 描述:Date类型转化为String类型. * * @param date the date * @param format the format * @return String String类型日期时间 */ public static String getStringByFormat(Date date, String format) { SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); String strDate = null; try { strDate = mSimpleDateFormat.format(date); } catch (Exception e) { e.printStackTrace(); } return strDate; } /** * 描述:获取指定日期时间的字符串,用于导出想要的格式. * * @param strDate String形式的日期时间,必须为yyyy-MM-dd HH:mm:ss格式 * @param format 输出格式化字符串,如:"yyyy-MM-dd HH:mm:ss" * @return String 转换后的String类型的日期时间 */ public static String getStringByFormat(String strDate, String format) { String mDateTime = null; try { Calendar c = new GregorianCalendar(); SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); c.setTime(mSimpleDateFormat.parse(strDate)); SimpleDateFormat mSimpleDateFormat2 = new SimpleDateFormat(format); mDateTime = mSimpleDateFormat2.format(c.getTime()); } catch (Exception e) { e.printStackTrace(); } return mDateTime; } /** * 描述:获取milliseconds表示的日期时间的字符串. * * @param format 格式化字符串,如:"yyyy-MM-dd HH:mm:ss" * @return String 日期时间字符串 */ public static String getStringByFormat(long milliseconds, String format) { String thisDateTime = null; try { SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); thisDateTime = mSimpleDateFormat.format(milliseconds); } catch (Exception e) { e.printStackTrace(); } return thisDateTime; } /** * 描述:获取表示当前日期时间的字符串. * * @param format 格式化字符串,如:"yyyy-MM-dd HH:mm:ss" * @return String String类型的当前日期时间 */ public static String getCurrentDate(String format) { String curDateTime = null; try { SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); Calendar c = new GregorianCalendar(); curDateTime = mSimpleDateFormat.format(c.getTime()); } catch (Exception e) { e.printStackTrace(); } return curDateTime; } //获取当前系统当天日期 public static String getCurrentDay() { String curDateTime = null; try { SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(dateFormat); Calendar c = new GregorianCalendar(); c.add(Calendar.DAY_OF_MONTH, 0); curDateTime = mSimpleDateFormat.format(c.getTime()); } catch (Exception e) { e.printStackTrace(); } return curDateTime; } //获取当前系统当天日期 public static String getCurrentDay2() { String curDateTime = null; try { SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(dateFormatYMDHMS); Calendar c = new GregorianCalendar(); c.add(Calendar.DAY_OF_MONTH, 0); curDateTime = mSimpleDateFormat.format(c.getTime()); } catch (Exception e) { e.printStackTrace(); } return curDateTime; } //获取当前系统前后第几天 public static String getNextDay(int i) { String curDateTime = null; try { SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(dateFormat); Calendar c = new GregorianCalendar(); c.add(Calendar.DAY_OF_MONTH, i); curDateTime = mSimpleDateFormat.format(c.getTime()); } catch (Exception e) { e.printStackTrace(); } return curDateTime; } //获取当前系统前后第几小时 public static String getNextHour(int i) { String curDateTime = null; try { SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(dateFormat); Calendar c = new GregorianCalendar(); c.add(Calendar.HOUR_OF_DAY, i); curDateTime = mSimpleDateFormat.format(c.getTime()); } catch (Exception e) { e.printStackTrace(); } return curDateTime; } /** * 描述:获取表示当前日期时间的字符串(可偏移). * * @param format 格式化字符串,如:"yyyy-MM-dd HH:mm:ss" * @param calendarField Calendar属性,对应offset的值, 如(Calendar.DATE,表示+offset天,Calendar.HOUR_OF_DAY,表示+offset小时) * @param offset 偏移(值大于0,表示+,值小于0,表示-) * @return String String类型的日期时间 */ public static String getCurrentDateByOffset(String format, int calendarField, int offset) { String mDateTime = null; try { SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); Calendar c = new GregorianCalendar(); c.add(calendarField, offset); mDateTime = mSimpleDateFormat.format(c.getTime()); } catch (Exception e) { e.printStackTrace(); } return mDateTime; } /** * 描述:计算两个日期所差的天数. * * @param date1 第一个时间的毫秒表示 * @param date2 第二个时间的毫秒表示 * @return int 所差的天数 */ public static int getOffectDay(long date1, long date2) { Calendar calendar1 = Calendar.getInstance(); calendar1.setTimeInMillis(date1); Calendar calendar2 = Calendar.getInstance(); calendar2.setTimeInMillis(date2); //先判断是否同年 int y1 = calendar1.get(Calendar.YEAR); int y2 = calendar2.get(Calendar.YEAR); int d1 = calendar1.get(Calendar.DAY_OF_YEAR); int d2 = calendar2.get(Calendar.DAY_OF_YEAR); int maxDays = 0; int day = 0; if (y1 - y2 > 0) { maxDays = calendar2.getActualMaximum(Calendar.DAY_OF_YEAR); day = d1 - d2 + maxDays; } else if (y1 - y2 < 0) { maxDays = calendar1.getActualMaximum(Calendar.DAY_OF_YEAR); day = d1 - d2 - maxDays; } else { day = d1 - d2; } return day; } /** * 描述:计算两个日期所差的小时数. * * @param date1 第一个时间的毫秒表示 * @param date2 第二个时间的毫秒表示 * @return int 所差的小时数 */ public static int getOffectHour(long date1, long date2) { Calendar calendar1 = Calendar.getInstance(); calendar1.setTimeInMillis(date1); Calendar calendar2 = Calendar.getInstance(); calendar2.setTimeInMillis(date2); int h1 = calendar1.get(Calendar.HOUR_OF_DAY); int h2 = calendar2.get(Calendar.HOUR_OF_DAY); int h = 0; int day = getOffectDay(date1, date2); h = h1 - h2 + day * 24; return h; } /** * 描述:计算两个日期所差的分钟数. * * @param date1 第一个时间的毫秒表示 * @param date2 第二个时间的毫秒表示 * @return int 所差的分钟数 */ public static int getOffectMinutes(long date1, long date2) { Calendar calendar1 = Calendar.getInstance(); calendar1.setTimeInMillis(date1); Calendar calendar2 = Calendar.getInstance(); calendar2.setTimeInMillis(date2); int m1 = calendar1.get(Calendar.MINUTE); int m2 = calendar2.get(Calendar.MINUTE); int h = getOffectHour(date1, date2); int m = 0; m = m1 - m2 + h * 60; return m; } /** * 描述:获取本周一. * * @param format the format * @return String String类型日期时间 */ public static String getFirstDayOfWeek(String format) { return getDayOfWeek(format, Calendar.MONDAY); } /** * 描述:获取本周日. * * @param format the format * @return String String类型日期时间 */ public static String getLastDayOfWeek(String format) { return getDayOfWeek(format, Calendar.SUNDAY); } /** * 描述:获取本周的某一天. * * @param format the format * @param calendarField the calendar field * @return String String类型日期时间 */ private static String getDayOfWeek(String format, int calendarField) { String strDate = null; try { Calendar c = new GregorianCalendar(); SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); int week = c.get(Calendar.DAY_OF_WEEK); if (week == calendarField) { strDate = mSimpleDateFormat.format(c.getTime()); } else { int offectDay = calendarField - week; if (calendarField == Calendar.SUNDAY) { offectDay = 7 - Math.abs(offectDay); } c.add(Calendar.DATE, offectDay); strDate = mSimpleDateFormat.format(c.getTime()); } } catch (Exception e) { e.printStackTrace(); } return strDate; } /** * 描述:获取本月第一天. * * @param format the format * @return String String类型日期时间 */ public static String getFirstDayOfMonth(String format) { String strDate = null; try { Calendar c = new GregorianCalendar(); SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); //当前月的第一天 c.set(GregorianCalendar.DAY_OF_MONTH, 1); strDate = mSimpleDateFormat.format(c.getTime()); } catch (Exception e) { e.printStackTrace(); } return strDate; } /** * 描述:获取本月最后一天. * * @param format the format * @return String String类型日期时间 */ public static String getLastDayOfMonth(String format) { String strDate = null; try { Calendar c = new GregorianCalendar(); SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); // 当前月的最后一天 c.set(Calendar.DATE, 1); c.roll(Calendar.DATE, -1); strDate = mSimpleDateFormat.format(c.getTime()); } catch (Exception e) { e.printStackTrace(); } return strDate; } /** * 描述:获取表示当前日期的0点时间毫秒数. * * @return the first time of day */ public static long getFirstTimeOfDay() { Date date = null; try { String currentDate = getCurrentDate(dateFormatYMD); date = getDateByFormat(currentDate + " 00:00:00", dateFormatYMDHMS); return date.getTime(); } catch (Exception e) { } return -1; } /** * 描述:获取表示当前日期24点时间毫秒数. * * @return the last time of day */ public static long getLastTimeOfDay() { Date date = null; try { String currentDate = getCurrentDate(dateFormatYMD); date = getDateByFormat(currentDate + " 24:00:00", dateFormatYMDHMS); return date.getTime(); } catch (Exception e) { } return -1; } /** * 描述:判断是否是闰年() *

(year能被4整除 并且 不能被100整除) 或者 year能被400整除,则该年为闰年. * * @param year 年代(如2012) * @return boolean 是否为闰年 */ public static boolean isLeapYear(int year) { if ((year % 4 == 0 && year % 400 != 0) || year % 400 == 0) { return true; } else { return false; } } /** * 描述:根据时间返回几天前或几分钟的描述. * * @param strDate the str date * @return the string */ public static String formatDateStr2Desc(String strDate, String outFormat) { DateFormat df = new SimpleDateFormat(dateFormatYMDHM); Calendar c1 = Calendar.getInstance(); Calendar c2 = Calendar.getInstance(); try { c2.setTime(df.parse(strDate)); c1.setTime(new Date()); int d = getOffectDay(c1.getTimeInMillis(), c2.getTimeInMillis()); if (d == 0) { int h = getOffectHour(c1.getTimeInMillis(), c2.getTimeInMillis()); if (h > 0) { return h + "小时前"; } else if (h < 0) { return Math.abs(h) + "小时后"; } else if (h == 0) { int m = getOffectMinutes(c1.getTimeInMillis(), c2.getTimeInMillis()); if (m > 0) { return m + "分钟前"; } else if (m < 0) { return Math.abs(m) + "分钟后"; } else { return "刚刚"; } } } else if (d > 0) { if (d == 1) { return "昨天"; } else if (d == 2) { return "前天"; } } else if (d < 0) { if (d == -1) { return "明天"; } else if (d == -2) { return "后天"; } return Math.abs(d) + "天后"; } String out = getStringByFormat(strDate, outFormat); if (!TextUtils.isEmpty(out)) { return out; } } catch (Exception e) { } return strDate; } /** * 取指定日期为星期几 * * @param strDate 指定日期 * @param inFormat 指定日期格式 * @return String 星期几 */ public static String getWeekNumber(String strDate, String inFormat) { String week = "星期日"; Calendar calendar = new GregorianCalendar(); DateFormat df = new SimpleDateFormat(inFormat); try { calendar.setTime(df.parse(strDate)); } catch (Exception e) { return "错误"; } int intTemp = calendar.get(Calendar.DAY_OF_WEEK) - 1; switch (intTemp) { case 0: week = "星期日"; break; case 1: week = "星期一"; break; case 2: week = "星期二"; break; case 3: week = "星期三"; break; case 4: week = "星期四"; break; case 5: week = "星期五"; break; case 6: week = "星期六"; break; } return week; } /** * 将字符串转位日期类型 * * @param sdate * @return */ private static Date toDate(String sdate) { try { return dateFormater.get().parse(sdate); } catch (ParseException e) { return null; } } /** * 以友好的方式显示时间 * * @param ms * @return */ public static String getfriendlyTime(Long ms) { if (ms == null) return ""; // Date time = toDate(sdate); Date time = new Date(); time.setTime(ms); if (time == null) { return "Unknown"; } String ftime = ""; Calendar cal = Calendar.getInstance(); // 判断是否是同一天 String curDate = dateFormater2.get().format(cal.getTime()); String paramDate = dateFormater2.get().format(time); if (curDate.equals(paramDate)) { int hour = (int) ((cal.getTimeInMillis() - time.getTime()) / 3600000); if (hour == 0) { if (((cal.getTimeInMillis() - time.getTime()) / 60000) < 1) { ftime = "刚刚"; } else { ftime = Math.max((cal.getTimeInMillis() - time.getTime()) / 60000, 1) + "分钟前"; } } else { ftime = hour + "小时前"; } return ftime; } long lt = time.getTime() / 86400000; long ct = cal.getTimeInMillis() / 86400000; int days = (int) (ct - lt); if (days == 0) { int hour = (int) ((cal.getTimeInMillis() - time.getTime()) / 3600000); if (hour == 0) ftime = Math.max( (cal.getTimeInMillis() - time.getTime()) / 60000, 1) + "分钟前"; else ftime = hour + "小时前"; } else if (days == 1) { ftime = "昨天"; } else if (days == 2) { ftime = "前天"; } else if (days > 2 && days <= 10) { ftime = days + "天前"; } else if (days > 10) { ftime = dateFormater2.get().format(time); } return ftime; } /** * 距离当前多少个小时 * * @param dateStr * @return */ @SuppressLint("SimpleDateFormat") public static int getExpiredHour(String dateStr) { int ret = -1; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date; try { date = sdf.parse(dateStr); Date dateNow = new Date(); long times = date.getTime() - dateNow.getTime(); if (times > 0) { ret = ((int) (times / ONE_HOUR_MILLISECONDS)); } else { ret = -1; } } catch (ParseException e) { e.printStackTrace(); } return ret; } /** * 过了多少个小时 * @param dateStr * @return */ @SuppressLint("SimpleDateFormat") public static int getExpiredHour2(String dateStr) { int ret = -1; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date sendDate; try { sendDate = sdf.parse(dateStr); Date dateNow = new Date(System.currentTimeMillis()); Log.e("JPush","date="+sendDate); long times = dateNow.getTime() - sendDate.getTime(); Log.e("JPush","date.getTime()="+sendDate.getTime()); if (times > 0) { ret = ((int) (times / ONE_HOUR_MILLISECONDS)); int sdqf =(int) Math.floor(times /ONE_HOUR_MILLISECONDS); } else { ret = -1; } } catch (ParseException e) { e.printStackTrace(); } Log.e("JPush","ret="+ret); return ret; } /** * 判断给定字符串时间是否为今日 * * @param sdate * @return boolean */ public static boolean isToday(String sdate) { boolean b = false; Date time = toDate(sdate); Date today = new Date(); if (time != null) { String nowDate = dateFormater2.get().format(today); String timeDate = dateFormater2.get().format(time); if (nowDate.equals(timeDate)) { b = true; } } return b; } /** * 判断给定字符串时间是否为今日 * * @param sdate * @return boolean */ public static boolean isToday(long sdate) { boolean b = false; Date time = new Date(sdate); Date today = new Date(); if (time != null) { String nowDate = dateFormater2.get().format(today); String timeDate = dateFormater2.get().format(time); if (nowDate.equals(timeDate)) { b = true; } } return b; } /** * 根据用户生日计算年龄 */ public static int getAgeByBirthday(Date birthday) { Calendar cal = Calendar.getInstance(); if (cal.before(birthday)) { throw new IllegalArgumentException( "The birthDay is before Now.It's unbelievable!"); } int yearNow = cal.get(Calendar.YEAR); int monthNow = cal.get(Calendar.MONTH) + 1; int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH); cal.setTime(birthday); int yearBirth = cal.get(Calendar.YEAR); int monthBirth = cal.get(Calendar.MONTH) + 1; int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH); int age = yearNow - yearBirth; if (monthNow <= monthBirth) { if (monthNow == monthBirth) { // monthNow==monthBirth if (dayOfMonthNow < dayOfMonthBirth) { age--; } } else { // monthNow>monthBirth age--; } } return age; } /** * 友好显示时间差 * * @param diff 毫秒 * @return */ public static String getFriendTimeOffer(long diff) { int day = (int) (diff / (24 * 60 * 60 * 1000)); if (day > 0) return day + "天"; int time = (int) (diff / (60 * 60 * 1000)); if (time > 0) return time + "小时"; int min = (int) (diff / (60 * 1000)); if (min > 0) return min + "分钟"; int sec = (int) diff / 1000; if (sec > 0) return sec + "秒"; return "1秒"; } /** * 友好的时间间隔 * * @param duration 秒 * @return */ public static String getFriendlyDuration(long duration) { String str = ""; long tmpDuration = duration; str += (tmpDuration / 60 > 10 ? tmpDuration / 60 : "0" + tmpDuration / 60) + ":"; tmpDuration %= 60; str += (tmpDuration / 1 >= 10 ? tmpDuration / 1 : "0" + tmpDuration / 1); tmpDuration %= 1; return str; } /** * 友好的时间间隔2 * * @param duration 秒 * @return */ public static String getFriendlyDuration2(long duration) { String str = ""; long tmpDuration = duration; str += (tmpDuration / 60>0?tmpDuration / 60+"'":""); tmpDuration %= 60; str += (tmpDuration / 1>=10?tmpDuration / 1+"''":"0"+tmpDuration / 1+"''"); tmpDuration %= 1; return str; } public static String getFriendlyMusicDuration(long duration) { String str = "-"; int tmpDuration = (int) (duration / 1000);//秒 str += (tmpDuration / 3600 > 10 ? tmpDuration / 3600 : "0" + tmpDuration / 3600) + ":"; tmpDuration %= 3600; str += (tmpDuration / 60 > 10 ? tmpDuration / 60 : "0" + tmpDuration / 60) + ":"; tmpDuration %= 60; str += (tmpDuration / 1 >= 10 ? tmpDuration / 1 : "0" + tmpDuration / 1); tmpDuration %= 1; return str; } /** * 通过日期来确定星座 * * @param mouth * @param day * @return */ public static String getStarSeat(int mouth, int day) { String starSeat = null; if ((mouth == 3 && day >= 21) || (mouth == 4 && day <= 19)) { starSeat = "白羊座"; } else if ((mouth == 4 && day >= 20) || (mouth == 5 && day <= 20)) { starSeat = "金牛座"; } else if ((mouth == 5 && day >= 21) || (mouth == 6 && day <= 21)) { starSeat = "双子座"; } else if ((mouth == 6 && day >= 22) || (mouth == 7 && day <= 22)) { starSeat = "巨蟹座"; } else if ((mouth == 7 && day >= 23) || (mouth == 8 && day <= 22)) { starSeat = "狮子座"; } else if ((mouth == 8 && day >= 23) || (mouth == 9 && day <= 22)) { starSeat = "处女座"; } else if ((mouth == 9 && day >= 23) || (mouth == 10 && day <= 23)) { starSeat = "天秤座"; } else if ((mouth == 10 && day >= 24) || (mouth == 11 && day <= 22)) { starSeat = "天蝎座"; } else if ((mouth == 11 && day >= 23) || (mouth == 12 && day <= 21)) { starSeat = "射手座"; } else if ((mouth == 12 && day >= 22) || (mouth == 1 && day <= 19)) { starSeat = "摩羯座"; } else if ((mouth == 1 && day >= 20) || (mouth == 2 && day <= 18)) { starSeat = "水瓶座"; } else { starSeat = "双鱼座"; } return starSeat; } /** * 返回聊天时间 * @return */ public static String getChatTimeForShow(long time){ if(TimeUtil.isToday(time)){ return TimeUtil.getStringByFormat(time, TimeUtil.dateFormatHMofChinese); }else{ return TimeUtil.getStringByFormat(time, TimeUtil.dateFormatMDHMofChinese); } } /** * 获取指定时间的毫秒值 */ public static long getDatelongMills(String fomat, String dateStr){ SimpleDateFormat sdf = new SimpleDateFormat(fomat); Date date = null; try { date = sdf.parse(dateStr); } catch (ParseException e) { e.printStackTrace(); } long longDate = date.getTime(); return longDate; } /** * 两个日期比较 * @param DATE1 * @param DATE2 * @return */ public static int compare_date(String DATE1, String DATE2) { DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.CHINA); try { Date dt1 = df.parse(DATE1); Date dt2 = df.parse(DATE2); if (dt1.getTime() - dt2.getTime()>0) {//date1>date2 return 1; } else { return -1; } } catch (Exception exception) { exception.printStackTrace(); } return 0; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/utils/ToastUitl.java ================================================ package com.lvr.livecircle.utils; import android.content.Context; import android.text.TextUtils; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.lvr.livecircle.R; import com.lvr.livecircle.base.BaseApplication; /** * Toast统一管理类 */ public class ToastUitl { private static Toast toast; private static Toast toast2; private static Toast initToast(CharSequence message, int duration) { if (toast == null) { toast = Toast.makeText(BaseApplication.getAppContext(), message, duration); } else { toast.setText(message); toast.setDuration(duration); } return toast; } /** * 短时间显示Toast * * @param message */ public static void showShort(CharSequence message) { initToast(message, Toast.LENGTH_SHORT).show(); } /** * 短时间显示Toast * * @param strResId */ public static void showShort(int strResId) { // Toast.makeText(context, strResId, Toast.LENGTH_SHORT).show(); initToast(BaseApplication.getAppContext().getResources().getText(strResId), Toast.LENGTH_SHORT).show(); } /** * 长时间显示Toast * * @param message */ public static void showLong(CharSequence message) { initToast(message, Toast.LENGTH_LONG).show(); } /** * 长时间显示Toast * * @param strResId */ public static void showLong(int strResId) { initToast(BaseApplication.getAppContext().getResources().getText(strResId), Toast.LENGTH_LONG).show(); } /** * 自定义显示Toast时间 * * @param message * @param duration */ public static void show(CharSequence message, int duration) { initToast(message, duration).show(); } /** * 自定义显示Toast时间 * * @param context * @param strResId * @param duration */ public static void show(Context context, int strResId, int duration) { initToast(context.getResources().getText(strResId), duration).show(); } /** * 显示有image的toast * * @param tvStr * @param imageResource * @return */ public static Toast showToastWithImg(final String tvStr, final int imageResource) { if (toast2 == null) { toast2 = new Toast(BaseApplication.getAppContext()); } View view = LayoutInflater.from(BaseApplication.getAppContext()).inflate(R.layout.toast_custom, null); TextView tv = (TextView) view.findViewById(R.id.toast_custom_tv); tv.setText(TextUtils.isEmpty(tvStr) ? "" : tvStr); ImageView iv = (ImageView) view.findViewById(R.id.toast_custom_iv); if (imageResource > 0) { iv.setVisibility(View.VISIBLE); iv.setImageResource(imageResource); } else { iv.setVisibility(View.GONE); } toast2.setView(view); toast2.setGravity(Gravity.CENTER, 0, 0); toast2.show(); return toast2; } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/video/VideoFragment.java ================================================ package com.lvr.livecircle.video; import com.lvr.livecircle.R; import com.lvr.livecircle.base.BaseFragment; /** * Created by lvr on 2017/2/6. */ public class VideoFragment extends BaseFragment { @Override protected int getLayoutResource() { return R.layout.fragment_video; } @Override protected void initView() { } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/widget/ClassicRefreshHeaderView.java ================================================ package com.lvr.livecircle.widget; import android.content.Context; import android.util.AttributeSet; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; import com.aspsine.irecyclerview.RefreshTrigger; import com.lvr.livecircle.R; public class ClassicRefreshHeaderView extends RelativeLayout implements RefreshTrigger { private ImageView ivArrow; private ImageView ivSuccess; private TextView tvRefresh; private ProgressBar progressBar; private Animation rotateUp; private Animation rotateDown; private boolean rotated = false; private int mHeight; public ClassicRefreshHeaderView(Context context) { this(context, null); } public ClassicRefreshHeaderView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ClassicRefreshHeaderView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); inflate(context, R.layout.layout_irecyclerview_classic_refresh_header_view, this); tvRefresh = (TextView) findViewById(R.id.tvRefresh); ivArrow = (ImageView) findViewById(R.id.ivArrow); ivSuccess = (ImageView) findViewById(R.id.ivSuccess); progressBar = (ProgressBar) findViewById(R.id.progressbar); rotateUp = AnimationUtils.loadAnimation(context, R.anim.rotate_up); rotateDown = AnimationUtils.loadAnimation(context, R.anim.rotate_down); } @Override public void onStart(boolean automatic, int headerHeight, int finalHeight) { this.mHeight = headerHeight; progressBar.setIndeterminate(false); } @Override public void onMove(boolean isComplete, boolean automatic, int moved) { if (!isComplete) { ivArrow.setVisibility(VISIBLE); progressBar.setVisibility(GONE); ivSuccess.setVisibility(GONE); if (moved <= mHeight) { if (rotated) { ivArrow.clearAnimation(); ivArrow.startAnimation(rotateDown); rotated = false; } tvRefresh.setText("下拉刷新"); } else { tvRefresh.setText("释放刷新"); if (!rotated) { ivArrow.clearAnimation(); ivArrow.startAnimation(rotateUp); rotated = true; } } } } @Override public void onRefresh() { ivSuccess.setVisibility(GONE); ivArrow.clearAnimation(); ivArrow.setVisibility(GONE); progressBar.setVisibility(VISIBLE); tvRefresh.setText("正在刷新"); } @Override public void onRelease() { } @Override public void onComplete() { rotated = false; ivSuccess.setVisibility(VISIBLE); ivArrow.clearAnimation(); ivArrow.setVisibility(GONE); progressBar.setVisibility(GONE); tvRefresh.setText("刷新完成"); } @Override public void onReset() { rotated = false; ivSuccess.setVisibility(GONE); ivArrow.clearAnimation(); ivArrow.setVisibility(GONE); progressBar.setVisibility(GONE); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/widget/ItemDragHelperCallback.java ================================================ /* * Copyright (c) 2016 咖枯 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.lvr.livecircle.widget; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.support.v7.widget.helper.ItemTouchHelper; public class ItemDragHelperCallback extends ItemTouchHelper.Callback { private OnItemMoveListener mOnItemMoveListener; private boolean mIsLongPressEnabled; public void setLongPressEnabled(boolean longPressEnabled) { mIsLongPressEnabled = longPressEnabled; } public interface OnItemMoveListener { boolean onItemMove(int fromPosition, int toPosition); } //相当于 set 设置监听 传入ChannelAdapter中的OnItemMoveListener对象 public ItemDragHelperCallback(OnItemMoveListener onItemMoveListener) { mOnItemMoveListener = onItemMoveListener; } //返回true 允许拖拽 @Override public boolean isLongPressDragEnabled() { return mIsLongPressEnabled; } @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { //根据recyclerView的布局,进行设置拖拽的方向 int dragFlags = setDragFlags(recyclerView); //不允许进行滑动 int swipeFlags = 0; return makeMovementFlags(dragFlags, swipeFlags); } private int setDragFlags(RecyclerView recyclerView) { int dragFlags; RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); if (layoutManager instanceof GridLayoutManager || layoutManager instanceof StaggeredGridLayoutManager) { dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; } else { dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; } return dragFlags; } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { return mOnItemMoveListener.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition()); } @Override public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { super.clearView(recyclerView, viewHolder); } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/widget/LoadMoreFooterView.java ================================================ package com.lvr.livecircle.widget; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.FrameLayout; import com.lvr.livecircle.R; public class LoadMoreFooterView extends FrameLayout { private Status mStatus; private View mLoadingView; private View mErrorView; private View mTheEndView; private OnRetryListener mOnRetryListener; public LoadMoreFooterView(Context context) { this(context, null); } public LoadMoreFooterView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public LoadMoreFooterView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); LayoutInflater.from(context).inflate(R.layout.layout_irecyclerview_load_more_footer_view, this, true); mLoadingView = findViewById(R.id.loadingView); mErrorView = findViewById(R.id.errorView); mTheEndView = findViewById(R.id.theEndView); mErrorView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mOnRetryListener != null) { mOnRetryListener.onRetry(LoadMoreFooterView.this); } } }); setStatus(Status.GONE); } public void setOnRetryListener(OnRetryListener listener) { this.mOnRetryListener = listener; } public Status getStatus() { return mStatus; } public void setStatus(Status status) { this.mStatus = status; change(); } public boolean canLoadMore() { return mStatus == Status.GONE || mStatus == Status.ERROR; } private void change() { switch (mStatus) { case GONE: mLoadingView.setVisibility(GONE); mErrorView.setVisibility(GONE); mTheEndView.setVisibility(GONE); break; case LOADING: mLoadingView.setVisibility(VISIBLE); mErrorView.setVisibility(GONE); mTheEndView.setVisibility(GONE); break; case ERROR: mLoadingView.setVisibility(GONE); mErrorView.setVisibility(VISIBLE); mTheEndView.setVisibility(GONE); break; case THE_END: mLoadingView.setVisibility(GONE); mErrorView.setVisibility(GONE); mTheEndView.setVisibility(VISIBLE); break; } } public enum Status { GONE, LOADING, ERROR, THE_END } public interface OnRetryListener { void onRetry(LoadMoreFooterView view); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/widget/LoadingDialog.java ================================================ package com.lvr.livecircle.widget; import android.app.Activity; import android.app.Dialog; import android.view.LayoutInflater; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; import com.lvr.livecircle.R; public class LoadingDialog { /** 加载数据对话框 */ private static Dialog mLoadingDialog; /** * 显示加载对话框 * @param context 上下文 * @param msg 对话框显示内容 * @param cancelable 对话框是否可以取消 */ public static Dialog showDialogForLoading(Activity context, String msg, boolean cancelable) { View view = LayoutInflater.from(context).inflate(R.layout.dialog_loading, null); TextView loadingText = (TextView)view.findViewById(R.id.id_tv_loading_dialog_text); loadingText.setText(msg); mLoadingDialog = new Dialog(context, R.style.CustomProgressDialog); mLoadingDialog.setCancelable(cancelable); mLoadingDialog.setCanceledOnTouchOutside(false); mLoadingDialog.setContentView(view, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)); mLoadingDialog.show(); return mLoadingDialog; } public static Dialog showDialogForLoading(Activity context) { View view = LayoutInflater.from(context).inflate(R.layout.dialog_loading, null); TextView loadingText = (TextView)view.findViewById(R.id.id_tv_loading_dialog_text); loadingText.setText("加载中..."); mLoadingDialog = new Dialog(context, R.style.CustomProgressDialog); mLoadingDialog.setCancelable(true); mLoadingDialog.setCanceledOnTouchOutside(false); mLoadingDialog.setContentView(view, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)); mLoadingDialog.show(); return mLoadingDialog; } /** * 关闭加载对话框 */ public static void cancelDialogForLoading() { if(mLoadingDialog != null) { mLoadingDialog.cancel(); } } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/widget/LoadingTip.java ================================================ package com.lvr.livecircle.widget; import android.annotation.TargetApi; import android.content.Context; import android.os.Build; import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.TextView; import com.lvr.livecircle.R; /** * 加载页面内嵌提示 */ public class LoadingTip extends LinearLayout { private ImageView img_tip_logo; private ProgressBar progress; private TextView tv_tips; private Button bt_operate; private String errorMsg; private onReloadListener onReloadListener; public LoadingTip(Context context) { super(context); initView(context); } public LoadingTip(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } public LoadingTip(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(context); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public LoadingTip(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); initView(context); } //分为服务器失败,网络加载失败、数据为空、加载中、完成四种状态 public static enum LoadStatus { sereverError,error, empty, loading,finish } private void initView(Context context) { View.inflate(context, R.layout.dialog_loading_tip, this); img_tip_logo = (ImageView) findViewById(R.id.img_tip_logo); progress = (ProgressBar) findViewById(R.id.progress); tv_tips = (TextView) findViewById(R.id.tv_tips); bt_operate = (Button) findViewById(R.id.bt_operate); //重新尝试 bt_operate.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { if(onReloadListener!=null){ onReloadListener.reload(); } } }); setVisibility(View.GONE); } public void setTips(String tips){ if(tv_tips!=null){ tv_tips.setText(tips); } } /** * 根据状态显示不同的提示 * @param loadStatus */ public void setLoadingTip(LoadStatus loadStatus){ switch (loadStatus){ case empty: setVisibility(View.VISIBLE); img_tip_logo.setVisibility(View.VISIBLE); progress.setVisibility(View.GONE); tv_tips.setText(getContext().getText(R.string.empty).toString()); img_tip_logo.setImageResource(R.drawable.no_content_tip); break; case sereverError: setVisibility(View.VISIBLE); img_tip_logo.setVisibility(View.VISIBLE); progress.setVisibility(View.GONE); if (TextUtils.isEmpty(errorMsg)){ tv_tips.setText(getContext().getText(R.string.net_error).toString()); }else { tv_tips.setText(errorMsg); } img_tip_logo.setImageResource(R.drawable.ic_wrong); break; case error: setVisibility(View.VISIBLE); img_tip_logo.setVisibility(View.VISIBLE); progress.setVisibility(View.GONE); if (TextUtils.isEmpty(errorMsg)){ tv_tips.setText(getContext().getText(R.string.net_error).toString()); }else { tv_tips.setText(errorMsg); } img_tip_logo.setImageResource(R.drawable.ic_wifi_off); break; case loading: setVisibility(View.VISIBLE); img_tip_logo.setVisibility(View.GONE); progress.setVisibility(View.VISIBLE); tv_tips.setText(getContext().getText(R.string.loading).toString()); break; case finish: setVisibility(View.GONE); break; } } public void setOnReloadListener(onReloadListener onReloadListener){ this.onReloadListener=onReloadListener; } /** * 重新尝试接口 */ public interface onReloadListener{ void reload(); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/widget/ScrollAwareFABBehavior.java ================================================ /* * Copyright (c) 2016 咖枯 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.lvr.livecircle.widget; import android.content.Context; import android.support.design.widget.CoordinatorLayout; import android.support.design.widget.FloatingActionButton; import android.support.v4.view.ViewCompat; import android.util.AttributeSet; import android.view.View; public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior { public ScrollAwareFABBehavior(Context context, AttributeSet attrs) { super(); } @Override public boolean onStartNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child, final View directTargetChild, final View target, final int nestedScrollAxes) { // Ensure we react to vertical scrolling return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes); } @Override public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) { child.setVisibility(View.INVISIBLE); } else if (dyConsumed < 0 && child.getVisibility() ==View.INVISIBLE) { child.setVisibility(View.VISIBLE); } } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/widget/StatusBarView.java ================================================ package com.lvr.livecircle.widget; import android.content.Context; import android.util.AttributeSet; import android.view.View; /** * Created by Jaeger on 16/6/8. * * Email: chjie.jaeger@gmail.com * GitHub: https://github.com/laobie */ public class StatusBarView extends View { public StatusBarView(Context context, AttributeSet attrs) { super(context, attrs); } public StatusBarView(Context context) { super(context); } } ================================================ FILE: LiveCircle/app/src/main/java/com/lvr/livecircle/widget/URLImageGetter.java ================================================ /* * Copyright (c) 2016 咖枯 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.lvr.livecircle.widget; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.Html; import android.widget.TextView; import com.lvr.livecircle.R; import com.lvr.livecircle.api.ApiService; import com.lvr.livecircle.app.AppApplication; import com.lvr.livecircle.client.RetrofitClient; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Function; import io.reactivex.schedulers.Schedulers; import okhttp3.ResponseBody; /** * @author 咖枯 * @version 1.0 2016/6/19 */ public class URLImageGetter implements Html.ImageGetter { private TextView mTextView; private int mPicWidth; private String mNewsBody; private int mPicCount; private int mPicTotal; private static final String mFilePath = AppApplication.getAppContext().getCacheDir().getAbsolutePath(); public Disposable mDisposable; public URLImageGetter(TextView textView, String newsBody, int picTotal) { mTextView = textView; mPicWidth = mTextView.getWidth(); mNewsBody = newsBody; mPicTotal = picTotal; } @Override public Drawable getDrawable(final String source) { Drawable drawable; File file = new File(mFilePath, source.hashCode() + ""); if (file.exists()) { mPicCount++; drawable = getDrawableFromDisk(file); } else { drawable = getDrawableFromNet(source); } return drawable; } @Nullable private Drawable getDrawableFromDisk(File file) { Drawable drawable = Drawable.createFromPath(file.getAbsolutePath()); if (drawable != null) { int picHeight = calculatePicHeight(drawable); drawable.setBounds(0, 0, mPicWidth, picHeight); } return drawable; } private int calculatePicHeight(Drawable drawable) { float imgWidth = drawable.getIntrinsicWidth(); float imgHeight = drawable.getIntrinsicHeight(); float rate = imgHeight / imgWidth; return (int) (mPicWidth * rate); } @NonNull private Drawable getDrawableFromNet(final String source) { RetrofitClient retrofitClient = RetrofitClient.getInstance(AppApplication.getAppContext(), ApiService.NEWS_BASE_URL); ApiService api = retrofitClient.create(ApiService.class); api.getNewsBodyHtmlPhoto(source) .unsubscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .map(new Function() { @Override public Boolean apply(ResponseBody body) throws Exception { return WritePicToDisk(body, source); } }) .subscribe(new Observer() { @Override public void onError(Throwable e) { } @Override public void onComplete() { } @Override public void onSubscribe(Disposable d) { mDisposable = d; } @Override public void onNext(Boolean isLoadSuccess) { mPicCount++; if (isLoadSuccess && (mPicCount == mPicTotal - 1)) { mTextView.setText(Html.fromHtml(mNewsBody, URLImageGetter.this, null)); } } }); return createPicPlaceholder(); } @NonNull private Boolean WritePicToDisk(ResponseBody response, String source) { File file = new File(mFilePath, source.hashCode() + ""); InputStream in = null; FileOutputStream out = null; try { in = response.byteStream(); out = new FileOutputStream(file); byte[] buffer = new byte[1024]; int len; while ((len = in.read(buffer)) != -1) { out.write(buffer, 0, len); } return true; } catch (Exception e) { return false; } finally { try { if (in != null) { in.close(); } if (out != null) { out.close(); } } catch (IOException e) { } } } @SuppressWarnings("deprecation") @NonNull private Drawable createPicPlaceholder() { Drawable drawable; int color = R.color.white; drawable = new ColorDrawable(AppApplication.getAppContext().getResources().getColor(color)); drawable.setBounds(0, 0, mPicWidth, mPicWidth / 3); return drawable; } } ================================================ FILE: LiveCircle/app/src/main/res/anim/act_fade_in_center.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/anim/act_fade_out_center.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/anim/fade_in.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/anim/fade_out.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/anim/rotate_down.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/anim/rotate_up.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/anim/slide_in_left.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/anim/slide_in_right.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/anim/slide_out_left.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/anim/slide_out_right.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/drawable/loading_dialog_progressbar.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/drawable/selector_gray.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/drawable/shape_loading_dialog.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/drawable/tv_rounded_corners.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/layout/activity_main.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/layout/activity_news_channel.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/layout/activity_news_detail.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/layout/activity_news_photo_detail.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/layout/activty_splash.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/layout/app_bar.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/layout/dialog_loading.xml ================================================ ================================================ FILE: LiveCircle/app/src/main/res/layout/dialog_loading_tip.xml ================================================