当前位置:   article > 正文

Android Fragment实践之简易的新闻应用_基于fragment的新闻客户端应用

基于fragment的新闻客户端应用

基本概念

Fragment,简称碎片,是Android 3.0(API 11)提出的,为了兼容低版本,support-v4库中也开发了一套Fragment API,最低兼容Android 1.6。

过去support-v4库是一个jar包,24.2.0版本开始,将support-v4库模块化为多个jar包,包含:support-fragment, support-ui, support-media-compat等,这么做是为了减少APK包大小,你需要用哪个模块就引入哪个模块。

如果想引入整个support-v4库,则compile 'com.android.support:support-v4:24.2.1',如果只想引入support-fragment库,则com.android.support:support-fragment:24.2.1

  • Fragment是依赖于Activity的,不能独立存在的。
  • 一个Activity里可以有多个Fragment。
  • 一个Fragment可以被多个Activity重用。
  • Fragment有自己的生命周期,并能接收输入事件。
  • 我们能在Activity运行时动态地添加或删除Fragment。

Fragment的优势有以下几点:

  • 模块化(Modularity):我们不必把所有代码全部写在Activity中,而是把代码写在各自的Fragment中。
  • 可重用(Reusability):多个Activity可以重用一个Fragment。
  • 可适配(Adaptability):根据硬件的屏幕尺寸、屏幕方向,能够方便地实现不同的布局,这样用户体验更好。

Demo:FragmentBestPractice兼容平板和手机的一个简易的新闻应用

View层:

双页模式下新闻内容部分的布局:news_fragment_frag.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!--新闻内容布局-->
  3. <RelativeLayout
  4. xmlns:android="http://schemas.android.com/apk/res/android"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent">
  7. <LinearLayout
  8. android:id="@+id/visibility_layout"
  9. android:layout_width="match_parent"
  10. android:layout_height="match_parent"
  11. android:orientation="vertical"
  12. android:visibility="invisible">
  13. <TextView
  14. android:id="@+id/news_title"
  15. android:gravity="center_horizontal|center_vertical"
  16. android:layout_width="match_parent"
  17. android:layout_height="50dp" />
  18. <View
  19. android:layout_width="match_parent"
  20. android:layout_height="1dp"
  21. android:background="#000"/>
  22. <TextView
  23. android:id="@+id/news_content"
  24. android:layout_width="match_parent"
  25. android:layout_height="0dp"
  26. android:layout_weight="1"
  27. android:padding="15dp"
  28. android:textSize="18sp"/>
  29. </LinearLayout>
  30. <View
  31. android:layout_width="1dp"
  32. android:layout_height="match_parent"
  33. android:layout_alignParentLeft="true"
  34. android:background="#000"
  35. android:layout_alignParentStart="true" />
  36. </RelativeLayout>

单页模式下新闻内容部分的布局activity_news_content.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!--单页新闻内容布局-->
  3. <LinearLayout
  4. xmlns:android="http://schemas.android.com/apk/res/android"
  5. xmlns:app="http://schemas.android.com/apk/res-auto"
  6. xmlns:tools="http://schemas.android.com/tools"
  7. android:orientation="vertical"
  8. android:layout_width="match_parent"
  9. android:layout_height="match_parent"
  10. tools:context=".Control.NewsContentActivity">
  11. <fragment
  12. android:id="@+id/news_content_fragment"
  13. android:name="com.example.dpl.fragmentbestpractice.Control.NewsContentFragment"
  14. android:layout_width="match_parent"
  15. android:layout_height="match_parent"/>
  16. </LinearLayout>

两种模式下共用新闻标题列表的布局news_title_frag.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical">
  6. <android.support.v7.widget.RecyclerView
  7. android:id="@+id/news_title_recycler_view"
  8. android:layout_width="match_parent"
  9. android:layout_height="match_parent"
  10. android:layout_gravity="center_horizontal"
  11. android:background="#1C1C1C" />
  12. </LinearLayout>

 新闻标题列表的子布局news_item.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <TextView
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:id="@+id/news_title"
  5. android:layout_width="match_parent"
  6. android:layout_height="wrap_content"
  7. android:maxLines="1"
  8. android:ellipsize="end"
  9. android:textSize="25sp"
  10. android:textColor="#fff"
  11. android:paddingRight="10dp"
  12. android:paddingLeft="10dp"
  13. android:paddingBottom="15dp"
  14. android:paddingTop="15dp"
  15. />

 单页模式下,只加载一个新闻标题的碎片布局:activity_main.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!--单页模式页面碎片-->
  3. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  4. xmlns:app="http://schemas.android.com/apk/res-auto"
  5. xmlns:tools="http://schemas.android.com/tools"
  6. android:id="@+id/news_title_layout"
  7. android:layout_width="match_parent"
  8. android:layout_height="match_parent"
  9. tools:context=".Control.MainActivity">
  10. <fragment
  11. android:id="@+id/news_title_fragment"
  12. android:name="com.example.dpl.fragmentbestpractice.Control.NewsTitleFragment"
  13. android:layout_height="match_parent"
  14. android:layout_width="match_parent"/>
  15. </FrameLayout>

 通过限定符的方式系统区分运行的大屏幕还是小屏幕,新建适配大屏幕的布局文件夹layout-sw600dp,在其下创建activity_main.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!--双页模式页面碎片-->
  3. <LinearLayout
  4. xmlns:android="http://schemas.android.com/apk/res/android"
  5. android:orientation="horizontal"
  6. android:layout_width="match_parent"
  7. android:layout_height="match_parent"
  8. android:baselineAligned="false">
  9. <fragment
  10. android:id="@+id/news_title_fragment"
  11. android:name="com.example.dpl.fragmentbestpractice.Control.NewsTitleFragment"
  12. android:layout_width="0dp"
  13. android:layout_height="match_parent"
  14. android:layout_weight="1"/>
  15. <FrameLayout
  16. android:id="@+id/news_content_layout"
  17. android:layout_width="0dp"
  18. android:layout_height="match_parent"
  19. android:layout_weight="3">
  20. <fragment
  21. android:id="@+id/news_content_fragment"
  22. android:name="com.example.dpl.fragmentbestpractice.Control.NewsContentFragment"
  23. android:layout_width="match_parent"
  24. android:layout_height="match_parent"/>
  25. </FrameLayout>
  26. </LinearLayout>

Model层: 

 新闻类:News.java

  1. public class News {
  2. private String title;
  3. private String content;
  4. public void setContent(String content) {
  5. this.content = content;
  6. }
  7. public String getContent() {
  8. return content;
  9. }
  10. public void setTitle(String title) {
  11. this.title = title;
  12. }
  13. public String getTitle() {
  14. return title;
  15. }
  16. }

 Control层:

创建两种模式下共用新闻内容的Fragment:NewsContentFragment.java:

  1. public class NewsContentFragment extends Fragment {
  2. private View view;
  3. @Nullable
  4. @Override
  5. public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  6. view=inflater.inflate(R.layout.news_content_frag,container,false);//获取布局
  7. return view;
  8. }
  9. /**
  10. * 将新闻内容和标题显示到界面上
  11. */
  12. public void refresh(String newsTitle,String newsContent){
  13. View visibilityLayout=view.findViewById(R.id.visibility_layout);//获取子布局
  14. visibilityLayout.setVisibility(View.VISIBLE);//布局设置为可见
  15. TextView newsTitleText= (TextView) view.findViewById(R.id.news_title);
  16. TextView newsContentText= (TextView) view.findViewById(R.id.news_content);
  17. newsTitleText.setText(newsTitle);//刷新标题
  18. newsContentText.setText(newsContent);//刷新内容
  19. }
  20. }

 单页模式下引用其上Fragment的Activity:NewsContentActivity.java:

  1. public class NewsContentActivity extends AppCompatActivity {
  2. public static void actionStart(Context context,String newsTitle,String newsContent){
  3. Intent intent=new Intent(context,NewsContentActivity.class);
  4. intent.putExtra("news_title",newsTitle);
  5. intent.putExtra("news_content",newsContent);
  6. context.startActivity(intent);
  7. }
  8. @Override
  9. protected void onCreate(Bundle savedInstanceState) {
  10. super.onCreate(savedInstanceState);
  11. setContentView(R.layout.activity_news_content);
  12. String newsTitle=getIntent().getStringExtra("news_title");//获取标题
  13. String newsContent=getIntent().getStringExtra("news_content");//获取内容
  14. NewsContentFragment newsContentFragment= (NewsContentFragment) getSupportFragmentManager().
  15. findFragmentById(R.id.news_content_fragment);
  16. newsContentFragment.refresh(newsTitle,newsContent);//刷新NewsContentFragment界面
  17. }
  18. }

两种模式下新闻标题部分的碎片NewsTitleFragment.java:

  1. public class NewsTitleFragment extends Fragment {
  2. private boolean isTwoPane;
  3. @Nullable
  4. @Override
  5. public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  6. View view = inflater.inflate(R.layout.news_title_frag, container, false);
  7. RecyclerView newsTitleRecyclerView= (RecyclerView) view.findViewById(R.id.news_title_recycler_view);
  8. LinearLayoutManager manager=new LinearLayoutManager(view.getContext());
  9. newsTitleRecyclerView.setLayoutManager(manager);
  10. NewsAdapter newsAdapter=new NewsAdapter(getNews());
  11. newsTitleRecyclerView.setAdapter(newsAdapter);
  12. return view;
  13. }
  14. private List<News> getNews() {//初始化标题列表
  15. List<News> newsList=new ArrayList<>();
  16. for (int i=1;i<=50;i++){
  17. News news=new News();
  18. news.setTitle("This is the title"+i);
  19. news.setContent(getRandomLengthContent("This is new content"+i+","));
  20. newsList.add(news);
  21. }
  22. return newsList;
  23. }
  24. private String getRandomLengthContent(String content){//随机添加内容
  25. Random random=new Random();
  26. int length=random.nextInt(20)+1;
  27. StringBuilder builder=new StringBuilder();
  28. for (int i=0;i<length;i++){
  29. builder.append(content);
  30. }
  31. return builder.toString();
  32. }
  33. @Override
  34. public void onActivityCreated(@Nullable Bundle savedInstanceState) {
  35. super.onActivityCreated(savedInstanceState);
  36. if (getActivity().findViewById(R.id.news_content_layout) != null) {
  37. isTwoPane = true; //可以找到news_content_layout时,显示双页模式
  38. } else {
  39. isTwoPane = false;//找不到new_content_layout时,显示单页模式
  40. }
  41. }
  42. class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> {
  43. private List<News> mNewsList;
  44. class ViewHolder extends RecyclerView.ViewHolder {
  45. TextView newsTitleText;
  46. public ViewHolder(@NonNull View itemView) {
  47. super(itemView);
  48. newsTitleText = (TextView) itemView.findViewById(R.id.news_title);
  49. }
  50. }
  51. private NewsAdapter(List<News> newsList) {
  52. mNewsList = newsList;
  53. }
  54. @NonNull
  55. @Override
  56. public ViewHolder onCreateViewHolder(@NonNull final ViewGroup viewGroup, final int i) {
  57. View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.news_item, viewGroup, false);
  58. final ViewHolder holder = new ViewHolder(view);
  59. view.setOnClickListener(new View.OnClickListener() {
  60. @Override
  61. public void onClick(View v) {
  62. News news = mNewsList.get(holder.getAdapterPosition());
  63. if (isTwoPane) {
  64. //如果是双页模式,刷新NewsContentFragment内容
  65. NewsContentFragment newsContentFragment = (NewsContentFragment) getFragmentManager()
  66. .findFragmentById(R.id.news_content_fragment);
  67. newsContentFragment.refresh(news.getTitle(), news.getContent());
  68. } else {
  69. //如果是单页模式,直接启动NewsContentActivity
  70. NewsContentActivity.actionStart(getActivity(), news.getTitle(), news.getContent());
  71. }
  72. }
  73. });
  74. return holder;
  75. }
  76. @Override
  77. public void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) {
  78. News news=mNewsList.get(i);
  79. viewHolder.newsTitleText.setText(news.getTitle());
  80. }
  81. @Override
  82. public int getItemCount() {
  83. return mNewsList.size();
  84. }
  85. }
  86. }

 主活动MainActivity.java:

  1. public class MainActivity extends AppCompatActivity {
  2. @Override
  3. protected void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. setContentView(R.layout.activity_main);
  6. }
  7. }

运行效果:

           

Github  源码

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/355329
推荐阅读
相关标签
  

闽ICP备14008679号