这是我的第二篇实战,相比于第一篇的看视频模仿着实战,这一篇完全是自己的实战,不借助任何视频教程,看视频的实战是在抄代码,而这一篇是完全自己构思,自己去解决问题的,这次的实战是仿照一个社交软件探探,该篇是这部分的第一篇主要讲一讲抽屉菜单DrawerLayout

以下是我们的效果,这是在点击了 左上角的按钮后呈现出来的。

看了效果图后,我们来回到布局代码中来看看吧!

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/drawer_layout"android:layout_width="match_parent"android:layout_height="match_parent" ><FrameLayoutandroid:id="@+id/middle_frame"android:layout_width="match_parent"android:layout_height="match_parent" ></FrameLayout><RelativeLayoutandroid:id="@+id/left_menu"android:layout_width="240dp"android:layout_height="match_parent"android:layout_gravity="left"android:background="#000000" ><LinearLayoutandroid:layout_width="240dp"android:layout_height="match_parent"android:orientation="vertical" ><com.example.library.CircleImageViewandroid:layout_width="160dp"android:layout_height="160dp"android:layout_centerInParent="true"android:layout_gravity="center"android:src="@drawable/hugh"app:border_color="@color/light"app:border_width="2dp" /><ListViewandroid:id="@+id/left_drawer"android:layout_width="240dp"android:layout_height="match_parent"android:layout_marginTop="50dp" ></ListView></LinearLayout></RelativeLayout></android.support.v4.widget.DrawerLayout>

接下来我们就这些个代码来讲解讲解一下吧!
首先我们看的是根标签,这次的根标签是

<android.support.v4.widget.DrawerLayout>

……

</android.support.v4.widget.DrawerLayout>

从这可以看出的是我们用到的Drawerlayout是support.v4下的一个类,使用这个类我们可以很方便的完成上述的效果,当然我不是说这里只能使用这个去完成,还有SlidingMenu……等许多个标签去完成,同样可以达到我们一样的效果,(SlidingMenu例子),在这里我们就拿DrawerLayout这个来讲解了。

讲完根标签以后我们继续往下看,可以看到的是一个FrameLayout布局,这个布局是我们用来放置主要内容的,在后续的实战中我们会在这里放置一个地图,定位在您所在的位置。

接着往下看是一个RelativeLayout嵌套了一个LinearLayout,在LinearLayout中有一个这个<com.example.library.CircleImageView />和一个<ListView />

对于ListView的我就不多讲了,在这里ListView我们就那俩放一下抽屉上的一些菜单选项,至于<com.example.library.CircleImageView />这个我们想放一下,我们把LinearLayout和RelativeLayout讲完在讲<com.example.library.CircleImageView />这个,LinearLayout在这是就是为了让我们看到的效果是头像在上,菜单选项在下,而整个的LinearLayout有放置在RelativeLayout中,在RelativeLayout的几个属性中最要在意个就是android:layout_gravity="left",这样设置的目的使得抽屉是从左边出来的,我们一般都是使用left和right的,当然你用start和end同样也是可以的,毕竟left和right更直观一些。好了,一些零碎的讲完了,我们来讲一下 <com.example.library.CircleImageView />这个,一般情况下我们如果放一个ImageView上去,我们看到了图片是一个矩形的,而我们想要一个圆形的或者圆角矩形的我们就要重写ImageView这个类,在这个类中设置我们自己想要的ImageView的样式,这里我们就把样式设置成圆形呈现。

我们来看一下这个类CircleIamgeView.class

package com.example.library;import com.myself.tantan.*;import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
//import android.support.annotation.ColorRes;
//import android.support.annotation.DrawableRes;
import android.util.AttributeSet;
import android.widget.ImageView;public class CircleImageView extends ImageView {private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;private static final int COLORDRAWABLE_DIMENSION = 2;private static final int DEFAULT_BORDER_WIDTH = 0;private static final int DEFAULT_BORDER_COLOR = Color.BLACK;private static final boolean DEFAULT_BORDER_OVERLAY = false;private final RectF mDrawableRect = new RectF();private final RectF mBorderRect = new RectF();private final Matrix mShaderMatrix = new Matrix();private final Paint mBitmapPaint = new Paint();private final Paint mBorderPaint = new Paint();private int mBorderColor = DEFAULT_BORDER_COLOR;private int mBorderWidth = DEFAULT_BORDER_WIDTH;private Bitmap mBitmap;private BitmapShader mBitmapShader;private int mBitmapWidth;private int mBitmapHeight;private float mDrawableRadius;private float mBorderRadius;private ColorFilter mColorFilter;private boolean mReady;private boolean mSetupPending;private boolean mBorderOverlay;public CircleImageView(Context context) {super(context);init();}public CircleImageView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public CircleImageView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH);mBorderColor = a.getColor(R.styleable.CircleImageView_border_color, DEFAULT_BORDER_COLOR);mBorderOverlay = a.getBoolean(R.styleable.CircleImageView_border_overlay, DEFAULT_BORDER_OVERLAY);a.recycle();init();}private void init() {super.setScaleType(SCALE_TYPE);mReady = true;if (mSetupPending) {setup();mSetupPending = false;}}@Overridepublic ScaleType getScaleType() {return SCALE_TYPE;}@Overridepublic void setScaleType(ScaleType scaleType) {if (scaleType != SCALE_TYPE) {throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));}}@Overridepublic void setAdjustViewBounds(boolean adjustViewBounds) {if (adjustViewBounds) {throw new IllegalArgumentException("adjustViewBounds not supported.");}}@Overrideprotected void onDraw(Canvas canvas) {if (getDrawable() == null) {return;}canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint);if (mBorderWidth != 0) {canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint);}}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);setup();}public int getBorderColor() {return mBorderColor;}public void setBorderColor(int borderColor) {if (borderColor == mBorderColor) {return;}mBorderColor = borderColor;mBorderPaint.setColor(mBorderColor);invalidate();}//    public void setBorderColorResource(@ColorRes int borderColorRes) {
//        setBorderColor(getContext().getResources().getColor(borderColorRes));
//    }public int getBorderWidth() {return mBorderWidth;}public void setBorderWidth(int borderWidth) {if (borderWidth == mBorderWidth) {return;}mBorderWidth = borderWidth;setup();}public boolean isBorderOverlay() {return mBorderOverlay;}public void setBorderOverlay(boolean borderOverlay) {if (borderOverlay == mBorderOverlay) {return;}mBorderOverlay = borderOverlay;setup();}@Overridepublic void setImageBitmap(Bitmap bm) {super.setImageBitmap(bm);mBitmap = bm;setup();}@Overridepublic void setImageDrawable(Drawable drawable) {super.setImageDrawable(drawable);mBitmap = getBitmapFromDrawable(drawable);setup();}//    @Override
//    public void setImageResource(@DrawableRes int resId) {
//        super.setImageResource(resId);
//        mBitmap = getBitmapFromDrawable(getDrawable());
//        setup();
//    }@Overridepublic void setImageURI(Uri uri) {super.setImageURI(uri);mBitmap = getBitmapFromDrawable(getDrawable());setup();}@Overridepublic void setColorFilter(ColorFilter cf) {if (cf == mColorFilter) {return;}mColorFilter = cf;mBitmapPaint.setColorFilter(mColorFilter);invalidate();}private Bitmap getBitmapFromDrawable(Drawable drawable) {if (drawable == null) {return null;}if (drawable instanceof BitmapDrawable) {return ((BitmapDrawable) drawable).getBitmap();}try {Bitmap bitmap;if (drawable instanceof ColorDrawable) {bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);} else {bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);}Canvas canvas = new Canvas(bitmap);drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());drawable.draw(canvas);return bitmap;} catch (OutOfMemoryError e) {return null;}}private void setup() {if (!mReady) {mSetupPending = true;return;}if (mBitmap == null) {return;}mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);mBitmapPaint.setAntiAlias(true);mBitmapPaint.setShader(mBitmapShader);mBorderPaint.setStyle(Paint.Style.STROKE);mBorderPaint.setAntiAlias(true);mBorderPaint.setColor(mBorderColor);mBorderPaint.setStrokeWidth(mBorderWidth);mBitmapHeight = mBitmap.getHeight();mBitmapWidth = mBitmap.getWidth();mBorderRect.set(0, 0, getWidth(), getHeight());mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, (mBorderRect.width() - mBorderWidth) / 2);mDrawableRect.set(mBorderRect);if (!mBorderOverlay) {mDrawableRect.inset(mBorderWidth, mBorderWidth);}mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2);updateShaderMatrix();invalidate();}private void updateShaderMatrix() {float scale;float dx = 0;float dy = 0;mShaderMatrix.set(null);if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {scale = mDrawableRect.height() / (float) mBitmapHeight;dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;} else {scale = mDrawableRect.width() / (float) mBitmapWidth;dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;}mShaderMatrix.setScale(scale, scale);mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top);mBitmapShader.setLocalMatrix(mShaderMatrix);}}

这个是我从github上下载的一个开源库,然后放到自己的项目中来使用的,记得先新建一个包哦,这里的代码我就不解释了,有些我还解释不清楚,我就不在这里误人子弟了,如果有哪位大神明白了可以教教我,大家一起进步。

到此为止,我们的布局就讲解完了,讲解了布局以后,我们在来看看MainActivity。

private DrawerLayout mDrawerLayout;private RelativeLayout left_menu;private RelativeLayout right_menu;private ListView left_mDrawerList;private ListView right_mDrawerList;private ActionBarDrawerToggle left_Toggle;private SimpleAdapter sAdapter;List<Map<String, Object>> left_list = new ArrayList<Map<String, Object>>();private ArrayAdapter<String> r_adapter;// 数据源private int[] res = { R.drawable.ic_action_place,R.drawable.ic_action_unread, R.drawable.ic_action_favorite,R.drawable.ic_action_settings, R.drawable.ic_action_about };private String[] name = { "探探", "消息", "匿名暗恋表白", "设置", "新手引导" };@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);SDKInitializer.initialize(getApplicationContext());setContentView(R.layout.activity_main);mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);left_menu = (RelativeLayout) findViewById(R.id.left_menu);right_menu = (RelativeLayout) findViewById(R.id.right_menu);left_menu.setAlpha(0.8f);left_mDrawerList = (ListView) findViewById(R.id.left_drawer);right_mDrawerList = (ListView) findViewById(R.id.right_drawer);r_adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, name);right_mDrawerList.setAdapter(r_adapter);for (int i = 0; i < res.length; i++) {Map<String, Object> map = new HashMap<String, Object>();map.put("name", name[i]);map.put("src", res[i]);left_list.add(map);}/** abour SimpleAdapter* http://blog.csdn.net/x605940745/article/details/11981049*/sAdapter = new SimpleAdapter(this, left_list, R.layout.left_item,new String[] { "name", "src" }, new int[] { R.id.tvName,R.id.img });left_mDrawerList.setAdapter(sAdapter);left_mDrawerList.setOnItemClickListener(this);left_Toggle = new ActionBarDrawerToggle(this, mDrawerLayout,R.drawable.ic_drawer, R.string.drawer_open,R.string.drawer_close) {@Overridepublic void onDrawerOpened(View drawerView) {super.onDrawerOpened(drawerView);invalidateOptionsMenu();}@Overridepublic void onDrawerClosed(View drawerView) {super.onDrawerClosed(drawerView);invalidateOptionsMenu();}};mDrawerLayout.setDrawerListener(left_Toggle);getActionBar().setDisplayHomeAsUpEnabled(true);getActionBar().setHomeButtonEnabled(true);}

一部分一部分来讲,这部分主要是一些空间的获取和设置监听事件和绑定适配器和数据源。

从内部标签到根标签的顺序来讲,首先要讲的是ListView的适配器绑定,从效果图上可以看到,在文字前面还有几个图标,因此我们在这里如果单纯的使用ArrayAdapter就显得不是那么合适了,当然如果你愿意,你也可以重写一下BaseAdapter,使用自定义的Adapter来实现我们的效果,这里简单的我们就使用了SimpleAdapter,如果关于SimpleAdapter还有疑问的话,在上面注释中有一个专门讲解SimpleAdapter 的,可以参考一下的。至于ListView的监听事件就不多讲了,实现一下OnItemClickListener,重写一下方法就可以了,之后会贴代码的。

讲完ListView之后我们也就这剩下关于DrawerLayout的监听事件了。要实现DrawerLayout的监听事件我们就要用到一个ActionBarDrawerToggle,通过这个来绑定按钮以及抽屉的拉开和关上时的情况。我们用到了ActionBarDrawerToggle,那么我们最好就重写一下onPostCreate和onConfigurationChanged这两个方法

@Overrideprotected void onPostCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onPostCreate(savedInstanceState);left_Toggle.syncState();}@Overridepublic void onConfigurationChanged(Configuration newConfig) {super.onConfigurationChanged(newConfig);left_Toggle.onConfigurationChanged(newConfig);}

OnItemClickListener的点击事件

 @Overridepublic void onItemClick(AdapterView<?> arg0, View arg1, int position,long arg3) {// 动态插入一个Fragment到FrameLayout中ContentFragment contentFragment = new ContentFragment();Bundle args = new Bundle();args.putString("text", left_mDrawerList.getItemAtPosition(position).toString());contentFragment.setArguments(args);FragmentManager fm = getFragmentManager();// 开启一个事务fm.beginTransaction().replace(R.id.middle_frame, contentFragment).commit();mDrawerLayout.closeDrawer(left_menu);}

上述的一些定义中有right的是因为我在这个项目中还有一个右边的抽屉,效果和左边的差不多,布局中也就是之后再加一个RelativeLayout,然后修改layout_graVity=“right”。
到此,该项目的第一步布局就完成的差不多了,接下来我要完成的目标就是实现地图的定位显示。

Android实战第二篇——模仿社交软件探探(一)相关推荐

  1. Android 进阶第二篇——性能优化

    Android 进阶第二篇--性能优化 一些Android书籍喜欢把性能优化放在最后的章节,简单提一提作为内容全面的点缀.在这里我将工具使用和性能优化的一些个人经验放在进阶系列博客的开始,因为我认为防 ...

  2. <Android开发> Android vold - 第二篇 vold 的main()函数简介

    本系列主要介绍 Android vold,分为以下篇章 <Android开发> Android vold - 第一篇 vold前言简介 <Android开发> Android ...

  3. vue 动态修改后端请求_vue-element-admin实战 | 第二篇: 最小改动接入后台实现根据权限动态加载菜单...

    一. 前言 本篇基于 有来商城 youlai-mall微服务项目,通过对vue-element-admin的权限菜单模块理解个性定制其后台接口,实现对vue-element-admin工程几乎不做改动 ...

  4. linux上的社交软件下载,探探交友app免费版-探探交友真实app下载v4.2.9.2-Linux公社...

    探探交友app是一款非常好用的社交聊天平台,使用方法非常简单,喜欢的话可以将名片向右滑,不喜欢的话就向左滑,只有相互喜欢的两人才可以开始聊天,避免了很多陌生人的消息,减少骚扰,探探交友app免费版非常 ...

  5. Android实战第一篇——时钟+闹钟+计时器+秒表

    学习了快一学期的Android了,之前的知识点都是零散的学习的,只有当我们真正的去把他们用起来的时候才会发现难点,自己才会独立尝试去解决某个问题.接下来是我的一个简单的多功能时钟的小实战(视频资源ht ...

  6. Android提高第二篇之SurfaceView的基本使用

    本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处! 上次介绍MediaPlayer的时候稍微介绍了SurfaceView,SurfaceView由于可以直接从内存 ...

  7. 狸窝音频剪辑软件_剪映零基础入门教程第二篇:剪辑软件剪映的音频功能怎么样...

    在制作短视频的时候大家常用的剪辑软件有哪些呢?说实话目前市面上的剪辑软件还是比较多的,有时候让用户们都纠结于到底哪款软件才是最好用的那款呢?但是我想用的最多的还是抖音自家推出的小软件剪映吧,不仅仅是因 ...

  8. Java爬虫实战第二篇:IOS、安卓应用爬虫

    1.选择应用:IOS下blued应用(当然也可以其他APP) 2.下载fiddler手机抓包软件到电脑上 fiddler:下载地址 解压后安装FiddlerSetup.exe 3.安装后运行Fiddl ...

  9. SpringCloud Alibaba实战--第二篇:NacosⅠ服务注册和配置中心

    系列文章目录 微服务新王SpringCloudAlibaba 文章目录 系列文章目录 前言 一.Nacos是什么?能干啥? 二.Nacos下载及安装 1. 下载 2. 安装并运行 3. 对比Eurek ...

最新文章

  1. 字节跳动大佬的Python自学笔记.pdf
  2. sqlserver 查找某个字段在哪张表里
  3. android 退出app代码_uniapp退出APP应用(IOS+安卓)
  4. 一位 CEO 在战略沟通会上的员工问答实录
  5. win10 mysql root密码_win10 mysql5.7root密码多少
  6. ruijie交换机lacp动态_Server2016和华为s5720交换机链路聚合增加带宽
  7. MySQL优化SQL性能问题
  8. 查找算法之三 插值查找(C++版本)
  9. 《非暴力沟通》-马歇尔·卢森堡
  10. 计算机主板CPU接口最多支持,CPU供电接口
  11. PDF文件如何插入图片?简单的操作方法
  12. [opencv4]——fatal error: opencv2/opencv.hpp: No such file or directory #include <opencv2/opencv.hpp>
  13. 上网行为安全之流量管理技术
  14. mmorpg游戏设计之2D游戏地图的九宫格子
  15. poi 获取excel单元格超链接和设置excel单元格超链接及导出excel
  16. 语音的时频分析(一)
  17. 计算机毕业设计JAVA离散制造业产品销售管理系统mybatis+源码+调试部署+系统+数据库+lw
  18. oppo手机怎么分屏android,OPPO手机怎么分屏 OPPO手机设置分屏模式的方法
  19. 智能声控娱乐新势力,华为平板M5青春版更懂你
  20. vue-cli初次搭建项目脚手架的过程(前后端分离第一步)

热门文章

  1. Python的字符编码
  2. 产品读书《AI人工智能:发展简史+技术案例+商业应用》
  3. 解决在win10的1703版中Chrome代理无效
  4. 计算机高中合肥,合肥市一名高中生被美国麻省理工学院录取,系安徽省首位
  5. 《Python程序设计(第3版)》[美] 约翰·策勒(John Zelle) 第 6 章 答案
  6. 微风:新手必看PS实用技巧大全
  7. 举个栗子~Tableau 技巧(237):用多节点瀑布图分阶段查看数据
  8. jQuery 绑定3种鼠标事件 click(鼠标点击),mouseover(鼠标移入),mouseout(鼠标移开)
  9. C# Nut Shell 第九章 LINQ运算符
  10. 【POJ】2786-Keep the Customer Satisfied(贪心 + 优先队列,姿势不对就要跪)