Android开发——项目实例(五)集新闻、音乐、电影于一体的软件(带打包源码)

主页面

 

1.写界面

很明显,这个主界面采用了ViewPager和TabLayout实现界面滑动切换,在使用TabLayout之前记得导包,TabLayout需要导入的包

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!--标题区-->
    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabGravity="fill"
        app:tabMode="fixed"
        android:background="#e67bab"
        app:tabTextColor="#fff"
        app:tabIndicatorColor="#92dfd1"
        app:tabSelectedTextColor="#1f67e2"
        >
    </android.support.design.widget.TabLayout>
    
    <!--页面显示区-->
    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        />

</LinearLayout>

2.写Activity

登录后的主页面
 * 前提:TabLayout依赖的design包
 * 属性:①TabLayout、ViewPager
 * 操作: 1.初始化一个适配器类
 *         1.  定义标题和页面列表
 *         2.  把三个Fragment添加到列表中
 *         3.  用列表和标题创建适配器
 *       2. 进行关联操作
 *         1.  ViewPager添加适配器
 *         2.  TabLayout与ViewPager关联
package com.example.tablayoutmenu;

import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

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

/**
 * 登录后的主页面
 * 前提:TabLayout依赖的design包
 * 属性:①TabLayout、ViewPager
 * 操作: 1.初始化一个适配器类
 * 1.  定义标题和页面列表
 * 2.  把三个Fragment添加到列表中
 * 3.  用列表和标题创建适配器
 * 2. 进行关联操作
 * 1.  ViewPager添加适配器
 * 2.  TabLayout与ViewPager关联
 *
 * @author thinkdoor
 */

public class MainActivity extends AppCompatActivity {

    /*
    定义UI组件
     */
    private TabLayout tabLayout;
    private ViewPager viewPager;

    /**
     * 创建的回调方法
     *
     * @param savedInstanceState
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //初始化界面组件
        tabLayout = (TabLayout) findViewById(R.id.tab_layout);
        viewPager = (ViewPager) findViewById(R.id.view_pager);

        //获取初始化的适配器
        MyFragmentPagerAdapter myFragmentPagerAdapter = init();

        //添加适配器
        viewPager.setAdapter(myFragmentPagerAdapter);

        //设置tablayou和viewpage关联
        tabLayout.setupWithViewPager(viewPager);
    }

    /**
     * 初始化适配器
     *
     * @return:初始化后的适配器
     */
    public MyFragmentPagerAdapter init() {
        //菜单标题
        String[] title = {"新闻", "音乐", "电影"};

        //创建装载Fragment的列表
        List<Fragment> fragmentlist;

        /*
            初始化列表,并把创建的三个Fragment页面添加到列表中
         */
        fragmentlist = new ArrayList<>();
        fragmentlist.add(new FragmentOne());
        fragmentlist.add(new FragmentTwo());
        fragmentlist.add(new FragmentThree());

        //创建Fragment适配器
        MyFragmentPagerAdapter myFragmentPagerAdapter;

        //适配器进行适配,传入列表与标题
        myFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager(),
                fragmentlist, title);
        return myFragmentPagerAdapter;
    }
}

3.前面提到了FragmentOne,FragmentTwo,FragmentThree直接创建先放着,记得继承Fragment奥。

4.创建适配器MyFragmentPagerAdpter

fragment的适配器类
 * 1.集成FragmentPagerAdapter,实现相关方法
 * 2.创建需要显示的List集合
 * 3.重写getPageTitle设置标题
package com.example.tablayoutmenu;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

import java.util.List;

/**
 * fragment的适配器类
 * 1.集成FragmentPagerAdapter,实现相关方法
 * 2.创建需要显示的List集合
 * 3.重写getPageTitle设置标题
 *
 * @author thinkdoor
 */

public class MyFragmentPagerAdapter extends FragmentPagerAdapter {

    //装载fragment的列表
    private List<Fragment> list;

    //标题
    private String[] title;

    /**
     * 构造方法
     *
     * @param fm
     * @param list:装载fragment的列表
     * @param title:标题栏
     */
    public MyFragmentPagerAdapter(FragmentManager fm, List<Fragment> list, String[] title) {
        super(fm);
        this.list = list;
        this.title = title;
    }

    /**
     * 返回当前位置的fragment
     *
     * @param position:当前页面的位置
     * @return
     */
    @Override
    public Fragment getItem(int position) {
        return list.get(position);
    }

    /**
     * 获取list中fragment的个数
     *
     * @return
     */
    @Override
    public int getCount() {
        return list.size();
    }

    /**
     * 返回当前的标题
     *
     * @param position:当前页面的位置
     * @return
     */
    @Override
    public CharSequence getPageTitle(int position) {
        return title[position];
    }
}

OK了,现在,我们已经可以实现界面滑动了,但是每个Fragment页面里都是空空的。

好了,现在,来点刺激的,写能显示新闻列表的的FragmentOne。

新闻页面

新闻页面能显示新闻列表,点击新闻进入新闻详情页面

分析——①关于新闻页面使用的是ListView,②然后有ListView就肯定有item的布局还有适配器,③点击进入详情就是设置了Onclick方法,④新闻详情页面博主是用WebView实现的。⑤数据如何获取?博主调用的知乎日报的API接口。

1.界面

就是一个LsitView

<LinearLayout 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"
    android:orientation="vertical"
    >

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

2.Activity

新闻页面

 注:News和NewsInfo都是实体model类,见到不要蒙圈
前提准备:OkHttpClient包、Gson包、联网授权
 1.属性:ListView、OkHttpClient(网络通信异步请求对象)、List<NewsInfo>列表(NewsInfo是新闻信息的实体类)
 2.操作:1.OkHttpClient+Handler请求网络,得到响应数据,并封装到List<NewsInfo>列表
                1).创建Handler,重写handlerMessage方法
                2).使用OkHttpClient实现网络异步请求
                    1.创建Request对象和OkHttpClient对象
                    2.通过前两个对象创建Call对象
                    3.通过Call的enqueue(Callback)方法来提交异步请求,子线程
                        1.把响应字符串转为json对象
                        2.把json对象转为java对象
                        3.创建Message对象,初始化后传输给Handler
                3).handlerMessage方法中获取List
        2.用添加好的List创建列适配器,并添加
        3.设置监听,点击跳转详情页面
                1).从list中的对象中获取属性
                2).通过intent的putExtra设置传输
                3).完成跳转
package com.example.tablayoutmenu;

import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;

import com.example.tablayoutmenu.model.News;
import com.example.tablayoutmenu.model.NewsInfo;
import com.example.tablayoutmenu.util.JsonUitl;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.List;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * 新闻页面

 注:News和NewsInfo都是实体model类,见到不要蒙圈
前提准备:OkHttpClient包、Gson包、联网授权
 1.属性:ListView、OkHttpClient(网络通信异步请求对象)、List<NewsInfo>列表(NewsInfo是新闻信息的实体类)
 2.操作:1.OkHttpClient+Handler请求网络,得到响应数据,并封装到List<NewsInfo>列表
                1).创建Handler,重写handlerMessage方法
                2).使用OkHttpClient实现网络异步请求
                    1.创建Request对象和OkHttpClient对象
                    2.通过前两个对象创建Call对象
                    3.通过Call的enqueue(Callback)方法来提交异步请求,子线程
                        1.把响应字符串转为json对象
                        2.把json对象转为java对象
                        3.创建Message对象,初始化后传输给Handler
                3).handlerMessage方法中获取List
        2.用添加好的List创建列适配器,并添加
        3.设置监听,点击跳转详情页面
                1).从list中的对象中获取属性
                2).通过intent的putExtra设置传输
                3).完成跳转
 * @author thinkdoor
 */
public class FragmentOne extends Fragment implements AdapterView.OnItemClickListener{

    //日志TAG
    private static final String TAG = "FragmentOne";

    private ListView listView;
    //存放新闻信息的列表
    private List<NewsInfo> data;

    /**
     * 1).创建Handler,重写handlerMessage方法
     */
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            News news = (News)msg.obj;
            //3).handlerMessage方法中获取List
            data = news.getStories();
            List<NewsInfo> data2 = news.getTop_stories();
            //2.用添加好的List创建列适配器,并给ListView添加适配器
            listView.setAdapter(new NewsAdapter(data,data2,getContext()));
        }
    };

    /**
     * 创建视图
     * @param inflater
     * @param container
     * @param savedInstanceState
     * @return
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        //用Fragment_one来填充View视图
        View view = inflater.inflate(R.layout.fragment_one, container, false);

        listView = view.findViewById(R.id.list_view);
        listView.setOnItemClickListener(this);

        //初始化加载新闻数据
        initNews();

        return view;
    }

    /**
     * 加载新闻数据,2).使用OkHttpClient实现网络异步请求
     */
    public void initNews(){
        //知乎新闻
        String path = "http://news-at.zhihu.com/api/4/news/latest";
        //1.创建Request对象和OkHttpClient对象
        OkHttpClient okHttpClient = new OkHttpClient();
        Request request = new Request.Builder()
                .get()
                .url(path)
                .build();
        //2.通过前两个对象创建Call对象
        Call call = okHttpClient.newCall(request);
        //3.通过Call的enqueue(Callback)方法来提交异步请求,子线程
        call.enqueue(new Callback() {
            //请求失败
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d(TAG, "onFailure() called with: call = [" + call + "], e = [" + e + "]");
            }

            //在子线程中运行的(不能更新UI),请求成功
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String str = response.body().string();
                Log.d(TAG, str);
                try {
                    //1.把响应字符串转为json对象
                    JSONObject jsonObject = new JSONObject(str);
                    //2.把json对象转为java对象
                    News news =  (News)JsonUitl.stringToObject(jsonObject.toString(),News.class);
                    Log.d(TAG, news.toString());
                    /**
                     //3.创建Message对象,包装对象后,传输给Handler
                     */
                    Message message = new Message();
                    message.obj = news;
                    handler.sendMessage(message);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 点击列表item显示新闻详情,取出当前点击的记录,传ID到详情页
     *
     * @param parent
     * @param view
     * @param position
     * @param id
     */
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        //1).从list中的对象中获取属性
        NewsInfo newsInfo = data.get(position);
        Intent intent = new Intent();
        //2).通过intent的putExtra设置传输
        intent.putExtra("id",newsInfo.getId());
        //3).完成跳转
        intent.setClass(getContext(),NewsDetailActivity.class);
        startActivity(intent);
    }
}

新闻界面的ListView的适配器

package com.example.tablayoutmenu;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.tablayoutmenu.model.NewsInfo;
import com.example.tablayoutmenu.util.AsyncImageLoader;

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

/**
 新闻适配器类

 1.因为是List的适配器,所以继承BaseAdapter,并实现必要方法
 2.创建需要的List集合
 3.重写getView方法实现适配界面

 * @author thinkdoor
 */

public class NewsAdapter extends BaseAdapter{

    private List<NewsInfo> list;
    //LayoutInflater将布局文件实例化为View对象
    private LayoutInflater layoutInflater;

    private AsyncImageLoader asyncImageLoader;

    public NewsAdapter(List<NewsInfo> list, Context context){
        this.list = list;
        layoutInflater = LayoutInflater.from(context);
        this.asyncImageLoader = new AsyncImageLoader(context);
    }

    public NewsAdapter(List<NewsInfo> list1,List<NewsInfo> list2, Context context){
        this.list = mergeList(list1,list2);
        layoutInflater = LayoutInflater.from(context);
        this.asyncImageLoader = new AsyncImageLoader(context);
    }
    /**
     * 两个列表合并的方法
     *
     * @param list1
     * @param list2
     * @return
     */
    public List<NewsInfo> mergeList(List<NewsInfo> list1,List<NewsInfo> list2){
        List<NewsInfo> list = new ArrayList<>();
        //遍历列表1,并添加到列表3中
        for(int i = 0;i < list1.size();i++){
            NewsInfo newsInfo = list1.get(i);
            list.add(newsInfo);
        }
        //遍历列表2,并把String类型的image转化成String[]类型,然后添加到列表3中
        for(int i = 0;i < list2.size();i++){
            NewsInfo newsInfo = list2.get(i);
            newsInfo.setImages(new String[]{newsInfo.getImage()});
            list.add(newsInfo);
        }
        return list;
    }

    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        //将布局文件实例化为View对象
        View view = layoutInflater.inflate(R.layout.news_item,null);
        //从布局取textview
        TextView textView = (TextView)view.findViewById(R.id.textView);
        ImageView imageView = (ImageView)view.findViewById(R.id.imageView);
        //取当前需要显示的对象
        NewsInfo newsInfo = list.get(position);
        //给textview赋值
        textView.setText(newsInfo.getTitle());
        //加载图片
        asyncImageLoader.asyncloadImage(imageView, newsInfo.getImages()[0]);
        return view;
    }
}

新闻详情页面

界面

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_news_detail"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.tablayoutmenu.NewsDetailActivity">

    <WebView
        android:id="@+id/web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true"
        />
</RelativeLayout>

Activity

package com.example.tablayoutmenu;

import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebView;

import com.example.tablayoutmenu.model.NewsDetail;
import com.example.tablayoutmenu.util.JsonUitl;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;


/**
 * 新闻详情页
 属性:WebView
 操作:1.初始化页面
    2.联网请求,得到响应数据,进行处理
        1.创建Handler,重写handlerMeassage方法
        2.创建OkHttpClient和Request对象
        3.创建Call对象
        4.重写Call#enqueue(Callback)方法
            1.把返回数据转为json对象
            2.把json对象转为java对象
            3.创建Message,发送数据到主线程
        5.handler处理消息
            1.得到所需消息
            2.WebView赋值
    3.完善结尾

 */
public class NewsDetailActivity extends AppCompatActivity {

    //日志TAG
    private static final String TAG = "NewsDetailActivity";

    //创建WebView
    private WebView webView;

    //创建Handler
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            NewsDetail newsDetail = (NewsDetail)msg.obj;
            //用webview加载网页
            webView.loadUrl(newsDetail.getShare_url());
        }
    };

    /**
     * 创建页面
     * @param savedInstanceState
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_news_detail);
        webView = (WebView) findViewById(R.id.web_view);
        //设置可以执行JS脚本
        webView.getSettings().setJavaScriptEnabled(true);
        //加载数据
        getNews();
    }

    /**
     * 加载新闻数据
     */
    public void getNews(){
        //知乎新闻详情
        String path = "http://news-at.zhihu.com/api/4/news/";
        Intent intent = getIntent();
        long id = intent.getLongExtra("id",0);
        path += id;
        //1.创建OkHttpClient对象和Request对象
        OkHttpClient okHttpClient = new OkHttpClient();
        Request request = new Request.Builder()
                .get()
                .url(path)
                .build();
        //2.创建Call对象
        Call call = okHttpClient.newCall(request);
        //3.执行请求,访问网络数据
        call.enqueue(new Callback() {
            //请求失败
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d(TAG, "onFailure() called with: call = [" + call + "], e = [" + e + "]");
            }

            //在子线程中运行的(不能更新UI),请求成功
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String str = response.body().string();
                Log.d(TAG, str);
                try {
                    //1.转换成JSON对象
                    JSONObject jsonObject = new JSONObject(str);
                    //2.通过Gson把json字符串转换成java对象
                    NewsDetail newsDetail
                            =  (NewsDetail) JsonUitl.stringToObject(jsonObject.toString(),NewsDetail.class);
                    //3.创建Message,发送消息
                    Message message = new Message();
                    message.obj = newsDetail;
                    handler.sendMessage(message);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 关闭页面的完善处理
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (webView!=null){
            webView.destroy();
        }
    }
}

后面两个页面举一反三

主要是①联网找API获取到数据,②获取到数据后的处理

音乐界面

电影页面

需要打包源码查看下方链接,源码带详细注释,博主用的IDE是Android Studio

GitHub - Thinkdoor/PractiseSoftware

要是觉得还可以,点个再走吧!求求了~

  • 114
    点赞
  • 392
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 90
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 90
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狮子座的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值