1. 程式人生 > >守望先鋒app(2)

守望先鋒app(2)

tool des ace 沖突 spec mode ret cat blank

上次的功能完成了英雄名字、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)