安卓开发笔记——打造属于自己的博客园APP(一)

  最近事情比较多,博客更新又落下了,平时有个习惯,喜欢睡前看看博客园里博友的文章,但一直感觉APP市场上下载下来的博客园客户端用起来并不是很舒服,近来发现博客园也有对外开放的数据接口,所以打算自己写个博客园的客户端。

  近来谷歌推出了一套全新的UI设计规范——Material Design,不清楚的朋友看看《Material design非官方中文指导手册》,相比之前谷歌在Android Holo风格上平平淡淡的表现不同,Material Design现在是被Google所比较重视的。在推出这门全新设计语言后,谷歌上自家的应用很快就使用Material Design全新设计了,如Play商店,Google Map,Google+等等。

  打算赶一下潮流,紧跟谷歌的步伐遵循Material Design设计规范开发这个APP,也刚好让自己熟悉下Android5.0后的新特性。这个APP会慢慢做下来,逐步完善所需功能,我也不确定会写几篇文章,然后有空闲的时候就拿出来写写吧。

好了,言归正传,先来看下今天要实现的效果:(UI主框架的搭建)

如果在过去,我们要实现上图的效果,侧滑菜单我们会使用SlidingMenu,ViewPager滑动页面指示器我们会使用ViewPagerIndicator或者PagerSlidingTabStrip等开源控件。但现在谷歌官方已经给我们提供了实现,我们当然就用官方提供的控件了。

侧滑菜单的实现:DrawerLayout  ViewPager滑动页面指示器的实现:TabLayout  这2个空间分别是在V4包和V7包中,不熟悉的朋友,网上自己查查资料吧。

关于代码实现:

顶部为ToolBar,侧滑菜单为DrawerLayout,主界面为ViewPager内嵌Fragment,直接看代码吧。

首先我们需要对风格进行定义,我们的顶部不再实现ActionBar,而是谷歌新推出的基于ActionBar实现的ToolBar(在V7支持包下):

 1 <resources>
 2     <!-- Base application theme. -->
 3     <style name="AppBaseTheme" parent="Theme.AppCompat.Light.NoActionBar">
 4         <!-- Toolbar(actionbar)颜色 -->
 5         <item name="colorPrimary">@color/md_green_600</item>
 6         <!-- 状态栏颜色 -->
 7         <item name="colorPrimaryDark">@color/md_green_800</item>
 8         <!-- 窗口的背景颜色 -->
 9         <item name="android:windowBackground">@android:color/white</item>
10         <!-- SearchView -->
11         <item name="searchViewStyle">@style/MySearchViewStyle</item>
12     </style>
13
14     <style name="MySearchViewStyle" parent="Widget.AppCompat.SearchView" />
15
16     <style name="AppTheme" parent="@style/AppBaseTheme" />
17 </resources>

然后关于底部的NavigationBar,我们需要额外的在values-v21文件内添加:

1 <resources xmlns:android="http://schemas.android.com/apk/res/android">
2
3     <style name="AppTheme" parent="@style/AppBaseTheme">
4         <!-- 底部导航栏颜色 -->
5         <item name="android:navigationBarColor">@color/md_green_600</item>
6     </style>
7
8 </resources>

再来看下布局文件:

主布局文件:activity_main.xml

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:layout_height="match_parent"
 4     android:orientation="vertical">
 5     <!--ToolBar-->
 6     <include layout="@layout/activity_toolbar" />
 7     <!--DrawerLayout-->
 8     <android.support.v4.widget.DrawerLayout
 9         android:id="@+id/dl_drawer"
10         android:layout_width="match_parent"
11         android:layout_height="match_parent">
12         <!--Main Content-->
13         <include layout="@layout/activity_main_content" />
14         <!--Main Menu-->
15         <include layout="@layout/activity_main_menu" />
16     </android.support.v4.widget.DrawerLayout>
17
18 </LinearLayout>

ToolBar布局文件:activity_toolbar.xml

1 <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
2     xmlns:app="http://schemas.android.com/apk/res-auto"
3     android:id="@+id/activity_toolbar"
4     android:layout_width="match_parent"
5     android:layout_height="?attr/actionBarSize"
6     android:background="@color/md_green_600"
7     android:theme="@style/ThemeOverlay.AppCompat.Dark"
8     app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

侧滑菜单布局文件:activity_main_menu.xml,activity_main_menu_header.xml

 1 <android.support.design.widget.NavigationView
 2     xmlns:android = "http://schemas.android.com/apk/res/android"
 3     xmlns:app = "http://schemas.android.com/apk/res-auto"
 4     android:id = "@+id/nv_main_menu"
 5     android:layout_height = "match_parent"
 6     android:layout_width = "wrap_content"
 7     android:layout_gravity = "start"
 8     android:clickable="true"
 9     app:headerLayout = "@layout/activity_main_menu_header"
10     app:menu = "@menu/menu_drawer_view"/>  
 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:app="http://schemas.android.com/apk/res-auto"
 3     android:layout_width="match_parent"
 4     android:layout_height="200dp"
 5     android:background="@drawable/menu_header_bg"
 6     android:orientation="vertical"
 7     android:theme = "@style/ThemeOverlay.AppCompat.Dark"
 8     android:padding="30dp">
 9
10
11     <com.makeramen.roundedimageview.RoundedImageView
12         android:id="@+id/imageView1"
13         android:layout_width="100dp"
14         android:layout_height="100dp"
15         android:src="@mipmap/avatar_default"
16         app:riv_border_color="#00ffffff"
17         app:riv_border_width="2dip"
18         app:riv_corner_radius="30dip"
19         app:riv_mutate_background="true"
20         app:riv_oval="true"
21         app:riv_tile_mode="repeat" />
22
23     <TextView
24         android:layout_width="wrap_content"
25         android:layout_height="wrap_content"
26         android:layout_marginTop="16dp"
27         android:layout_marginLeft="16dp"
28         android:layout_marginStart="16dp"
29         android:text="未登录用户"
30         android:textAppearance="@style/TextAppearance.AppCompat.Body2"/>
31
32 </LinearLayout>

菜单内容文件:menu_drawer_view.xml(menu文件夹下)

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <menu xmlns:android="http://schemas.android.com/apk/res/android">
 3
 4     <group android:checkableBehavior="single">
 5         <item
 6             android:id="@+id/nav_home"
 7             android:icon="@mipmap/ic_home_black_48dp"
 8             android:title="主页" />
 9         <item
10             android:id="@+id/nav_sort"
11             android:icon="@mipmap/ic_assignment_black_48dp"
12             android:title="分类" />
13         <item
14             android:id="@+id/nav_rss"
15             android:icon="@mipmap/ic_favorite_black_48dp"
16             android:title="订阅" />
17         <item
18             android:id="@+id/nav_like"
19             android:icon="@mipmap/ic_grade_black_48dp"
20             android:title="收藏" />
21     </group>
22
23     <item android:title="其他">
24         <menu>
25             <item
26                 android:id="@+id/nav_setting"
27                 android:icon="@mipmap/ic_settings_black_48dp"
28                 android:title="设置"></item>
29             <item
30                 android:id="@+id/nav_help"
31                 android:icon="@mipmap/ic_help_black_48dp"
32                 android:title="帮助"></item>
33         </menu>
34     </item>
35
36 </menu>

主内容布局文件:activity_main_content.xml

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

    <android.support.design.widget.TabLayout
        android:id="@+id/tl_main_tabs"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:background="@color/md_green_600"
        app:elevation="5dp"
        app:tabIndicatorColor="@color/md_green_800"
        app:tabSelectedTextColor="@color/md_white_1000"
        app:tabTextColor="@color/md_green_100" />

    <android.support.v4.view.ViewPager
        android:id="@+id/vp_main_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

再来看下JAVA代码:

主Activity:

package com.lcw.rabbit.myblog;

import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;

import com.lcw.rabbit.myblog.adapter.ViewPagerAdapter;
import com.lcw.rabbit.myblog.fragment.BestFragment;
import com.lcw.rabbit.myblog.fragment.CandidateFragment;
import com.lcw.rabbit.myblog.fragment.HomeFragment;
import com.lcw.rabbit.myblog.fragment.RecommendFragment;

public class MainActivity extends AppCompatActivity {

    private Toolbar mToolbar;
    private DrawerLayout mDrawerLayout;
    private NavigationView mNavigationView;
    private TabLayout mTabLayout;
    private ViewPager mViewPager;
    private ActionBarDrawerToggle mActionBarDrawerToggle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    /**
     * 初始化布局
     */
    private void initView() {
        //实例化控件
        mToolbar = (Toolbar) findViewById(R.id.activity_toolbar);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.dl_drawer);
        mTabLayout = (TabLayout) findViewById(R.id.tl_main_tabs);
        mNavigationView = (NavigationView) findViewById(R.id.nv_main_menu);
        mViewPager = (ViewPager) findViewById(R.id.vp_main_content);
        //设置对应属性
        initToolBar();
        initMainContent();
        initAction();

    }

    /**
     * 初始化控件的动作监听
     */
    private void initAction() {
        //设置侧滑菜单点击监听
        mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(MenuItem menuItem) {
                int id = menuItem.getItemId();
                switch (id) {
                    //返回首页
                    case R.id.nav_home:
                        mViewPager.setCurrentItem(0);
                        break;
                }
                mDrawerLayout.closeDrawers();
                return false;
            }
        });
    }

    /**
     * 初始化TabLayout和ViewPager
     */
    private void initMainContent() {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        Fragment homeFragment = new HomeFragment();
        Fragment bestFragment = new BestFragment();
        Fragment candidateFragment = new CandidateFragment();
        Fragment recommendFragment = new RecommendFragment();
        adapter.addFragment(homeFragment, "首页");
        adapter.addFragment(bestFragment, "精华");
        adapter.addFragment(candidateFragment, "候选");
        adapter.addFragment(recommendFragment, "推荐");
        mViewPager.setAdapter(adapter);
        mTabLayout.setupWithViewPager(mViewPager);
    }

    /**
     * 初始化ToolBar
     */
    private void initToolBar() {
        mToolbar.setTitle("博客园");
        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        mActionBarDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolbar, R.string.drawer_open, R.string.drawer_close);
        mActionBarDrawerToggle.syncState();
        mDrawerLayout.setDrawerListener(mActionBarDrawerToggle);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();

        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

主滑动页面ViewPager适配器:

 1 package com.lcw.rabbit.myblog.adapter;
 2
 3 import android.support.v4.app.Fragment;
 4 import android.support.v4.app.FragmentManager;
 5 import android.support.v4.app.FragmentPagerAdapter;
 6
 7 import java.util.ArrayList;
 8 import java.util.List;
 9
10 /**
11  * 主页面VierPager适配器
12  * Created by Lichenwei
13  * Date: 2015-08-16
14  * Time: 13:47
15  */
16 public class ViewPagerAdapter extends FragmentPagerAdapter {
17
18     private List<Fragment> mFragments;
19     private List<String> mTitles;
20
21     public ViewPagerAdapter(FragmentManager fm) {
22         super(fm);
23         mFragments = new ArrayList<Fragment>();
24         mTitles = new ArrayList<String>();
25     }
26
27     /**
28      * 新添Fragment内容和标题
29      * @param fragment
30      * @param title
31      */
32     public void addFragment(Fragment fragment, String title) {
33         mFragments.add(fragment);
34         mTitles.add(title);
35     }
36
37     @Override
38     public Fragment getItem(int position) {
39         return mFragments.get(position);
40     }
41
42     @Override
43     public int getCount() {
44         return mFragments.size();
45     }
46
47     @Override
48     public CharSequence getPageTitle(int position) {
49         return mTitles.get(position);
50     }
51 }

作者:李晨玮
出处:http://www.cnblogs.com/lichenwei/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
正在看本人博客的这位童鞋,我看你气度不凡,谈吐间隐隐有王者之气,日后必有一番作为!旁边有“推荐”二字,你就顺手把它点了吧,相得准,我分文不收;相不准,你也好回来找我!

时间: 2024-08-25 10:05:11

安卓开发笔记——打造属于自己的博客园APP(一)的相关文章

安卓开发笔记——打造属于自己的博客园APP(四)

在上篇文章<安卓开发笔记——打造属于自己的博客园APP(三)>中,我们对博客文章的详情页和评论页进行了实现,慢慢的一个APP已经出现雏形了,当然这只是完成了"表面效果",要真正做好一个APP并不是一件很轻松的事情,有很多细节需要我们一点一滴的去完善. 好了,来讲下今天要完成的效果,在优化了之前部分代码的前提下,今天来说下关于博客搜索和博客详情页的实现,依旧国际惯例,来看下效果图:(动态图片比较大,加载需要点时间) 效果比较简单,很多东西我们还是可以复用之前的代码,毕竟这种列

安卓开发笔记——打造属于自己的博客园APP(二)

在上一篇文章<安卓开发笔记——打造属于自己的博客园APP(一)>中,我们基本上实现了博客园的主体UI框架(后面可能会有些小变化,等遇到了再说).今天来讲讲博客园首页模块的大体实现,国际惯例,先来看下效果图: 整体UI效果: 下拉刷新和上拉加载的动画效果: 在上篇文章中,我们定义的Tabs主题文字分别是(首页,精华,候选,推荐),这边的命名我是根据博客园网站首页的栏目来命名的,那时候我还没仔细看过博客园的开放接口,后来才发现原来博客园没有对应开放这些栏目的接口,博客园只开放了(文章列表,48小时

Xamarin Android 打造属于自己的博客园APP(2)

好尴尬,隔了四个月才写第二篇幅,自己都不好意思了.这个拖延症好尴尬,妈蛋! 为那些在期待续集的同学说声sorry! 下面开始正文: 完成功能: 1.分页获取首页文章 2.分页获取精华文章 3.分页获取新闻 4.分页获取知识库文章 5.博客园账号登录,获取收藏文章,我的博客 6.文章评论 在写第一篇的时候,那个时候APP接口是调用的博客园公开的wcf接口,很多功能都有所限制,有诸多的不方便.我看见官方有ios版本的博客园,我用fiddler监听了下请求地址,发现域名是以api.cnblogs.co

Xamarin Android 打造属于自己的博客园APP(1)

目前完成情况 目前已有功能:分页获取首页博客,登录,查看文章详情,以及查看提交评论. 目前查看评论有一个Bug,提交的评论在APP上不能够立即刷新出来,但是在网页上能及时刷新出来,我已经确认过我代码很多次了,确定没有问题.纠结了有好几天了,不知道是不是WCF接口有问题. 未做功能:想按照分类获取文章,离线收藏,以后APP一些地方优化. 主要是作为一个个人开发者,白天上班,晚上才有时间搞.所以进度较慢. 偷个懒,直接发个大图吧,太累了,要睡觉了. 代码的话还需要整理下,不过目前的APK我上传到百度

Xamarin Android 打造属于自己的博客园APP(3)

打造通用下拉刷新上拉加载更多组件 android开发中最常用的就是列表组件,如ListView,recycleView,用到它们感觉就会涉及到数据更新,分页加载. 最开始的时候,刷新组件我是在技术群里头找了一个被人绑定好的库,是绑定的github上一个星星很多的java原生组件.但是demo很简单,对于当时小白的我懵逼了,不晓得咋个用,而且一直觉得banding的库总感觉有问题,就想着直接找一个java的库翻译成C#版本的.功夫不负苦心人,在csdn上找到了一篇 http://blog.csdn

【原】博客园第三方客户端-i博客园App开源

[原]博客园第三方客户端-i博客园App开源 本文转载请注明出处 —— polobymulberry-博客园 1.前言 目前i博客园App已经更新到2.0.0版本了,使用了最新的博客园Web API.相比于第一个版本,添加了很多新的功能,也修改了很多功能.整体来说改动比较大,代码也比较混乱.所以趁着清明假期,把代码好好整理了一番.目前基本的架构已成型(当然,后期还需要不断优化),但App基本功能方面还有很多需要添加的,后面会集中把App功能完善. 上面简单介绍了下目前App的情况,回到开源的话题

基于Corova的博客园APP

       背景: 自从今年下半年接触一个基于ReactJS 的手机APP项目.开始了解到了Corodva这个神奇的东西.后续自己也自作了一些小的APP放到了应用宝上.8月份开始想做一个博客园APP.于是就私聊博客园团队申请了博客园API访问权限(当然其实应用宝里面也有博客园APP了.而且用fiddler抓取了一下.发现API还很完善.说实话比博客园团队提供的API完善多了.我想应该是开发者用爬虫软件爬的页面然后自己解析的吧.) 第一步: 申请API: 私聊博客园,获取了OAuth的Clien

安卓开发笔记——打造万能适配器(Adapter)

为什么要打造万能适配器? 在安卓开发中,用到ListView和GridView的地方实在是太多了,系统默认给我们提供的适配器(ArrayAdapter,SimpleAdapter)经常不能满足我们的需要,因此我们时常要去继承BaseAdapter类去实现一个自定义的适配器来满足我们的场景需要. 如果你是开发一个简单点的APP还好,可能ListView和GridView的数量不会太多,我们只要去写几个BaseAdapter实现类就可以了. 但如果有一天,你需要开发一个APP里面具有几十个ListV

安卓开发笔记——深入Activity

在上一篇文章<安卓开发笔记——重识Activity >中,我们了解了Activity生命周期的执行顺序和一些基本的数据保存操作,但如果只知道这些是对于我们的开发需求来说是远远不够的,今天我们继续探索Activity,来了解下关于Activity任务栈和Activity四种启动模式的区别. 为什么需要了解关于Activity的任务栈,其实最直接的体现就是提高用户交互友好性. 举个例子,当我们去浏览一个新闻客户端的时候,我们进入了新闻详情页,在这个页面有相隔两条的新闻标题,当我们去点击这个标题的时