上次的功能完成了英雄名字、id、头像的下载并使用RecyclerView展示,

所以接下来就是点击每个英雄的caraview就能打开下一个活动进行英雄的介绍。先打开暴雪的官网查看有那些技能、故事、图片可供下载。首先是http://ow.blizzard.cn/heroes/

如果我想要看源氏的详细介绍,点击之后就打开了http://ow.blizzard.cn/heroes/genji,可以发现比上一个网站多了一个genji,genji就是源氏英文名也是上次获得的id。

详细介绍中有:

概况:角色类型 技能 攻击简介

故事:英雄简介,台词,背景故事

然后是html代码的分析了,大概想要的内容可分为三个部分:

1、英雄图片

这个src="http://overwatch.nos.netease.com/1/assets/images/hero/genji/full-portrait.png"可以得到英雄的全身照片.png

2、技能、角色类型

3、故事

所以相应的代码就是:

    Elements elements1 = doc.select(".hero-image"); //读取图片url
Elements elements2 = doc.select(".h2,.hero-detail-role-name"); //角色类型
Elements elements3 = doc.select(".hero-ability"); //读取技能
Elements elements4 = doc.select(".h5");//读取技能名字
Elements elements5 = doc.select(".hero-ability-descriptor");//读取技能描述
Elements elements6 = doc.select(".hero-detail-description");//读取英雄描述
Elements elements7 = doc.select(".hero-bio-copy");//读取英雄简介
Elements elements8 = doc.select(".h4,.hero-detail-title");//读取英雄台词
Elements elements9 = doc.select(".hero-bio-backstory");//读取英雄故事

大概分析就结束了,然后就是活动布局的设定了,

这部分的布局首先是一个可折叠的标题栏用于展示英雄图片,然后是一个可滑动切换的标签栏用于概况和故事的切换。

然后viewpager中将是两个Fragment分别展示概况和故事。

xml代码分别是:

活动的:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"> <android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="250dp"
android:fitsSystemWindows="true"
android:background="@drawable/timg2"> <android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collaping_toobar"
android:layout_width="match_parent"
android:layout_height="210dp"
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:contentScrim="@drawable/img2"
app:layout_scrollFlags="scroll|exitUntilCollapsed"> <ImageView
android:id="@+id/hero_image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:scaleType="centerInside"
app:layout_collapseMode="parallax" /> <android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin" /> </android.support.design.widget.CollapsingToolbarLayout> <android.support.design.widget.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorColor="#00C3FF"
app:layout_anchorGravity="bottom"
app:tabBackground="@android:color/white"/> </android.support.design.widget.AppBarLayout> <android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior"> <xbt.exp22.WrapContentHeightViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@android:color/white"/> </android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>

概况:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="15dp"
android:orientation="vertical"
android:background="#6B778E"> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="15dp"
android:text="角色类型"
android:textSize="35sp"
android:textColor="#00C3FF"
android:textStyle="bold|italic" /> <TextView
android:id="@+id/hero_style"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:textSize="45sp"
android:textColor="#F0EDF2"
android:textStyle="bold|italic" /> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="20dp"> <ImageView
android:layout_width="5dp"
android:layout_height="120dp"
android:background="#00C3FF"/> <TextView
android:id="@+id/heroSmileDescriptor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginLeft="10dp"
android:textColor="#F0EDF2"/> </LinearLayout> </LinearLayout> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="15dp"
android:text="技能"
android:textSize="35sp"
android:textColor="#00C3FF"
android:textStyle="bold|italic" /> <LinearLayout
android:id="@+id/skill_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout> </LinearLayout>

故事:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#6B778E"> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="15dp"
android:text="简介"
android:textSize="35sp"
android:textColor="#00C3FF"
android:textStyle="bold|italic" /> <TextView
android:id="@+id/hero1"
android:layout_marginTop="10dp"
android:layout_marginLeft="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#F0EDF2" /> <TextView
android:id="@+id/hero2"
android:layout_marginTop="10dp"
android:layout_marginLeft="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#F0EDF2" /> <TextView
android:id="@+id/hero3"
android:layout_marginTop="10dp"
android:layout_marginLeft="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#F0EDF2" /> <TextView
android:id="@+id/hero4"
android:layout_marginTop="10dp"
android:layout_marginLeft="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#F0EDF2" /> <TextView
android:id="@+id/hero5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="50dp"
android:textSize="30sp"
android:textColor="#00C3FF"
android:textStyle="bold|italic" /> <TextView
android:id="@+id/hero6"
android:layout_marginLeft="35dp"
android:layout_marginRight="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:background="#516080"
android:textColor="#F0EDF2" /> </LinearLayout>

然后就是java代码的编写了,首先要解决布局中一个很严重的问题viewpager和NestedScrollView是有冲突的,所以新建了一个WrapContentHeightViewPager类继承自ViewPager重写了onMeasure方法(这段是网上人家的代码,但是现在我找不到来源了==),

public class WrapContentHeightViewPager extends ViewPager {
public WrapContentHeightViewPager(Context context) {
super(context);
} public WrapContentHeightViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); int height = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
if (h > height) height = h;
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}

活动的java代码:

public class HeroDetails extends AppCompatActivity {

    public static final String Hero_NAME = "hero_name";

    public static final String Hero_ID = "hero_id";

    private Handler handler;

    String imgUrl;

    private List<HeroSkill> heroSkillList = new ArrayList<>();

    private List<String> list_title;
private List<Fragment> list_fragment; private FragmentAdapter fAdapter; private SkillFragment nFragment;
private Fragment2 sFragment; private TabLayout tab_title;
private ViewPager vp_pager; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hero_details); Intent intent = getIntent();
final String heroName =intent.getStringExtra(Hero_NAME);
String heroId =intent.getStringExtra(Hero_ID);
String url = "http://ow.blizzard.cn/heroes/" + heroId; //标题栏设定
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar); //设置标题栏标题
CollapsingToolbarLayout collapsingToolbar = (CollapsingToolbarLayout) findViewById(R.id.collaping_toobar);
collapsingToolbar.setTitle(heroName);
collapsingToolbar.setExpandedTitleColor(Color.parseColor("#00C3FF") );
collapsingToolbar.setCollapsedTitleTextColor(Color.parseColor("#00C3FF") ); //让返回图标显示出来
ActionBar actionBar = getSupportActionBar();
if(actionBar != null){
actionBar.setDisplayHomeAsUpEnabled(true);
} initHeroes(url);
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what == 1){
ImageView overWatchImageView = (ImageView) findViewById(R.id.hero_image_view);
Glide.with(HeroDetails.this).load(imgUrl).into(overWatchImageView);
tab_title = (TabLayout)findViewById(R.id.tablayout);
vp_pager = (ViewPager)findViewById(R.id.viewpager);
fragmentChange();
}
}
};
} //读取数据
private void initHeroes(String Url){
HttpUtil.sendOkHttpRequest(Url, new Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
final String responseText = response.body().string();
new Thread(new Runnable() {
@Override
public void run() {
Document doc = Jsoup.parse(responseText);//将String类型的html转换为Document
Elements elements1 = doc.select(".hero-image"); //读取图片url
Elements elements2 = doc.select(".h2,.hero-detail-role-name"); //角色类型
Elements elements3 = doc.select(".hero-ability"); //读取技能
Elements elements4 = doc.select(".h5");//读取技能名字
Elements elements5 = doc.select(".hero-ability-descriptor");//读取技能描述
Elements elements6 = doc.select(".hero-detail-description");//读取英雄描述
Elements elements7 = doc.select(".hero-bio-copy");//读取英雄简介
Elements elements8 = doc.select(".h4,.hero-detail-title");//读取英雄台词
Elements elements9 = doc.select(".hero-bio-backstory");//读取英雄故事 Log.d("message", elements9.text());
List<String> heroBio = new ArrayList<String>(); for(int i= 0; i < elements7.size(); i++) {
heroBio.add(elements7.get(i).text());
}
heroBio.add(elements8.get(6).text());
heroBio.add(elements9.text()); imgUrl = elements1.attr("src"); for(int j = 0; j < elements4.size(); j++ ) {
String skillImgUrl = elements3.select("img").get(j).attr("src");
String skillName = elements4.get(j).text();
String skillDescriptor = elements5.get(j).select("p").text();
HeroSkill heroSkill = new HeroSkill(skillImgUrl,skillName,skillDescriptor,elements2.text(),elements6.text(),heroBio);
heroSkillList.add(heroSkill);
}
Message msg = new Message();
msg.what = 1;
handler.sendMessage(msg);
}
}).start();
} @Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(HeroDetails.this, "数据获取失败", Toast.LENGTH_SHORT).show();
}
});
}
});
} //点击左上角的返回后退出活动
public boolean onOptionsItemSelected(MenuItem item){
switch (item.getItemId()){
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
} //用于和Fragment的通信
public List<HeroSkill> getHeroSkillList(){
return heroSkillList;
} private void fragmentChange()
{
list_fragment = new ArrayList<>(); nFragment = new SkillFragment();
sFragment = new Fragment2(); list_fragment.add(nFragment);
list_fragment.add(sFragment); list_title = new ArrayList<>();
list_title.add("技能");
list_title.add("概况"); fAdapter = new FragmentAdapter(getSupportFragmentManager(),list_fragment,list_title);
vp_pager.setAdapter(fAdapter); //将tabLayout与viewpager连起来
tab_title.setupWithViewPager(vp_pager);
}
}

这里新建的HeroSkill类:

public class HeroSkill {

    private String skillImg;

    private String skillName;

    private String skillDescriptor;

    private String heroStyle;

    private String heroSmileDescriptor;

    private List<String> heroBio;

    public HeroSkill(String skillImg, String skillName,String skillDescriptor,String heroStyle, String heroSmileDescriptor,List<String> heroBio ) {
this.skillDescriptor = skillDescriptor;
this.skillImg = skillImg;
this.skillName = skillName;
this.heroStyle = heroStyle;
this.heroSmileDescriptor = heroSmileDescriptor;
this.heroBio = heroBio; } public String getSkillImg() {
return skillImg;
} public void setSkillImg(String skillImg) {
this.skillImg = skillImg;
} public String getSkillName() {
return skillName;
} public void setSkillName(String skillName) {
this.skillName = skillName;
} public String getSkillDescriptor() {
return skillDescriptor;
} public void setSkillDescriptor(String skillDescriptor) {
this.skillDescriptor = skillDescriptor;
} public String getHeroStyle() {
return heroStyle;
} public void setHeroStyle(String heroStyle) {
this.heroStyle = heroStyle;
} public String getHeroSmileDescriptor() {
return heroSmileDescriptor;
} public void setHeroSmileDescriptor(String heroSmileDescriptor) {
this.heroSmileDescriptor = heroSmileDescriptor;
} public List<String> getHeroBio() {
return heroBio;
} public void setHeroBio(List<String> heroBio) {
this.heroBio = heroBio;
}
}

然后还有两个fragment的代码,还有连接fragment TabLayout ViewPager的FragmentAdapter继自FragmentPagerAdapter。就不贴了。。

全部的源代码在这https://github.com/xbtshady/Exp22

预览:

  

守望先锋app(2)的更多相关文章

  1. 守望先锋app(1)

    这个app就是从守望先锋的官网下载相关的图片.文字.视频然后展示出来. 第一个功能是英雄介绍,所以先分析一波官网的数据.守望先锋的英雄数据的官方网站是http://ow.blizzard.cn/her ...

  2. 浅谈《守望先锋》中的 ECS 构架

    https://blog.codingnow.com/2017/06/overwatch_ecs.html 今天读了一篇 <守望先锋>架构设计与网络同步 .这是根据 GDC 2017 上的 ...

  3. Android仿“守望先锋”加载动画

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 效果图 实现思路 画一个小六边形 按效果图位置画七个小六边形 实现一个小六边形的显示与隐藏 ...

  4. 暴雪游戏-守望先锋-FPS

    http://us.battle.net/overwatch/en/    

  5. 守望先锋overwatch美服外服设置方法

    打开:C:\Users\你的用户名\AppData\Roaming\Battle.net\Battle.net.config 替换为下方内容: { "Client": { &quo ...

  6. Python爬取CSDN博客文章

    0 url :http://blog.csdn.net/youyou1543724847/article/details/52818339Redis一点基础的东西目录 1.基础底层数据结构 2.win ...

  7. VR应用向导,全球Top10 VR应用排行榜

    2016年国际知名产商索尼.三星.HTC.Oculus.YouTube等等都推出了自己的VR设备,与此同时还有自有的VR应用平台,供各位玩家下载应用体验沉浸式VR,当然每个平台的VR应用下载量各不相同 ...

  8. Android开源项目库汇总

    最近做了一个Android开源项目库汇总,里面集合了OpenDigg 上的优质的Android开源项目库,方便移动开发人员便捷的找到自己需要的项目工具等,感兴趣的可以到GitHub上给个star. 抽 ...

  9. 开源分享 Unity3d客户端与C#分布式服务端游戏框架

    很久之前,在博客园写了一篇文章,<分布式网游server的一些想法语言和平台的选择>,当时就有了用C#做网游服务端的想法.写了个Unity3d客户端分布式服务端框架,最近发布了1.0版本, ...

随机推荐

  1. linux命令积累

    lsof -i: //根据端口号查相关信息 //杀进程 ps -ef|grep appName //根据进程名称查找相关信息 grep -r "关键词" 目录 //在制定目录下根据 ...

  2. CSS属性过滤

    在前端领域,当我们想在ie6及以下版本和标准浏览器的样式不同我们怎么做呢 此时此刻不得不提到过滤器:即一种对特定浏览器显示和隐藏规则的声明方法 1.下划线属性过滤器 符合标准的浏览器都会忽略这个声明, ...

  3. C++20 的 Modules

    最近看了两篇关于 C++ 20 Modules 很有意思的文章,戳: <Understanding C++ Modules: Part 1: Hello Modules, and Module ...

  4. webpack4基础入门操作(一)

    基于webpack4实践:开始:打开控制面板,制定到创建Webpack的文件夹. 并创建初始配置文件package.json 输入命令:npm init -y,在文件夹中出现一个package.jso ...

  5. Tomcat配置解析

    Tomcat文件配置 tomcat解压后目录 bin:可执行文件(startup.bat shutdown.bat) conf:配置文件(server.xml) lib:tomcat依赖的jar文件 ...

  6. 原创:Python编写通讯录,支持模糊查询,利用数据库存储

    1.要求 数据库存储通讯录,要求按姓名/电话号码查询,查询条件只有一个输入入口,自动识别输入的是姓名还是号码,允许模糊查询. 2.实现功能 可通过输入指令进行操作. (1)首先输入“add”,可以对通 ...

  7. 整型,布尔值,字符串详解,for语句 练习

    2019 年 7 月 8 日 1.将今天的课上的代码敲一遍,然后整理笔记 已完成 2.有变量name = "aleX leNb" 完成如下操作: 移除 name 变量对应的值两边的 ...

  8. numpy表示图片详解

    我自己的一个体会,在学习机器学习和深度学习的过程里,包括阅读模型源码的过程里,一个比较大的阻碍是对numpy掌握的不熟,有的时候对矩阵的维度,矩阵中每个元素值的含义晕乎乎的. 本文就以一个2 x 2 ...

  9. 你可能不知道的github的秘密

    github也可以使用快捷键 先举例子,如何快速查找项目中的文件? 只需要进入项目,并按下T键 在浏览代码时,如何快速跳到指定行? 只需要进入项目,并按下L键 下面是一些常用的快捷键 聚焦搜索栏 按下 ...

  10. 嵌入式web服务器BOA的移植及应用

    嵌入式web服务器子系统 一.嵌入式web服务器的控制流程 如下图所示,嵌入式web服务器可实现通过网络远程控制嵌入式开发板,便捷实用. 控制流程:浏览器 --->>>嵌入式开发板 ...