《第一行代码》4.5碎片的最佳时间——简易版的新闻应用

public class News {
    private String title;
    private String content;

    public String getTitle() {
        return title;
    }

    public String getContent() {
        return content;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

先准备好一个新闻的实体类,News类,title,content分别表示标题和内容。

接着新建布局文件news_content _frag.xml,作为新闻内容的布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
 <LinearLayout
     android:id="@+id/visibility_layout"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
     android:visibility="invisible">
     <TextView
         android:id="@+id/news_title"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:gravity="center"
         android:padding="10dp"
         android:textSize="20sp"/>
     <View
         android:layout_width="match_parent"
         android:layout_height="1dp"
         android:background="#000"/>

     <TextView
         android:id="@+id/news_content"
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:layout_weight="1"
         android:padding="15dp"
         android:textSize="18sp" />
 </LinearLayout>
    <View
        android:layout_width="1dp"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:background="#000"/>

</RelativeLayout>

新闻内容布局由两部分组成,头部分显示新闻标题,正文部分显示新闻内容,中间用一条细线分开。

注意细线是通过View实现,

如图所示:

新建NewsContentFragment类,继承Fragment,代码如下:

public class NewsContentFragment extends Fragment {
    private View view;

    @Override
    //onCreateView()方法加载了news_content_frag布局


    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        view=inflater.inflate(R.layout.news_content_frag,container,false);
        return view;
    }
//refresh方法,将新闻的标题和内容显示在界面上。这里通过findViewById()方法分别获取到新闻标题和内容的控件,然后将方法传递进来的参数设置进去。


    public void refresh(String newsTitle,String newsContent){
        View visibilityLayout=view.findViewById(R.id.visibility_layout);
        visibilityLayout.setVisibility(View.VISIBLE);
        TextView newsTitleText=(TextView) view.findViewById(R.id.news_title);
        TextView newsContextText=(TextView) view.findViewById(R.id.news_content);
        newsTitleText.setText(newsTitle);//刷新新闻的标题
        newsContextText.setText(newsContent);//刷新新闻的内容
    }
}

至此,新闻的内容碎片和布局都已创建,但都是基于双页模式中使用。

因此,必须创建单页模式下使用的布局和碎片。新建一个NewsContentActivity活动,并将布局指定为news_content,(此处需注意:我的Android Studio版本上,当创建NewsContentActivity活动时,会默认创建一个布局,但名字不是news_content,此处可以改名,通过右击——Refactor——Rename,即可更改成news_content),

修改news_content.xml的代码;

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".NewsContentActivity">
    <fragment
        android:id="@+id/news_content_fragment"
        android:name="com.example.yt.fragmentpractice.NewsContentFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

android:name="com.example.yt.fragmentpractice.NewsContentFragment",直接在布局中引入NewsContentFragment,相当于把news_content_frag布局的内容自动加入进来。

修改NewsContentActivity代码;

public class NewsContentActivity extends AppCompatActivity {


    public static void actionStart(Context context,String newsTitle,String newsContent){
        Intent intent=new Intent(context,NewsContentActivity.class);
        intent.putExtra("news_title",newsTitle);
        intent.putExtra("news_content",newsContent);
        context.startActivity(intent);
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.news_content);
        String newsTitle=getIntent().getStringExtra("news_title");//获取传入的新闻标题
        String newsContent=getIntent().getStringExtra("news_content");//获取传入的新闻内容
        NewsContentFragment newsContentFragment=(NewsContentFragment)getSupportFragmentManager().findFragmentById(R.id.news_content_fragment);
        newsContentFragment.refresh(newsTitle,newsContent);
    }
}

额,这里提供了一个actionStart方法,此方法是启动活动的最佳方法,可以非常清晰的了解需要传递的数据,简化了启动活动的代码。(现在可能还有点糊涂,但先记着,之后的会用到)

这里的onCreate()方法,通过Intent获取传入的新闻标题和内容,然后调用FragmentManager的findFragmentById()方法得到了NewsContentFragment的实例,然后调用refresh()方法,并将新闻的标题和内容传入。

 

接下来创建一个用于显示新闻列表的布局,新建news_title_frag.xml。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/news_title_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

只有一个显示新闻列表的RecyclerView,还需要RecyclerView子项的布局,新建news_item.xml作为子项布局

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/news_title"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:maxLines="1"
    android:ellipsize="end"
    android:textSize="18sp"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:paddingTop="15dp"
    android:paddingBottom="15dp"/>

android:padding表示给控件的周围加上补白

android:ellipsize用于设定当文本内容超出控件宽度时,文本的缩略的方式,这里指定成end,表示在尾部进行缩略。

至此新闻列表和子项的布局已经创建好,接下来创建一个用于展示新闻的列表的地方。这里新建NewsTitleFragment作为展示新闻列表的碎片:

public class NewsTitleFragment extends Fragment {
    private boolean isTwoPane;

    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view=inflater.inflate(R.layout.nws_title_frag,container,false);

        RecyclerView newTitleRecyclerView=(RecyclerView)view.findViewById(R.id.news_title_recycler_view);
        LinearLayoutManager layoutManager=new LinearLayoutManager(getActivity());

        newTitleRecyclerView.setLayoutManager(layoutManager);
        NewsAdapter adapter=new NewsAdapter(getNews());
        newTitleRecyclerView.setAdapter(adapter);
        return view;
    }
    private List<News> getNews(){
        List<News> newsList=new ArrayList<>();
        for(int i=1;i<=50;i++){

            News news=new News();
            news.setTitle("This is news title "+i);
            news.setContent(getRandomLengthContent("This is news content "+i+"."));
            newsList.add(news);
        }
        return newsList;
    }
    private  String getRandomLengthContent(String content){
        Random random=new Random();
        int length=random.nextInt(20)+1;
        StringBuilder builder=new StringBuilder();
        for(int i=0;i<length;i++){
            builder.append(content);
        }
        return builder.toString();
    }
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if(getActivity().findViewById(R.id.news_content_layout)!=null){
            isTwoPane=true;
        }
        else {
            isTwoPane=false;
        }
    }
    class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder>{

        private List<News>mNewsList;
        class ViewHolder extends  RecyclerView.ViewHolder{

            TextView newsTitleText;
            public  ViewHolder(View view){
                super(view);
                newsTitleText=(TextView)view.findViewById(R.id.news_title);

            }
        }
        public  NewsAdapter(List<News> newsList){
            mNewsList=newsList;
        }

        @Override
        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.news_item, parent, false);
            final ViewHolder holder = new ViewHolder(view);
            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    News news = mNewsList.get(holder.getAdapterPosition());
                    if (isTwoPane) {
//如果是双页模式,则刷新NewsContentFragment中的内容

                        NewsContentFragment newsContentFragment = (NewsContentFragment) getFragmentManager().findFragmentById(R.id.news_content_fragment);
                        newsContentFragment.refresh(news.getTitle(), news.getContent());
                    } else {
//如果是单页模式,则直接启动NewsContentActivity
                        NewsContentActivity.actionStart(getActivity(), news.getTitle(), news.getContent());
                    }
                }
            });
            return holder;
        }

        @Override
        public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
         News news=mNewsList.get(position);
         holder.newsTitleText.setText(news.getTitle());
        }

        @Override
        public int getItemCount() {
            return mNewsList.size();
        }
    }
}

onCreateView加载了news_title_frag布局,onActivityCreated()方法,这个方法通过在活动中能否找到一个id为news_content_layout的View来判断当前是双页还是单页模式,因此我们需要让news_content_layout在双页模式中出现

首先修改activity_main.xml中的代码,在单页模式下,只会加载一个新闻的标题的碎片

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/news_title_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <fragment
        android:id="@+id/news_title_fragment"
        android:name="com.example.yt.fragmentpractice.NewsTitleFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>


</FrameLayout>

单页模式下只会显示新闻标题一栏;

然后新建layout-sw600dp文件夹,在此文件夹下新建一个activity_main.xml文件; 建的文件名写全,为activity_main.xml,否则会显示错误。

 

言归正传:activity_main.xml代码

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
   android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment
        android:id="@+id/news_title_fragment"
        android:name="com.example.yt.fragmentpractice.NewsTitleFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"/>
    <FrameLayout
        android:id="@+id/news_content_layout"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3">
        <fragment
            android:id="@+id/news_content_fragment"
            android:name="com.example.yt.fragmentpractice.NewsContentFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </FrameLayout>

</LinearLayout>

可见,在双页模式下我们同时引入了两个碎片,将新闻内容的碎片放在FrameLayout布局下,而这个布局的id是news_content_layout。因此,能找到这个id的时候就是双页模式,否则为单页模式。

最后一点,在NewsTitleFragment中通过RecyclerView将新闻列表展示出来,我们在NewsTitleFragment中新建一个内部类NewsAdapter来作为RecyclerView的适配器,onCreateView()方法中添加了RecyclerView标准的使用方法

分别在手机和平板上运行:

 

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YuannaY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值