仿9GAG制作过程(一)
仿9GAG制作过程(一)
- 有话要说
- 成果图
- 布局代码
- 插一个知识点
有话要说
准备开始学习Android
应用程序的一个完整的设计过程。准备做一个仿9GAG的APP,前端界面设计+后台数据爬虫+后台接口设计,整个流程体验一遍。今天准备先把前端界面的框架给完成了。
成果图
布局代码
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 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:id="@+id/drawer_layout"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"tools:openDrawer="start"><includelayout="@layout/activity_main_appbar"android:layout_width="match_parent"android:layout_height="match_parent" /><android.support.design.widget.NavigationViewandroid:id="@+id/nav_view"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_gravity="start"android:fitsSystemWindows="false"app:headerLayout="@layout/activity_main_drawer_head"app:menu="@menu/activity_main_drawer_menu"android:theme="@style/MenuTextStyle"/></android.support.v4.widget.DrawerLayout>
主活动用了DrawerLayout
的布局方式,通过设置DrawerLayout
的openDrawer
属性以及NavigationView
的gravity
属性来实现左侧的测拉区域。
下面来看看NavigationView
的头部布局以及menu
的布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"android:background="@color/background"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"><de.hdodenhof.circleimageview.CircleImageViewandroid:id="@+id/circleImageView"android:layout_width="28dp"android:layout_height="28dp"android:layout_centerVertical="true"android:layout_marginLeft="14dp"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="懒星人"android:layout_centerVertical="true"android:layout_marginLeft="14dp"android:layout_toRightOf="@id/circleImageView"android:textColor="@color/colorPrimary"/><ImageViewandroid:id="@+id/imageView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/ic_settings_gray_24dp"android:layout_centerVertical="true"android:layout_marginRight="14dp"android:layout_alignParentRight="true"/></RelativeLayout><Viewandroid:layout_alignParentBottom="true"android:layout_width="match_parent"android:layout_height="1dp"android:background="?android:listDivider"/>
</RelativeLayout>
这里用到了CircleImageView
组件来实现图片缩放裁剪成圆形,作为左上角头像的布局。并且由于头部的布局与menu
的布局之间没有直接的分割线,就用View
来实现了一个分割线。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"tools:showIn="navigation_view"><groupandroid:id="@+id/group1"android:checkableBehavior="single"><itemandroid:id="@+id/nav_home"android:icon="@drawable/ic_home_gray_24dp"android:title="@string/home" /><itemandroid:id="@+id/nav_notifications"android:icon="@drawable/ic_notifications_gray_24dp"android:title="@string/notifications" /></group><group android:id="@+id/group2"><itemandroid:id="@+id/nav_share"android:icon="@drawable/ic_share_gray_24dp"android:title="@string/share" /><itemandroid:id="@+id/nav_send"android:icon="@drawable/ic_send_gray_24dp"android:title="@string/send" /></group></menu>
左侧menu
的布局和主menu
实现方式一致,通过menu
的配置文件来实现。
在这里遇到了两个问题:
- 左侧
menu
字体不是粗体,但是需要粗体 - 左侧
menu
布局的图标和文字之间的间隔太大
第一个问题通过给NavigationView
设置了主题,主题的主要意义就是加粗字体,如下代码:
<style name="MenuTextStyle"><item name="android:textStyle">bold</item>
</style>
第二个问题,通过阅读NavigationView
的源码逐步找到了item
的布局文件,布局文件为design_navigation_menu_item.xml
,于是将布局文件复制到layout
下,并将drawablePadding
改成了20dp
,如下代码:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"><CheckedTextViewandroid:id="@+id/design_menu_item_text"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:drawablePadding="20dp"android:gravity="center_vertical|start"android:maxLines="1"android:textAppearance="@style/TextAppearance.AppCompat.Body2"/><ViewStubandroid:id="@+id/design_menu_item_action_area_stub"android:inflatedId="@+id/design_menu_item_action_area"android:layout="@layout/design_menu_item_action_area"android:layout_width="wrap_content"android:layout_height="match_parent"/></merge>
插一个知识点
可以直接通过Android Studio
来生成需要用到的图标,这里的图标我都是直接通过Android Studio
生成的,生成步骤如下:
接下来说一下主页面的实现,是通过TabLayout
+ViewPage
的方式来实现的,先来看代码:
<?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"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".activity.MainActivity"><android.support.design.widget.AppBarLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:theme="@style/AppTheme.AppBarOverlay"><android.support.v7.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"android:background="?attr/colorPrimary"app:layout_scrollFlags="scroll|enterAlways"app:popupTheme="@style/AppTheme.PopupOverlay" /><android.support.design.widget.TabLayoutandroid:id="@+id/tabLayout"android:layout_width="match_parent"android:layout_height="wrap_content"app:tabBackground="@color/background"app:tabIndicatorColor="@color/colorPrimary"app:tabTextColor="@color/defaultColor"app:tabSelectedTextColor="@color/colorPrimary"app:tabTextAppearance="@style/TabText"/></android.support.design.widget.AppBarLayout><android.support.v4.view.ViewPagerandroid:id="@+id/viewPage"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior"/></android.support.design.widget.CoordinatorLayout>
这里需要注意一下几个知识点:
- 通过给
Toolbar
的layout_scrollFlags
属性设置scroll|enterAlways
并且给ViewPager
设置layout_behavior
属性来实现滑动的时候Toolbar
消失。即当设置layout_behavior
的组件滑动时设置layout_scrollFlags
的组件会移出屏幕 - 给
TabLayout
的tabTextAppearance
设置一个字体样式来实现Tab
页加粗效果
下面主要来说一下activity
部分的代码,先上代码:
package com.example.lanxingren.imitating9gag.activity;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.GravityCompat;
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.example.lanxingren.imitating9gag.R;
import com.example.lanxingren.imitating9gag.adapter.MyFragmentPagerAdapter;
import com.example.lanxingren.imitating9gag.fragment.HomeFragment;
import com.squareup.picasso.Picasso;import java.util.ArrayList;
import java.util.List;import butterknife.BindView;
import butterknife.ButterKnife;
import de.hdodenhof.circleimageview.CircleImageView;public class MainActivity extends AppCompatActivityimplements NavigationView.OnNavigationItemSelectedListener {@BindView(R.id.toolbar)Toolbar toolbar;@BindView(R.id.drawer_layout)DrawerLayout drawer;@BindView(R.id.nav_view)NavigationView navigationView;@BindView(R.id.tabLayout)TabLayout tabLayout;@BindView(R.id.viewPage)ViewPager viewPager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ButterKnife.bind(this);//设置ActionBarsetSupportActionBar(toolbar);//设置DrawerLayout的监听事件,其中后两个参数是给残障人士的语音ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);//设置左上角的三杠图标toggle.syncState();drawer.addDrawerListener(toggle);//设置抽屉的监听事件navigationView.setNavigationItemSelectedListener(this);//直接findViewById会导致NPE,抽屉head部分的头像CircleImageView circleImageView = navigationView.getHeaderView(0).findViewById(R.id.circleImageView);Picasso.with(this).load("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1527745766743&di=c24134fe5233902ca1a60a8665c30a35&imgtype=0&src=http%3A%2F%2Fimg1.sc115.com%2Fuploads%2Fsc%2Fjpg%2F144%2F18628.jpg").into(circleImageView);//定义viewPage的适配器List<Fragment> fragments = new ArrayList();fragments.add(new HomeFragment());fragments.add(new HomeFragment());MyFragmentPagerAdapter adapter = new MyFragmentPagerAdapter(getSupportFragmentManager(), fragments);viewPager.setAdapter(adapter);tabLayout.setupWithViewPager(viewPager);}@Overridepublic void onBackPressed() {if (drawer.isDrawerOpen(GravityCompat.START)) {drawer.closeDrawer(GravityCompat.START);} else {super.onBackPressed();}}/*** 右上角按钮图标* @param menu* @return*/@Overridepublic boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.main, menu);return true;}//右上角按钮点击事件@Overridepublic boolean onOptionsItemSelected(MenuItem item) {return super.onOptionsItemSelected(item);}//左侧抽屉menu点击事件@SuppressWarnings("StatementWithEmptyBody")@Overridepublic boolean onNavigationItemSelected(MenuItem item) {int id = item.getItemId();if (id == R.id.nav_home) {} else if (id == R.id.nav_notifications) {} else if (id == R.id.nav_send) {} else if (id == R.id.nav_share) {}drawer.closeDrawer(GravityCompat.START);return true;}}
知识点:
- 用了
ButterKnife
而不是findViewById
来获取组件 - 用了
Picasso
来加载网络图片,头像以及内部都是通过这种方式来加载的 - 定义了
MyFragmentPagerAdapter
适配器来实现ViewPage
的布局
MyFragmentPagerAdapter
内部的数据实际上为HomeFragment
,而该Fragment
的布局实际上只是一个简单的RecyclerView
,下面上HomeFragment
的代码:
package com.example.lanxingren.imitating9gag.fragment;import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;import com.example.lanxingren.imitating9gag.R;
import com.example.lanxingren.imitating9gag.adapter.NewsAdapter;
import com.example.lanxingren.imitating9gag.bean.NewsBean;import java.util.ArrayList;
import java.util.List;/***/
public class HomeFragment extends Fragment {@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {return inflater.inflate(R.layout.fragment_home, container, false);}@Overridepublic void onStart() {super.onStart();List<NewsBean> newsBeans = new ArrayList<NewsBean>();for (int i = 0; i < 30; i++) {newsBeans.add(new NewsBean("这是第 " + Integer.toString(i+1) + " 条有趣的段子!","http://ws4.sinaimg.cn/mw600/6c560b83ly1fruncq3z03j20ks0rs41b.jpg", 0));}LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());RecyclerView recyclerView = getView().findViewById(R.id.recyclerView);recyclerView.setAdapter(new NewsAdapter(newsBeans));recyclerView.setLayoutManager(linearLayoutManager);}
}
RecyrView
用了NewsAdapter
适配器,适配器代码如下:
package com.example.lanxingren.imitating9gag.adapter;import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;import com.example.lanxingren.imitating9gag.R;
import com.example.lanxingren.imitating9gag.bean.NewsBean;
import com.squareup.picasso.Picasso;import java.util.List;public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.NewsHolder> {private List<NewsBean> myNewsList;private Context myContext;static class NewsHolder extends RecyclerView.ViewHolder {CardView cardView;TextView textView;ImageView imageView;private NewsHolder (View view) {super(view);cardView = (CardView) view;textView = view.findViewById(R.id.item_text);imageView = view.findViewById(R.id.item_image);}}public NewsAdapter (List<NewsBean> newsList) {this.myNewsList = newsList;}@Overridepublic int getItemCount() {int count = 0;if (myNewsList != null) {count = myNewsList.size();}return count;}@NonNull@Overridepublic NewsHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {if (myContext == null) {myContext = parent.getContext();}View view = LayoutInflater.from(myContext).inflate(R.layout.item_news, parent, false);return new NewsHolder(view);}@Overridepublic void onBindViewHolder(@NonNull NewsHolder holder, int position) {NewsBean newsBean = myNewsList.get(position);holder.textView.setText(newsBean.getTitle());int screenWidth = myContext.getResources().getDisplayMetrics().widthPixels;Picasso.with(myContext).load(newsBean.getPicUrl()).resize(screenWidth, 0).into(holder.imageView);}
}
每一项的布局为item_news
,一会儿看具体布局。在onBindViewHolder
中给布局的textView
设置了文字,给imageView
设置了图片。
之前看别人的博客,经常会在适配器中定义一个myContext
,我一直觉得没什么用。但是在这次实际编写适配器的过程中,发现了myContext
还是有很多地方要用到的。
下面来看看item_news
的布局,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_marginVertical="10dp"app:cardCornerRadius="0dp"android:elevation="0dp"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="40dp"android:gravity="center"><TextViewandroid:id="@+id/item_text"android:textStyle="bold"android:textColor="@color/colorPrimary"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_marginLeft="14dp"/><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:src="@drawable/ic_expand_more_gray_24dp"android:layout_marginRight="14dp"/></RelativeLayout><ImageViewandroid:id="@+id/item_image"android:layout_width="match_parent"android:layout_height="wrap_content"android:scaleType="fitCenter"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="40dp"android:orientation="horizontal"android:gravity="center"><LinearLayoutandroid:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"android:orientation="horizontal"><ImageViewandroid:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"android:src="@drawable/ic_thumb_up_gray_24dp"android:scaleType="fitEnd"/><TextViewandroid:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"android:gravity="center"android:text="5k"/><ImageViewandroid:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"android:src="@drawable/ic_thumb_down_gray_24dp"android:scaleType="fitStart"/></LinearLayout><Viewandroid:layout_width="1dp"android:layout_height="20dp"android:background="?android:listDivider"/><LinearLayoutandroid:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"android:gravity="center"><ImageViewandroid:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"android:src="@drawable/ic_comment_gray_24dp"android:scaleType="fitEnd"android:paddingRight="5dp"/><TextViewandroid:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"android:gravity="left"android:text="46"android:paddingLeft="5dp"/></LinearLayout><Viewandroid:layout_width="1dp"android:layout_height="20dp"android:background="?android:listDivider"/><LinearLayoutandroid:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"android:gravity="center"><ImageViewandroid:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"android:src="@drawable/ic_share_gray_24dp"android:scaleType="fitEnd"android:paddingRight="5dp"/><TextViewandroid:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"android:gravity="left"android:text="分享"android:paddingLeft="5dp"/></LinearLayout></LinearLayout></LinearLayout></android.support.v7.widget.CardView>
每一项使用的是卡片式布局,使用了官方的CardView
组件。
通过设置cardCornerRadius
来设置圆角弧度为0
,使得卡片为正矩形。
ImageView
的scaleType
的意思是图片如何填充,其中fitCenter
为居中填充,fitStart
为左对齐填充,fitEnd
为右对齐填充。
写的比较仓促,如有疑问或者错误的地方欢迎留言指正。
仿9GAG制作过程(一)相关推荐
- ss570122的雕刻机制作过程
ss570122的雕刻机制作过程1 作者注:我将以前发表过的几个有关机械和驱动电路的DIY帖子重新整理组合一下重新发表(并会适当增加电源和主轴的DIY内容),为的是方便初入雕刻机制作的网友能够方便的了 ...
- 电脑绣花制版-仿版的过程与注意事项
电脑绣花制版-仿版的过程与注意事项 所谓电脑绣花实样制版,指的是客户提供已经绣作好.形成绣花成品的花样.制版人员根据实样进行二次制版的过程,这也可称之为仿作.它与彩稿制版有以下几个比较: (一)实样制 ...
- (转载)连连看游戏外挂详细制作过程
标 题: [原创]新人入手第一个游戏外挂,附上详细制作过程 作 者: caigui 时 间: 2013-01-09,00:56:16 链 接: http://bbs.pediy.com/showthr ...
- Js黑客帝国效果 文字下落 制作过程和思路
效果预览: http://jsfiddle.net/dtdxrk/m8R6b/embedded/result/ Js黑客帝国效果 文字向下落制作过程和思路 1.css控制文字竖显示 2.动态添加div ...
- Ireport制作过程
Ireport制作过程 1.首先要到Option下设置一下ClassPath添加文件夹 2.到预览->报表字段设置一下将要用到的字段 3.到编辑->查询报表->写sql语句,然后把语 ...
- 简易数字时钟软件详细制作过程
这是我自己用VS2010制作的简易数字时钟小软件,在制作过程中收获知识不少,希望和初学MFC编程的朋友分享一下. 一.其功能有一下三点: 1.打开软件后,其程序自动获取当前电脑系统的日期.时间和周次, ...
- 通过WiFi控制智能小车机器人制作过程详解
之前发的作品都是基于蓝牙控制的智能小车机器人,由于蓝牙的传输范围比较小,所以控制距离的局限性比较大,并且通过蓝牙传输视频会明显出现卡屏的现象. 而通过WiFi方式控制智能小车机器人能达到100米左右的 ...
- rpt水晶报表制作过程
原文:rpt水晶报表制作过程 最近公司安排一个以前的项目,里面需要用到水晶报表,由于原来做这个项目的同事离职,所在公司的同事报表做成了rdlc类型的,而这类报表在加载的时候很难动态的从数据库加载数据, ...
- 电路制版工作笔记001---印刷电路板的制作过程
技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 下面这个是比较严格的过程,四层板的制作流程: PCB 印刷电路板的制作过程 我们来看一下印刷电路板 ...
- 手工制作机器人用彩泥_印度神奇芒果干制作过程,看一遍顶三遍,游客:不会再吃了...
印度神奇芒果干制作过程,看一遍顶三遍,游客:不会再吃了 随着我国经济迅速发展,人们生活水平得到了很大提升,物质消费得到满足以后,人们更注重精神需求,希望通过旅游要开放视野,放松心情,让自己体验不同地域 ...
最新文章
- 自兴人工智能——Python运算符和操作对象
- linux服务器多网卡bond
- UITableView刷新单个cell或者单个Section
- OpenGL Static Texture静态纹理的实例
- 【Linux C 多线程编程】互斥锁与条件变量
- 无法全新安装_好墙板更需好安装:护墙板安装新方法
- .NET 开源项目 Anet 介绍
- Java集合Stream类
- 关于RDLC使用导出PDF文件时,中文乱码解决方案
- 在pycharm中安装pygame
- Java 编程(基础面试题)
- 与计算机相关活动主题,计算机文化节活动策划书
- Win10锁屏之后屏幕自动关闭怎么办
- Doris export任务概率性cancelled第二种情况
- Winsock 10106错误解决方法
- MySQL45讲 读书笔记 22讲MySQL有哪些“饮鸩止渴”提高性能的方法
- 2019,关于我的故事
- 程序员工作9年月薪从1.5K到24K,网友:不如刚毕业985
- java中.的意思_java中“:”的意思是什么?
- JavaBeans 教程
热门文章
- 使用Java实现多个文件压缩打包
- Android浏览器翻译功能调研
- 计算机辅助翻译在翻译实践中的应用,计算机辅助翻译在翻译实践中的应用
- 英语语法 第一章 句子的形成——概说
- GoldWave教程分享:删除声道该怎么操作?
- SQL Server 数据库之视图(二)
- html css屏蔽右键,css右键菜单.html
- w10计算机右键管理,Win10右键菜单怎么管理
- 计算机图表制作教程,echarts入门教程 5分钟上手制作ECharts图表
- ime输入法android,创建输入法 | Android 开发者 | Android Developers