ViewDragHelper实战 自己打造Drawerlayout,2024年最新android企业项目实战开发工程师

final int contentHeightSpec = MeasureSpec.makeMeasureSpec(

heightSize - lp.topMargin - lp.bottomMargin, MeasureSpec.EXACTLY);

contentView.measure(contentWidthSpec, contentHeightSpec);

mLeftMenuView = leftMenuView;

mContentView = contentView;

}

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b)

{

View menuView = mLeftMenuView;

View contentView = mContentView;

MarginLayoutParams lp = (MarginLayoutParams) contentView.getLayoutParams();

contentView.layout(lp.leftMargin, lp.topMargin,

lp.leftMargin + contentView.getMeasuredWidth(),

lp.topMargin + contentView.getMeasuredHeight());

lp = (MarginLayoutParams) menuView.getLayoutParams();

final int menuWidth = menuView.getMeasuredWidth();

int childLeft = -menuWidth + (int) (menuWidth * mLeftMenuOnScrren);

menuView.layout(childLeft, lp.topMargin, childLeft + menuWidth,

lp.topMargin + menuView.getMeasuredHeight());

}

@Override

public boolean onInterceptTouchEvent(MotionEvent ev)

{

boolean shouldInterceptTouchEvent = mHelper.shouldInterceptTouchEvent(ev);

return shouldInterceptTouchEvent;

}

@Override

public boolean onTouchEvent(MotionEvent event)

{

mHelper.processTouchEvent(event);

return true;

}

@Override

public void computeScroll()

{

if (mHelper.continueSettling(true))

{

invalidate();

}

}

public void closeDrawer()

{

View menuView = mLeftMenuView;

mLeftMenuOnScrren = 0.f;

mHelper.smoothSlideViewTo(menuView, -menuView.getWidth(), menuView.getTop());

}

public void openDrawer()

{

View menuView = mLeftMenuView;

mLeftMenuOnScrren = 1.0f;

mHelper.smoothSlideViewTo(menuView, 0, menuView.getTop());

}

@Override

protected LayoutParams generateDefaultLayoutParams()

{

return new MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

}

public LayoutParams generateLayoutParams(AttributeSet attrs)

{

return new MarginLayoutParams(getContext(), attrs);

}

protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p)

{

return new MarginLayoutParams§;

}

}

哈,很少的代码就完成了我们的侧滑的编写,目测如果使用横向的LinearLayout代码更短。构造方法中,主要就是初始化我们的mDragHelper了,接下来onMeasure和onLayout都比较简单,onLayout也只是去将我们的menu设置到屏幕的左侧以至于不可见。onInterceptTouchEventonTouchEvent中都只需要简单的调用mDragHelper的方法。那么核心代码都在我们的ViewDragHelper.Callback的实例中了。注意一点:我们LeftDrawerLayout默认的LayoutParams为MarginLayoutParams,注意复写相关方法。

接下来就把注意力放到我们的Callback中,我尽可能的按照调用的逻辑来解释各个方法:

  • onEdgeDragStarted 如果你仔细的看过上篇,那么一定知道这个方法的回调位置;因为我们的View不可见,所以我们没有办法直接通过触摸到它来把menu设置为captureView,所以我们只能设置边界检测,当MOVE时回调onEdgeDragStarted时,我们直接通过captureChildView手动捕获。

  • tryCaptureView 那么既然我们手动捕获了,为什么还需要这个方法呢?主要是因为当Drawer拉出的时候,我们通过拖拽Drawer也能进行移动菜单。

  • clampViewPositionHorizontal 主要是移动的时候去控制控制范围,可以看到我们的int newLeft = Math.max(-child.getWidth(), Math.min(left, 0));一定>=-child.getWidth() && <=0 。

  • getViewHorizontalDragRange 为什么要复写,我们上篇已经描述过,返回captureView的移动范围。

  • onViewReleased 则是释放的时候触发的,我们计算当前显示的百分比,以及加速度来决定是否显示drawer,从代码可以看出,当xvel > 0 || xvel == 0 && offset > 0.5f显示我们的菜单,其他情况隐藏。这里注意一点xvel的值只有大于我们设置的minVelocity才会出现大于0,如果小于我们设置的值则一直是0。

  • onViewPositionChanged 整个pos变化的过程中,我们计算offset保存,这里可以使用接口将offset回调出去,方便做动画。

ok,我们重写的所有方法描述完成了那么博文主要内容也就结束了哈~是不是 so easy ~!

呃,忘了MainActivity和Fragment的代码了~~按顺序贴

(三)LeftDrawerLayoutActivity

package com.imooc.testandroid;

import android.os.Bundle;

import android.support.v4.app.FragmentManager;

import android.support.v7.app.ActionBarActivity;

import android.view.Menu;

import android.view.MenuItem;

import android.widget.TextView;

import com.zhy.learn.view.LeftDrawerLayout;

public class LeftDrawerLayoutActivity extends ActionBarActivity

{

private LeftMenuFragment mMenuFragment;

private LeftDrawerLayout mLeftDrawerLayout ;

private TextView mContentTv ;

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_left_drawer_layout);

mLeftDrawerLayout = (LeftDrawerLayout) findViewById(R.id.id_drawerlayout);

mContentTv = (TextView) findViewById(R.id.id_content_tv);

FragmentManager fm = getSupportFragmentManager();

mMenuFragment = (LeftMenuFragment) fm.findFragmentById(R.id.id_container_menu);

if (mMenuFragment == null)

{

fm.beginTransaction().add(R.id.id_container_menu, mMenuFragment = new LeftMenuFragment()).commit();

}

mMenuFragment.setOnMenuItemSelectedListener(new LeftMenuFragment.OnMenuItemSelectedListener()

{

@Override

public void menuItemSelected(String title)

{

mLeftDrawerLayout.closeDrawer();

mContentTv.setText(title);

}

});

}

可以看到drawer使用了一个Fragment ~~

(四) LeftMenuFragment

import android.os.Bundle;

import android.support.annotation.Nullable;

import android.support.v4.app.ListFragment;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.ListView;

/**

  • Created by zhy on 15/4/26.

*/

public class LeftMenuFragment extends ListFragment {

private static final int SIZE_MENU_ITEM = 3;

private MenuItem[] mItems = new MenuItem[SIZE_MENU_ITEM];

private LeftMenuAdapter mAdapter;

private LayoutInflater mInflater;

@Override

public void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

mInflater = LayoutInflater.from(getActivity());

MenuItem menuItem = null;

for (int i = 0; i < SIZE_MENU_ITEM; i++) {

menuItem = new MenuItem(getResources().getStringArray(R.array.array_left_menu)[i], false, R.drawable.music_36px, R.drawable.music_36px_light);

mItems[i] = menuItem;

}

}

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

return super.onCreateView(inflater, container, savedInstanceState);

}

@Override

public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {

super.onViewCreated(view, savedInstanceState);

view.setBackgroundColor(0xffffffff);

setListAdapter(mAdapter = new LeftMenuAdapter(getActivity(), mItems));

}

@Override

public void onListItemClick(ListView l, View v, int position, long id) {

super.onListItemClick(l, v, position, id);

if (mMenuItemSelectedListener != null) {

mMenuItemSelectedListener.menuItemSelected(((MenuItem) getListAdapter().getItem(position)).text);

}

mAdapter.setSelected(position);

}

//选择回调的接口

public interface OnMenuItemSelectedListener {

void menuItemSelected(String title);

}

private OnMenuItemSelectedListener mMenuItemSelectedListener;

public void setOnMenuItemSelectedListener(OnMenuItemSelectedListener menuItemSelectedListener) {

this.mMenuItemSelectedListener = menuItemSelectedListener;

}

}

public class MenuItem

{

public MenuItem(String text, boolean isSelected, int icon, int iconSelected) {

this.text = text;

this.isSelected = isSelected;

this.icon = icon;

this.iconSelected = iconSelected;

}

boolean isSelected;

String text;

int icon;

int iconSelected;

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

最后

最后这里放上我这段时间复习的资料,这个资料也是偶然一位朋友分享给我的,里面包含了腾讯、字节跳动、阿里、百度2020-2021面试真题解析,并且把每个技术点整理成了视频和PDF(知识脉络 + 诸多细节)。

还有 高级架构技术进阶脑图、高级进阶架构资料 帮助大家学习提升进阶,这里我也免费分享给大家也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

一起互勉~

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img
觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)**
[外链图片转存中…(img-9YPCw2uk-1712770551761)]

最后

最后这里放上我这段时间复习的资料,这个资料也是偶然一位朋友分享给我的,里面包含了腾讯、字节跳动、阿里、百度2020-2021面试真题解析,并且把每个技术点整理成了视频和PDF(知识脉络 + 诸多细节)。

还有 高级架构技术进阶脑图、高级进阶架构资料 帮助大家学习提升进阶,这里我也免费分享给大家也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

[外链图片转存中…(img-5blz9rPO-1712770551761)]

[外链图片转存中…(img-7MqTrrlX-1712770551761)]

一起互勉~

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-VkBZO5lh-1712770551762)]

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值