手机平板要兼顾---探究碎片

  • 一、 碎片是什么?
  • 二、 碎片的简单介绍
    • 1. 碎片的简单用法
    • 2. 动态添加碎片
    • 3. 在碎片中模拟返回栈
    • 4. 碎片和活动之间进行通信
  • 三、 碎片的生命周期
    • 1. 碎片的状态和回调
    • 2. 体验碎片的生命周期
  • 四、 动态加载布局的技巧
    • 1. 使用限定符(Qualifiers)
    • 2. 使用最小宽度限定符
  • 五、 实践--简易版的新闻应用

为了解决平板和手机之间的视觉效果而产生,比如一些界面在手机上看起来非常美观,但在平板电脑上看上去就可能会有控件被过分拉长、元素之间空隙过大等情况。

一、 碎片是什么?

碎片(Fragment)是一种可以嵌入在活动当中的UI片段,他能让程序更加合理和充分地利用大屏幕空间,因而在平板上应用得非常广泛。
在手机中排放一个新闻列表,点击一个标题时,就打开另一个界面显示新闻详情信息。

在平板中,则使用两个碎片,将新闻列表界面和新闻详情页面分别放在两个碎片中,屏幕也就可以被充分利用起来了。

二、 碎片的简单介绍

首先创建一个平板模拟器

1. 碎片的简单用法

(1)新建左侧布局left_fragment.xml,右侧同样

(2)接着新建一个LeftFragment类,右侧同样,将button换成TextView

    <Buttonandroid:id="@+id/button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:text="Button"/>
</LinearLayout>

(3)修改activity_main.xml中的代码

    <fragmentandroid:id="@+id/left_fragment"android:name="com.example.fragmenttest.LeftFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"/><fragmentandroid:id="@+id/right_fragment"android:name="com.example.fragmenttest.RightFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"/>
</LinearLayout>

(4)结果如下所示

2. 动态添加碎片

上面已经学会了在布局文件中添加碎片的方法,我们可以在程序运行时动态地添加到活动中。根据具体情况来动态地添加碎片,可以将程序界面定制的更加多样化。
(1) 在上面的基础上,首先新建一个another_right_fragment.xml,并只是将上面的right_fragment.xml改变颜色
android:background=“#EED5B7”

(2) 新建一个AnthorRightFragment类,代码如下:
public class AnthorRightFragment extends Fragment {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    View view =inflater.inflate(R.layout.another_right_fragment,container,false);return view;
}

}

(3) 在活动.xml主页面中修改写文档部分,代码如下:

(4) 在FragmentLayout中添加内容,从而实现动态添加碎片的功能。修改MainActivity代码。
动态添加碎片分为五步:
1:创建待添加的碎片实例
2:获取 FragmentManager,并调用getSupportFragmentManager()
3:开启一个事务,并调用beginTransaction()开启
4:向容器添加或替换碎片,调用.replace()方法实现
5:commit()提交事务
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button button =(Button) findViewById(R.id.button);//点击左边的按钮,右边响应button.setOnClickListener(this);replaceFragment(new RightFragment());
}@Override
public void onClick(View v) {switch (v.getId()){case R.id.button:replaceFragment(new AnthorRightFragment());break;default:break;}
}private void replaceFragment(Fragment fragment){FragmentManager fragmentManager =getSupportFragmentManager();FragmentTransaction transaction =fragmentManager.beginTransaction();transaction.replace(R.id.right_layout,fragment);//向容器内添加或替换碎片transaction.commit();//提交事务
}

}

(5)结果如图所示,点击Button后,会变为右图所示

3. 在碎片中模拟返回栈

按back键回到上一个碎片,修改MainActivity,添加一个 transaction.addToBackStack(null);
private void replaceFragment(Fragment fragment){
FragmentManager fragmentManager =getSupportFragmentManager();
FragmentTransaction transaction =fragmentManager.beginTransaction();
transaction.replace(R.id.right_layout,fragment);//向容器内添加或替换碎片
transaction.addToBackStack(null);
transaction.commit();//提交事务
}

4. 碎片和活动之间进行通信

在活动中得到相应的碎片实例:调用FragmentManager的findFragmentById();方法
碎片中调用活动里的方法:MainActivity activity =(MainActivity)getActivity();

三、 碎片的生命周期

1. 碎片的状态和回调

(1) 运行状态
(2) 暂停状态
(3) 停止状态:进入停止状态的碎片对用户是完全不可见的,有可能被系统回收
(4) 销毁状态

碎片的回调
onAttach().当碎片和活动建立关联的时候调用
onCreateView().为碎片创建视图(加载布局)时调用
onActivityCreated().确保与碎片相关联的活动已创建完毕时调用
onDestroyView().当与碎片相关联的视图被移除的时候调用
onDetach(). 当碎片和活动解除关联的时候调用

2. 体验碎片的生命周期

修改RightFragment中的代码,如图所示:
public static final String TAG = “RightFragment”;

@Override
public void onAttach(@NonNull Context context) {super.onAttach(context);Log.d(TAG, "onAttach: 11");
}@Override
public void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);Log.d(TAG, "onCreate: ");
}
@Override
public void onStart() {super.onStart();Log.d(TAG, "onStart: ");
}@Override
public void onResume() {super.onResume();Log.d(TAG, "onResume: ");
}@Override
public void onPause() {super.onPause();Log.d(TAG, "onPause: ");
}@Override
public void onStop() {super.onStop();Log.d(TAG, "onStop: ");
}@Override
public void onDestroyView() {super.onDestroyView();Log.d(TAG, "onDestroyView: ");
}@Override
public void onDestroy() {super.onDestroy();Log.d(TAG, "onDestroy: ");
}@Override
public void onDetach() {super.onDetach();Log.d(TAG, "onDetach: ");
}@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {Log.d(TAG, "onCreateView: ");View view =inflater.inflate(R.layout.right_fragment,container,false);return view;
}

运行程序后,在打印日志的代码中能看到打印信息。

点击button按钮后,RightFragment就会进入销毁状态。

点击back键后,重新回到了运行状态。

再次按下Back退出程序,打印的信息如图所示。

四、 动态加载布局的技巧

1. 使用限定符(Qualifiers)

平板显示两页内容,但手机只能显示一页内容,如何判断使用双页模式还是单页模式呢?
(1) 首先在activity_main.xml中,修改left页面的代码,让他充满整个父布局。
android:layout_width=“match_parent”

(2) 新建layout-large文件夹,并新建activity_main.xml。代码如下。
(3) 其中large就是一个限定符,那些屏幕被认为是large的设备就会自动加载layout-large文件夹下的布局,而屏幕小的设备则会加载layout下的布局。


Android常见限定符

2. 使用最小宽度限定符

large限定符解决了单双页的问题,那么large到底指多大呢?
可以在res目录下新建layout-sw600dp文件夹,并新建activity_main.xml布局。
这就是说,当程序运行屏幕宽度大于600dp时候,会自动加载这个布局。

五、 实践–简易版的新闻应用

(1) 首先在app/build.gradle中添加依赖库
implementation ‘androidx.recyclerview:recyclerview:1.2.1’

(2) 新建News类
public class News {
private String title; //新闻标题
private String content;//新闻内容

public String getTitle() {return title;
}public void setTitle(String title) {this.title = title;
}public String getContent() {return content;
}public void setContent(String content) {this.content = content;
}

}

(3) 新建布局文件news_content_frag.xml,用于作为新闻内容的布局:
布局主要分为两部分,头部部分显示新闻标题,正文部分显示新闻内容,中间再使用一条细线(View)分隔开。

    <LinearLayoutandroid:id="@+id/visibility_layout"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:visibility="invisible"><TextViewandroid:id="@+id/news_title"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:padding="10dp"android:textSize="20sp"/><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:background="#000"/><TextViewandroid:id="@+id/news_content"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:padding="15dp"android:textSize="18sp"/></LinearLayout><Viewandroid:layout_width="1dp"android:layout_height="match_parent"android:background="#000"/>

(4) 新建NewsContentFragment类,继承自Fragment。
在onCreateView()方法,加载了news_content_frag布局。 refresh()方法是用于将新闻的标题和内容显示在界面上的。
public class NewsContentFragment extends Fragment {
private View view;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.news_content_frag, container, false);
return view;
}
public void refresh(String newsTitle, String newsContent) {
View visibiltyLayout = view.findViewById(R.id.visibility_layout);
visibiltyLayout.setVisibility(View.VISIBLE);
TextView newsTitleText = (TextView) view.findViewById(R.id.news_title);
TextView newsContentText = (TextView) view.findViewById(R.id.news_content);
newsTitleText.setText(newsTitle);//刷新新闻标题
newsContentText.setText(newsContent);//刷新新闻内容
}
}

(5) 上面所示,都是在双页模式中使用的,如果想在单页模式上使用的话,需要再创建一个活动,NewsContentActivity类,并将布局名称指定成news_content.xml.

(6) 在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);//刷新newsContentFragment界面
}

}

(7) 创建新闻列表布局,新建news_title_frag.xml,里面只有一个用于显示新闻列表的RecyclerView。

<androidx.recyclerview.widget.RecyclerView
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:id=“@+id/news_title_recycler_view”/>

(8) 新建news_item.xml作为recyclerView子项布局

(9) 新建NewsTitleFragment类,作为展示新闻列表的地方。
package com.example.fragmentbestpractice;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class NewsTitleFragment extends Fragment {

private boolean isTwoPane;class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> {private List<News> mNewsList;@NonNull@Overridepublic 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() {@Overridepublic void onClick(View v) {News news = mNewsList.get(holder.getAdapterPosition());if (isTwoPane) {NewsContentFragment newsContentFragment = (NewsContentFragment) getFragmentManager().findFragmentById(R.id.news_content_fragment);newsContentFragment.refresh(news.getTitle(), news.getContent());} else {NewsContentActivity.actionStart(getActivity(), news.getTitle(), news.getContent());}}});return holder;}@Overridepublic void onBindViewHolder(@NonNull ViewHolder holder, int position) {News news = mNewsList.get(position);holder.newsTitleText.setText(news.getTitle());}@Overridepublic int getItemCount() {return mNewsList.size();}class ViewHolder extends RecyclerView.ViewHolder {TextView newsTitleText;public ViewHolder(@NonNull View view) {super(view);newsTitleText = (TextView) view.findViewById(R.id.news_title);}}public NewsAdapter(List<News> newsList) {mNewsList = newsList;}
}@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.news_title_frag, container, false);RecyclerView newsTitleRecyclerView = (RecyclerView) view.findViewById(R.id.news_title_recycler_view);LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());newsTitleRecyclerView.setLayoutManager(layoutManager);NewsAdapter adapter = new NewsAdapter(getNews());newsTitleRecyclerView.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("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;}}

}

(10) 修改activity_main.xml中的代码

    <fragmentandroid:id="@+id/news_title_fragment"android:name="com.example.fragmentbestpractice.NewsTitleFragment"android:layout_width="match_parent"android:layout_height="match_parent"/>
</FrameLayout>

(11) 在layout-sw600dp文件夹中,新建一个activity_main.xml文件。

    <fragmentandroid:id="@+id/news_title_fragment"android:name="com.example.fragmentbestpractice.NewsTitleFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"tools:ignore="MissingConstraints" /><FrameLayoutandroid:id="@+id/news_content_layout"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="3"><fragmentandroid:id="@+id/news_content_fragment"android:name="com.example.fragmentbestpractice.NewsContentFragment"android:layout_width="match_parent"android:layout_height="match_parent" /></FrameLayout>
</LinearLayout>

(12) 在NewsTitleFragment中新增适配器。
下图为手机新闻

下图为平板新闻

Android--碎片相关推荐

  1. android碎片按钮,Android 碎片(Fragment)

    Android 碎片(Fragment) 碎片是活动的一部分,使得活动更加的模块化设计.我们可以认为碎片是一种子活动. 下面是关于碎片的重要知识点 - 碎片拥有自己的布局,自己的行为及自己的生命周期回 ...

  2. Android碎片化与兼容性问题的元凶

    Android碎片化是其发展中的一个计划内的必然结果,也从来就不是什么问题.真正的问题是不同Android系统的应用兼容性. Android的碎片化 Android的碎片化,是指它在发展的过程中,随着 ...

  3. android碎片,图说Android碎片

    图说Android碎片 http://img4.cache.netease.com/photo/0011/2012-05-31/82QL30CL2ERI0011.jpg http://img4.cac ...

  4. Android技术馆系列之:Android 碎片的介绍

    借用海子的一句诗来抒发一下感慨"每天喂马砍柴,面朝大海,春暖花开" Android 碎片(Fragment) 碎片是活动的一部分,是的活动更加的模块化设计.我们可以认为碎片是一种子 ...

  5. android碎片调用动态碎片,Android Training - 使用碎片创建一个动态UI

    为了能够在Android中创建动态和多窗口的用户界面,你需要封装UI组件和activity行为在不同的模块中,以便你可以在不同的activity间切换.你可以使用Fragment类创建这些模块,类似于 ...

  6. android碎片功能实现,Android 列表碎片

    Android 列表碎片 列表碎片的基本实现是用来在碎片中创建项目列表 实例 这个实例解释如何基于 ArrayAdapter 来创建列表碎片.让我们按照下面的步骤开始: 步骤 描述 1 使用 Andr ...

  7. Android碎片化难题:手游兼容性测试应该适配哪些机型?

    在中国上线的Android游戏的机型适配难度有多大?根据工信部数据,2014年全年的上市智能手机中,有1604款采用Android操作系统,出货量3.49亿部.这也就意味着2014年平均每天有5款新机 ...

  8. android碎片化的解决方法,解决 Android 设备碎片化--屏幕适配

    随着支持 Android 系统的设备(手机.平板.电视.手表)的增多,设备碎片化.品牌碎片化.系统碎片化.传感器碎片化和屏幕碎片化的程度也在不断地加深. 在当时初学 Android 的时候,就初步接触 ...

  9. android 碎片问题,Android碎片问题

    我正在使用Fragments来表示我的应用程序中的不同视图.在视图之间导航时,我使用以下代码替换片段: FragmentTransaction ft = getSupportFragmentManag ...

  10. 为防 Android 碎片化?Google 强迫开发者使用自有开发工具!

    作者 | 郭芮 出品 | CSDN(ID:CSDNnews) 前不久,因 Android 向华为"闭源"一事,Google 频频被推上风口浪尖,关于开源和操作系统的讨论也不绝于耳. ...

最新文章

  1. 裸辞后,从Android转战Web前端的学习以及求职之路
  2. Java黑皮书课后题第4章:*4.17(一个月的天数)编写一个程序,提示用户输入一个年份和一个月份名称的前3个字母(第一个字母使用大写形式),显示该月中的天数。如果月份非法则显示出错信息
  3. python excel 单元格格式_python设置单元格数值格式
  4. ios(safar/微信)返回不执行js
  5. Nginx 默认的日志类型
  6. dml操作mysql_数据库DML操作(DCL了解)
  7. java url参数值替换_修改url中参数的值
  8. 每天一个linux命令(25):chgrp命令
  9. JAVA语言程序设计(基础篇)第十版课后题答案(第一章)
  10. ASP实现倒计时功能
  11. Dubbo-接口数据序列化Serialization
  12. 三国志战略版:登庸令队伍_貂蝉与贾诩的武锋组合
  13. 用rpa必须会用python语言_几步教你用 Python 制作一个 RPA 机器人!
  14. linux 内存告警门限,H3C LA系列无线网关 配置指导(V7)-R0304-6W100_基础配置指导_设备管理配置-新华三集团-H3C...
  15. python 获取csv的列数_Python读取excel的两种方法
  16. 微信小程序---搜索功能并跳转搜索结果页面
  17. 全角和半角相互转换(C语言实现)
  18. Placement blockage types
  19. 麻将判断几步入听算法
  20. 自认为最中肯的“北大”评价吧(转)

热门文章

  1. Android屏幕录像转换GIF解决方案
  2. 对口计算机高考考纲占比,计算机对口高考考纲.doc
  3. FTP客户端FlashFXP使用方法
  4. java开发150个建议
  5. 李玉婷MYSQL进阶02:条件查询
  6. 为什么按照“阿法狗”的思路去实现人工智能是歧路
  7. 年轻的时候应该去漂泊
  8. JAVA练习14-十进制数转二进制数、掷骰子游戏
  9. 免费代理IP的四大弊端
  10. yii2的加密解密那些事儿