说说 Android 中如何实现同时兼容手机与平板的新闻应用界面
发布日期:2021-06-29 21:09:58 浏览次数:2 分类:技术文章

本文共 9239 字,大约阅读时间需要 30 分钟。

企业一般都会为应用提供手机版与 Pad 版的程序,我们可以利用 Android 碎片,编写出兼容手机与平板的应用程序。

因为新闻列表会用到 RecyclerView,所以我们先在 app/build.gradle 中引入依赖库:

dependencies {    compile fileTree(dir: 'libs', include: ['*.jar'])    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:24.2.1'    compile 'com.android.support:recyclerview-v7:24.2.1'    testCompile 'junit:junit:4.12'}

接下来,编写一个新闻的实体类:

public class News {
/** * 标题 */ private String title; /** * 内容 */ private String content; /** * 图片列表 */ private List
images; public News(String title, String content) { this.title = title; this.content = 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; } public List
getImages() { return images; } public void setImages(List
images) { this.images = images; } @Override public String toString() { return "News{" + "title='" + title + '\'' + ", content='" + content + '\'' + ", images=" + images + '}'; }}

新闻的实体类包含标题、内容和图片资源列表。

新建布局 news_content_frag.xml:

新闻内容的布局主要分为两个部分,头部显示新闻标题,正文显示新闻图片与内容,中间使用一条细线分隔开。细线采用 View 实现,把 View的宽与高都设置为 1dp,然后再通过 background 设置背景色即可。

然后再新建一个 NewsContentFragment 类,作为新闻内容的碎片:

public class NewsContentFragment extends Fragment {
private View view; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { view = inflater.inflate(R.layout.news_content_frag, container, false); return view; } /** * 更新 * * @param title 标题 * @param content 内容 * @param imageResId 图片资源 ID */ public void refresh(String title, String content, int imageResId) { view.findViewById(R.id.visibility_layout).setVisibility(View.VISIBLE); ((TextView) view.findViewById(R.id.news_title)).setText(title); ((ImageView) view.findViewById(R.id.news_image)).setImageResource(imageResId); ((TextView) view.findViewById(R.id.news_content)).setText(content); }}

这里提供了一个 refresh 方法,用于将新闻的标题、图片与内容显示在界面中。

这样就把新闻内容的碎片和布局创建好了,但它们都是运行在双页模式中的,所以我们还需创建一个活动 NewsContentActivity,用于单页模式中。

NewsContentActivity 的 布局文件 activity_news_content.xml:

这里充分发挥了代码的复用性,直接在布局中引入了 NewsContentFragment,这相当于把 news_content_frag 布局也自动加载了进来。

然后编写 NewsContentActivity 的代码:

public class NewsContentActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_news_content); //获取传入的数据 Intent intent = getIntent(); String title = intent.getStringExtra("title"); String content = intent.getStringExtra("content"); int imageResId = intent.getIntExtra("imageResId", 0); Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.news_content_fragment); ((NewsContentFragment) fragment).refresh(title, content, imageResId); } /** * 启动活动 * * @param context * @param title 标题 * @param content 内容 * @param imageResId 图片资源 ID */ public static void start(Context context, String title, String content, int imageResId) { Intent intent = new Intent(context, NewsContentActivity.class); intent.putExtra("title", title); intent.putExtra("content", content); intent.putExtra("imageResId", imageResId); context.startActivity(intent); }}

在 onCreate() 方法中,我们通过 Intent 获取传入的新闻标题、图片(这里为了简便,只取出图片列表的第一张图片)和内容,然后调用 FragmentManager 的 findFragmentById() 方法得到 NewsContentFragment 的实例,接着调用它的 refresh() 方法,传入相应的数据。

这里还为 Activity 定义了一个静态的启动方法 start 。

接着,创建显示新闻列表的布局 news_title_frag.xml:

这里只定义了一个用于显示新闻列表的 RecyclerView。

然后,新建 news_item.xml 作为 RecyclerView 子项的布局:

这里的布局采用 FrameLayout,然后使用 layout_gravity 来控制控件在布局中的对齐方式。

因为新闻列表和子项布局都创建好了,所以接下来就需要创建一个 NewsTitleFragment 作为展示新闻列表的碎片:

public class NewsTitleFragment extends Fragment {
private static final String TAG = "NewsTitleFragment"; /** * 是否为双页模式 */ private boolean isTwoPage; class NewsAdapter extends RecyclerView.Adapter
{ private List
newsList; class ViewHolder extends RecyclerView.ViewHolder { ImageView image; TextView titleText; public ViewHolder(View itemView) { super(itemView); titleText = (TextView) itemView.findViewById(R.id.news_title); image = (ImageView) itemView.findViewById(R.id.news_image); } } public NewsAdapter(List
data) { newsList = data; Log.d(TAG, "NewsAdapter: " + newsList); } @Override public ViewHolder onCreateViewHolder(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 = newsList.get(holder.getAdapterPosition()); Integer firstImageResId = news.getImages().get(0); if (isTwoPage) {
//双页模式,则直接刷新 NewsContentFragment 中的内容 ((NewsContentFragment) getFragmentManager().findFragmentById(R.id.news_content_fragment)).refresh(news.getTitle(), news.getContent(), firstImageResId); } else {
//单页模式,直接启动 NewsContentActivity 活动 NewsContentActivity.start(getActivity(), news.getTitle(), news.getContent(), firstImageResId); } } }); return holder; } @Override public void onBindViewHolder(ViewHolder holder, int position) { News news = newsList.get(position); holder.titleText.setText(news.getTitle()); holder.image.setImageResource(news.getImages().get(0));//取第一张图片 } @Override public int getItemCount() { return newsList.size(); } } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.news_title_frag, container, false); //为 RecyclerView 填充数据 RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.news_title_recycler_view); LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()); recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(new NewsAdapter(getNews())); return view; } private List
getNews() { List
list = new ArrayList<>(); addNews(list, R.drawable.new1, "在韩国上演的北京8分钟,中国首次用AI展示国家形象", "时隔14年后,奥林匹克再次进入北京时间。 刚刚结束的平昌冬奥会闭幕仪式上,张艺谋和团队用8分钟的时间,展示了国家形象并向全球发出邀请。与上次雅典8分钟不同的是,这次中国的形象有了更多科技元素。可能你不知道,整个展示过程其实是由人工智能和人类演员共同完成。今晚20点20分,2名大熊猫特使、22名北体大学生滑冰登场,紧随人类表演者亮相的还有24面冰雪通透的屏幕,按照长城砖比例设计,由24个机器人操作。整个表演也因此呈现“画中画”模式。"); addNews(list, R.drawable.new2, "AI的乌托邦!谷歌母公司正在建造超级智慧城市 ", "xxx"); addNews(list, R.drawable.new3, "诺基亚CEO:世界各大运营商加速 5G部署将提前一年 ", "xxx"); addNews(list, R.drawable.new4, "买房难,苹果新总部附近房屋平均售价116万美元 ", "xxx"); addNews(list, R.drawable.new5, "人民日报三问区块链:区分是技术创新还是集资创新 ", "xxx"); Log.d(TAG, "getNews: " + list); return list; } /** * 新增新闻 * * @param list * @param image 图片资源 * @param title 标题 * @param content 内容 */ private void addNews(List
list, int image, String title, String content) { News news = new News(title, content); List
images = new ArrayList<>(); images.add(image); news.setImages(images); list.add(news); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if (getActivity().findViewById(R.id.news_content_layout) != null) { //双页模式 isTwoPage = true; } else { isTwoPage = false; } }}
  1. 这里新建了一个内部类 NewsAdapter 来作为 RecyclerView 的适配器,因为内部类可以直接访问外部类的变量。

  2. 在 onCreateViewHolder 中,我们注册了点击事件,并根据当前所处的模式,来进行相应的逻辑处理。如果是单页模式,就启动一个新的活动来显示新闻内容;如果是双页模式,就更新新闻内容碎片中的内容。

  3. 在 onCreateView 方法中,把数据填充到 RecyclerView 中。

  4. 在 onActivityCreated 方法中,我们通过能否找到一个 news_content_layout 的 View 来判断当前处于的模式(双页或单页)。这是通过限定符来实现的:

主布局 activity_main.xml :

接着,在 res 目录下新建 layout-sw600dp 文件夹,并在这个文件夹下再新建一个布局

activity_main.xml :

这样当运行在屏幕宽度大于 600 dp 的设备上时,就会加载 news_content_fragment 布局,这样我们也就能判断出当前活动所处的模式啦O(∩_∩)O~

在手机模拟器中运行程序:

手机模拟器中的新闻列表

点击一条新闻:

手机模拟器中的新闻内容

然后在平板模拟器中运行程序:

平板模拟器运行效果

是不是很酷呀O(∩_∩)O~

转载地址:https://deniro.blog.csdn.net/article/details/79388849 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:说说 Android 的广播机制
下一篇:说说 Android 中动态加载布局的实用技巧

发表评论

最新留言

不错!
[***.144.177.141]2024年04月19日 12时57分43秒