开发语言:Java
开发工具:Android Studio
用到的一些控件,功能:
Tablayout,ViewPager(滑动切换菜单功能),Navigation,ToolBar
需要的外部包:
import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter;
注意!!!这里可能有的人版本是support-v4对应的包
添加了support-v4的包后发现build.gradle(Gradle Scripts文件夹下)有报错,
报错内容类似
Version 28 (intended for Android Pie and below) is the last version of the legacy support library
这是因为当前的AS已经不支持这些旧的包,因此可以将support-v4迁移到AndroidX,具体方法参考下面的文章或者自行搜索:
(174条消息) Version 28 (intended for Android Pie and below) is the last version of the legacy support library_谷哥的小弟的博客-CSDN博客
代码的源码仓库地址为
https://github.com/Cheesheep/AndroidExp2-NEWSApp
先放出最终的实现效果:
首页是国际新闻列表,总共有四个菜单
可以通过滑动或点击切换到其他菜单,可以看到不同页面的列表有一定的差异
点击查看其中一篇文章,可以看到本地是加载了一篇纯文本的内容
点击右上角的菜单列表,有另外两种查看该文章的方式,选择阅读原文
接着在app内显示出原文所在的网页
再次点击右上角菜单可以选择重新显示本地的文章
如果选择浏览器打开,就会跳转到浏览器并且显示该网页
回到主页面,左划或者点击左上角即可显示滑动菜单栏
打开后这里放了一些个人页面的信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4nWF9Sk9-1683948018508)(https://gitee.com/cheesheep/typora-photo-bed/raw/master/Timg/%E8%81%94%E6%83%B3%E6%88%AA%E5%9B%BE_20230422153131.png)]
不过菜单上面的功能都没有实现,只是做了样式,包括顶部的分享和个人页面按钮也是
顶部菜单栏的效果如图
涉及到的配置文件:
activity_main.xml :主活动页面
toolbar_menu:菜单栏图标(右侧的分享和个人页面的logo)
nav_header,xml :侧滑栏的头部信息(头像,昵称,联系方式)
left_drawer.xml:侧滑栏的菜单内容
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RVdj73Lq-1683948018509)(https://gitee.com/cheesheep/typora-photo-bed/raw/master/Timg/联想截图_20230422153131.png)]
侧滑栏如上
Java活动文件:
MainActivity.java :全部逻辑功能代码都在该活动当中
导入”NavigationView“的依赖
implementation 'com.android.support:design:29.0.1'
关于toolbar的各种设置,可以参考以下文章
(174条消息) Android Toolbar的使用详解_暗恋花香的博客-CSDN博客
设置为NoActionBar:
要使用toolbar,首先要去掉系统默认设置的ActionBar
在AndroidManifest.xml文件当中可以设置活动的主题,我们新建一个NoActionBar的主题,并且给我们需要配置toolBar的页面赋予这个主题即可
AndroidManifest.xml
themes.xml
最右边是noActionBar,内容设置了toolbar的背景颜色等等
配置toolBar
需要在activity_main.xml
文件当中放入toolBar,因为是在首页主活动放置toolBar
activity_main.xml部分代码
<androidx.appcompat.widget.Toolbar
android:id="@+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:titleTextColor="@color/white"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
除了在活动布局文件中放置toolbar,还需要一个菜单图标文件
toolbar_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/tool_msg"
android:icon="@drawable/share"
android:orderInCategory="80"
android:title="edit"
app:showAsAction="ifRoom|withText" />
<item
android:id="@+id/tool_user"
android:icon="@drawable/personal"
android:orderInCategory="80"
android:title="share"
app:showAsAction="ifRoom|withText" />
menu>
这里的配置和actionBar的menu绘制方法类似,唯一区别就是app:showAsAction
不同,该属性是Toolbar当中很关键的属性
其中四个不同的值的作用分别如下:
1)always:这个值会使菜单项一直显示在 ToolBar上。
2)ifRoom:如果有足够的空间,这个值会使菜单项显示在 Tool Bar上。
3)never:这个值会使菜单项永远都不出现在 ToolBar上。
4)withText:这个值会使菜单项和它的图标、菜单文本一起显示。一般和ifRoom一起通过“|”使用
app:showAsAction 属性值为 ifRoom|withText,表示如果有空间,那么就连同文字一起显示在标题栏中,否则就显示在菜单栏中。
而当app:showAsAction 属性值为 never时,该项作用为Menu不显示在菜单组件中。
这个文件后面我们会在activity的Java代码当中写入并且连接上
MainActivity.java
myToolbar.inflateMenu(R.menu.toolbar_menu);
添加NavigationView组件
(要使用该组件需要从外部导入design包,在前面有提到导入的具体的包)
将该组件添加到toolbar所在的活动的页面当中,这里就是activity_main.xml
activity_main.xml部分代码
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
--------
这里是该页面的其他布局文件,可以将整个布局文件代码放进去也是可以的
--------
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@color/colorPrimary"
app:headerLayout="@layout/nav_header"
app:menu="@menu/left_drawer" />
androidx.drawerlayout.widget.DrawerLayout>
这个菜单栏由于是侧滑出现的,所以放在整个布局的最外面,并且需要用DrawerLayout
包裹
注意看下面两个app的属性app:headerLayout
和app:menu
除此之外需要新建两个文件,一个是头部的代码,一个是菜单的部分
nav_header.xml
这里代码就不全部放出来了,给出效果
left_drawer.xml
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_item_user"
android:title="用户中心" />
<item
android:id="@+id/navigation_item_setting"
android:title="用户设置" />
<item
android:id="@+id/navigation_item_about"
android:title="关于我们" />
<item
android:id="@+id/navigation_item_logout"
android:title="注销" />
menu>
这个是菜单栏的页面,预览的效果和最终实现的效果是有差异的,不需要以预览的那个效果为准。
将nav_header和left_drawer结合之后,效果图片在上面有显示。
布局文件写好后,就是在Activity活动当中去实现我们的点击事件,以及一些组件的连接,布局的设置其他等等。
这里对应的Java代码全部都在MainActivity.java当中
ToolBar和侧边栏的初始化都在MainActivity的initToolBarView()
方法当中
初始化Toolbar:
MainActivity.java
private void initToolBarView() {
Toolbar myToolbar = findViewById(R.id.my_toolbar);
drawer_layout = findViewById(R.id.drawer_layout);
//将图标菜单文件添加到toolbar当中
myToolbar.inflateMenu(R.menu.toolbar_menu);
myToolbar.setTitle("Hello News");
//ToolBar的菜单的点击事件
myToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()){
default:
Toast.makeText(MainActivity.this, "菜单栏功能尚未开发", Toast.LENGTH_SHORT).show();
}
return true;
}
});
通过inflateMenu()
将右侧的菜单图标添加到toolbar当中。
然后设置这些图标的点击事件,只不过这里我没有去写对应的功能,要用到的话,识别item当中的id即可。
监听打开侧滑栏的按钮:
//配置侧滑栏,并且监听点击事件
myToolbar.setNavigationIcon(R.drawable.left_nav);
//打开侧滑栏的监听事件
myToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
drawer_layout.openDrawer(GravityCompat.START);
}
});
这样就可以通过点击打开侧滑栏了。
然后是侧滑栏的按钮的监听设置
//侧滑栏里面的菜单的监听事件
NavigationView mNavigationView = findViewById(R.id.nav_view);
mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
//侧滑栏中菜单的点击事件
}
});
这样就完成了toolbar的代码了
注意事项!:
想让Toolbar本身的inflateMenu生效,则必须删去以下类似代码!!!
不然会由于同时使用了ActionBar导致失效
//设置侧边栏
setSupportActionBar(myToolbar);
setTitle("Top News");//设置标题名称
getSupportActionBar().setDisplayHomeAsUpEnabled(true);//设置左边home键
getSupportActionBar().setHomeAsUpIndicator(R.drawable.left_nav);//更换home键样式
导航栏使用了上述三样东西结合
TabLayout:提供选项切换到不同的菜单
ViewPager:用于滑动切换到不同的菜单
Fragment:每个菜单显示的页面内容
涉及配置文件:
- activity_main.xml
- selected.xml (选中菜单的颜色设置)
- themes.xml (设置菜单的文件大小)
如果是旧版的话应当是导入support-v4里面的组件,这个时候可能会出现兼容问题
该菜单就是在首页展现的,因此所有布局文件也都在activity_main.xml当中
Tablayout+ViewPager控件:
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="80dp"
app:tabIndicatorColor="#ffffff"
app:tabIndicatorHeight="5dp"
app:tabTextColor="@color/white"
app:tabIconTint="@color/white"
app:tabSelectedTextColor="@color/white"
app:tabMode="fixed"
app:tabBackground="@drawable/selected"
app:tabTextAppearance="@style/MyTabLayoutTextAppearance"
/>
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
接着要在对应的页面的活动文件当中进行代码逻辑编写:
initViewPager()
private void initViewPager() {
mViewPager= (ViewPager) findViewById(R.id.viewPager);
MyFragmentPagerAdapter myFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(myFragmentPagerAdapter);
}
初始化viewPager,这里用到了一个新的类myFragmentPagerAdapter来初始化内容
该类需要继承FragmentPagerAdapter
,不过现在的android studio当中会显示该类已经被移除了,但是实际上还能用,不报错就行,不用管那个下划线,
FragmentPagerAdapter.java
public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
private String[] mTitles = new String[]{"国际", "体育", "生活","科学"};
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
//选择不同的菜单返回不同的Fragment页面
@Override
public Fragment getItem(int position) {
if (position == 1) {
return new SportNewsFragment();
} else if (position == 2) {
return new LifeNewsFragment();
}else if (position==3){
return new ScienceNewsFragment();
}
return new GlobalNewsFragment();
}
@Override
public int getCount() {return mTitles.length;}
//ViewPager与TabLayout绑定后,这里获取到PageTitle就是Tab的Text
@Override
public CharSequence getPageTitle(int position) {return mTitles[position];}
}
该类的代码也比较简短,根据需要的菜单数量,增加String数组元素个数和页面Fragment的数量就行
initTabLayoutView()
private void initTabLayoutView() {
//将TabLayout与ViewPager绑定在一起
TabLayout mTabLayout = (TabLayout) findViewById(R.id.tabLayout);
mTabLayout.setupWithViewPager(mViewPager);
//指定Tab的位置
TabLayout.Tab one = mTabLayout.getTabAt(0);
TabLayout.Tab two = mTabLayout.getTabAt(1);
TabLayout.Tab three = mTabLayout.getTabAt(2);
TabLayout.Tab four = mTabLayout.getTabAt(3);
//设置Tab的图标,假如不需要则把下面的代码删去
one.setIcon(R.drawable.global);
two.setIcon(R.drawable.soccer);
three.setIcon(R.drawable.life);
four.setIcon(R.drawable.science);
}
初始化TabLayout的设置,先将viewPager与TabLayout绑定在一起,然后设定对应的位置,最后设置图标,代码比较简单。
注意事项!:
其他xml文件的添加
这里说几个tablayout和viewPager要导入的一些其他的简短的xml文件
在themes.xml
(或styles.xml)文件当中要添加style name = MyTabLayoutTextAppearance
的样式
<style name="MyTabLayoutTextAppearance" parent="TextAppearance.AppCompat.Widget.ActionBar.Title">
- "android:textSize"
>18sp
- "android:textColor"
>@color/white
style>
还有在drawable文件下的 selected.xml
,用于展示被选中下菜单的颜色
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@color/TabBackGround"/>
<item android:drawable="@color/colorAccent"/>
selector>
涉及配置文件:
- fragment_global_news.xml 以及类似的四个文件(都是只有一个ListView)
- listView_item.xml以及相关的三种卡片布局
Java文件:
- GlobalNewsFragment.java (新闻列表的显示页面)
- NewsUtils.java (存放新闻的数据,例如标题,内容,url)
- NewsBean.java 新闻类(含标题,内容等)
由于四个新闻列表页面的布局是很像的,所以这里只拿其中一个举例
菜单的布局实现后,就要说下具体怎么实现新闻的列表内容了。
这里也是相对复杂一点的内容,因为该Fragment的代码内容比较多
但是布局文件xml是比较少的,或者说都是相似的
首先是Fragment碎片的布局
很简单,只有一个ListView在里面
fragment_global_news.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".newsListPage.GlobalNewsFragment">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/globalList"
/>
FrameLayout>
相对的其他的碎片文件也是一样
接着是list里面每个的样式该怎么实现呢?
这就要我们自己去涉及一个布局样式
listview_item.xml
这里代码较长,就只给出一个样式结合以及图片了
其他的样式例如有
接下来是将listView与自定义的卡片xml文件结合到一起
最终效果如下:
GlobalNewsFragment.java :
首先看看代码初始化的内容
public class GlobalNewsFragment extends Fragment {
private ListView lv;
private ArrayList<NewsBean> mList;
private View globalView;
private MainActivity mainActivity;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// 获取view,并且连接到主活动上面
globalView = inflater.inflate(R.layout.fragment_global_news, container, false);
mainActivity =(MainActivity) getActivity();
initUI();
initData();
initAdapter();
return globalView;
}
只需要一个onCreateVIew()是Fragment类当中的函数重载,其他的函数都是自己写出来的了。
初始化globalVIew的时候,获取了上面写好的配置文件fragment_global_news.xml
。
介绍三个初始化的函数内容
initUI():
监听列表每个item的点击事件
private void initUI() {
lv = (ListView) globalView.findViewById(R.id.globalList);
//设置点击事件监听
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//跳转到显示文章内容的活动
NewsBean bean = mList.get(position); NewsArticleContentActivity.actionStart(mainActivity,bean.title,bean.news_content,bean.news_url);
}
});
}
这里就是对每个列表的新闻卡片做了一个点击监听的事件,通过Intent跳转到文章的详情页面,经典的活动之间的跳转方法,不阐述了。
listView的获取连接了之前写的xml文件globalList.xml
当中
该意图已经封装好一个方法,只需要传固定的参数即可,分别是标题,内容,还有url链接。
文章的详情页面用一个Activity来实现,下一小节会讲到。
initData():
private void initData() {
mList = NewsUtils.getGlobalNews(mainActivity);
}
这里只调用了一个函数。
功能是将数据存到mList当中,方便后面用适配器Adapter调用
来看下NewsUtils类里面是怎么获取数据的
代码内容是比较简单直接的,虽然这里可以使用数据库的方式会更高效。
MewsBean里面的内容也只有简单的几个成员数据而已。
NewsBean:
public class NewsBean {
public String title;
public String des;
public Drawable icon;
public String news_url;
public String news_content;
}
initAdapter()
一行代码
private void initAdapter() {
lv.setAdapter(new GlobalNewsFragment.NewsAdapter());
}
setAdapter()方法是官方提供的,而里面的NewsAdapter()则需要我们去自定义实现
NewsAdpter类:
private class NewsAdapter extends BaseAdapter {
//适配器处理新闻列表
@Override
public int getCount() {
return mList.size();
}
@Override
public NewsBean getItem(int position) {
return mList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
GlobalNewsFragment.ViewHolder holder;
if (convertView == null) {//获取卡片的具体内容
holder = new GlobalNewsFragment.ViewHolder();
convertView = View.inflate(mainActivity.getApplicationContext(), R.layout.listview_item, null);
holder.tv_title = (TextView) convertView.findViewById(R.id.tv_title);
holder.tv_des = (TextView) convertView.findViewById(R.id.tv_des);
holder.iv_icon = (ImageView) convertView.findViewById(R.id.iv_icon);
convertView.setTag(holder);
} else {
holder = (GlobalNewsFragment.ViewHolder) convertView.getTag();
}
NewsBean item = getItem(position);
holder.tv_title.setText(item.title);
holder.tv_des.setText(item.des);
holder.iv_icon.setImageDrawable(item.icon);
return convertView;
}
}
该类继承了BaseAdapter,并对四个基本的方法进行了重载。
前面的三个都比较简单,根据名字就可以知道该方法调用的是一些基本的参数,例如获得列表当中的item等等。
最后的getView()比较长,主要是将数据传递到view布局上面
该方法可以看到调用了listview_item.xml
文件,想要不同的卡片样式,这里可以选中不同的布局文件。
holder类(直接定义在当前的Fragment类里面就行)
private static class ViewHolder {
TextView tv_title;
TextView tv_des;
ImageView iv_icon;
}
至此就完成了新闻列表样式的渲染和点击事件了。
相关配置文件:
- activity_news_article_content.xml
- article_open_browser.xml (设置右上角菜单内容)
java代码:
- NewsArticleContentActivity.java
该页面对应一个Activity,实现效果如下:
点击阅读原文,实际上是将当前页面的标题和内容隐藏,然后将webView显示出来。
根据页面内容可以看出,活动文件的内容应当有标题,内容,webView。
activity_news_article_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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".NewsArticleContentActivity">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="30sp"
android:fontFamily="sans-serif-black"
android:id="@+id/LocalTitle"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/cardview_dark_background"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:id="@+id/LocalContent"/>
<WebView
android:id="@+id/news_webView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
/>
LinearLayout>
ScrollView>
LinearLayout>
这里要用到scorllView来避免由于文章内容过多而页面无法下拉的问题。
一开始的WebView设置是不可见gone的,在运行后经过点击事件才能让其可见。
标题栏:
直接使用默认给出的actionBar
<style name="Theme.NEWSPage" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
标题当中的菜单栏
article_open_browser.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/article_open_webView"
android:title="阅读原文"/>
<item
android:id="@+id/article_open_browser"
android:title="用浏览器打开"/>
menu>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-txfrVbhX-1683948018512)(https://gitee.com/cheesheep/typora-photo-bed/raw/master/Timg/%E8%81%94%E6%83%B3%E6%88%AA%E5%9B%BE_20230423013518.png)]
相关代码都在NewsArticleContentActivity.java当中实现
首先看看初始化这个活动的时候用到的代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_news_article_content);
//设置标题栏内容
ActionBar actionBar = getSupportActionBar();
if(actionBar != null){
setTitle("Article");
actionBar.setHomeButtonEnabled(true);//设置左上角是否可以点击
actionBar.setDisplayHomeAsUpEnabled(true);//添加返回的图标
}
//设置文章内容
String newsTitle = getIntent().getStringExtra("news_title");
String newsContent = getIntent().getStringExtra("news_content");
articleUrl = getIntent().getStringExtra("news_url");
title = findViewById(R.id.LocalTitle);
content = findViewById(R.id.LocalContent);
title.setText(newsTitle);
content.setText(newsContent);
//设置webView内容
isArticleDisplayed = true;//从新闻列表进入文章的时候默认标志位为真
webView = findViewById(R.id.news_webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient(){
//重写这个方法解决重定向的问题
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
});
webView.loadUrl(articleUrl);
}
这里都是对activity_news_article_content.xml
布局的内容渲染。
代码分为三个步骤
setHomeBUttonEnabled()
和setDisplayHomeAsUpEnabled()
来设置顶部菜单栏左边的返回按钮。getIntent()
获取传过来的文章标题,内容和链接urls,并且给控件的内容设置相应的文本关于getIntent获得的数据,我在NewsArticleContentActivity类当中写了一个actionStart()
方法作为接口来接收Intent,提供给外部想要进入这个活动并且传参。
//提供一个传入意图的接口,用来跳转活动
public static void actionStart(Context context,String newsTitle,String newsContent,String newsUrl){
Intent intent = new Intent(context,NewsArticleContentActivity.class);
intent.putExtra("news_title",newsTitle);
intent.putExtra("news_content",newsContent);
intent.putExtra("news_url",newsUrl);
context.startActivity(intent);
}
创建右侧的顶部菜单栏:
//重写顶部菜单栏构造方法
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.article_open_browser,menu);
return super.onCreateOptionsMenu(menu);
}
这里的方法将之前写好的article_open_browser.xml
放到menu当中
最后是重写这个菜单里面的点击触发事件,代码如下
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
//设置返回按钮事件
finish();
return true;
case R.id.article_open_browser:
//设置浏览器打开事件
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse(articleUrl));//跳转到网页
startActivity(intent);
return true;
case R.id.article_open_webView:
//设置显示的显示网页内容
if(isArticleDisplayed){
title.setVisibility(View.GONE);
content.setVisibility(View.GONE);
webView.setVisibility(View.VISIBLE);
item.setTitle("本地文章");
}else {
title.setVisibility(View.VISIBLE);
content.setVisibility(View.VISIBLE);
webView.setVisibility(View.GONE);
item.setTitle("嵌入网页");
}
isArticleDisplayed = !isArticleDisplayed;
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
分别对返回键,显示网页内容,和跳转浏览器三个按键做了点击响应
对应下图的三个图标:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GzwPV83b-1683948018513)(https://gitee.com/cheesheep/typora-photo-bed/raw/master/Timg/%E8%81%94%E6%83%B3%E6%88%AA%E5%9B%BE_20230423091235.png)]
至此就完成了新闻文章详情页面的所有功能了。
注意事项!!:
webview无法正常打开的原因(这里指已经设置了uses-permission的情况):
可以参考这篇博客文章,完美解决问题
(174条消息) WebView出现net:ERR_CLEARTEXT_NOT_PERMITTED和net::ERR_UNKNOWN_URL_SCHEME错误的解决办法_飞鸭传书的博客-CSDN博客
主要原因有例如现在的版本不支持http格式的协议,因此需要在AndroidManifest.xml当中新添加一行
<uses-permission android:name="android.permission.INTERNET"/>
<application
........其他设置
android:usesCleartextTraffic="true"
......其他设置
>
接着会出现网页能够加载一下,然后就又发生了错误,这次提示net::ERR_UNKNOWN_URL_SCHEME错误
,这里是重定向的问题
解决方法是重写 shouldOverrideUrlLoading(WebView view, String url)
方法
webView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
});
return true
表示当前url即使是重定向url也不会再执行(除了在return true之前使用webview.loadUrl(url)除外,因为这个会重新加载)
return false
表示由系统执行url,直到不再执行此方法,即加载完重定向的ur(即具体的url,不再有重定向)。
或者采用上面博客给出的更加多判断的方法,可以对更多类型的页面的重定向进行判断
最后来说一下总结吧
本次可以说是安卓课上第一次做一个比较像App的实验了,之前的几次实验和作业也只是实现了一些简单的样式或者功能,而这次不仅要实现功能,UI也要进行一定的设计和美化。
个人认为工作量还是比较大的了,花费的时间也比较多,虽然最后做出来的功能其实并没有很多,但是因为是第一次做这种体量的安卓项目。
相比于以往接触到的小程序开发,web开发,android给人最大的不同就是需要配置大量的布局文件。在android当中,并不需要编写像html,css这样的文件去渲染页面,而是需要用xml文件来展现布局的页面内容,也并没有JavaScript这样的语言去对前端的样式,数据逻辑进行处理,而是靠Java语言来编写一个叫做活动(Activity)的东西,将数据连接到一起。
ndroid.permission.INTERNET"/>
android:usesCleartextTraffic=“true”
…其他设置
>
接着会出现网页能够加载一下,然后就又发生了错误,这次提示`net::ERR_UNKNOWN_URL_SCHEME错误`,这里是重定向的问题
解决方法是重写 `shouldOverrideUrlLoading(WebView view, String url)` 方法
webView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
});
- `return true` 表示当前url即使是重定向url也不会再执行(除了在return true之前使用webview.loadUrl(url)除外,因为这个会重新加载)
- `return false` 表示由系统执行url,直到不再执行此方法,即加载完重定向的ur(即具体的url,不再有重定向)。
或者采用上面博客给出的更加多判断的方法,可以对更多类型的页面的重定向进行判断
---
## 3. 总结
最后来说一下总结吧
本次可以说是安卓课上第一次做一个比较像App的实验了,之前的几次实验和作业也只是实现了一些简单的样式或者功能,而这次不仅要实现功能,UI也要进行一定的设计和美化。
个人认为工作量还是比较大的了,花费的时间也比较多,虽然最后做出来的功能其实并没有很多,但是因为是第一次做这种体量的安卓项目。
相比于以往接触到的小程序开发,web开发,android给人最大的不同就是需要配置大量的布局文件。在android当中,并不需要编写像html,css这样的文件去渲染页面,而是需要用xml文件来展现布局的页面内容,也并没有JavaScript这样的语言去对前端的样式,数据逻辑进行处理,而是靠Java语言来编写一个叫做活动(Activity)的东西,将数据连接到一起。