代码地址如下:
http://www.demodashi.com/demo/12826.html

前言:

前几天在看手机直播的时候,自己就用上了触手app。一进到主页就看上了里面页面切换的效果,自己想这种效果用什么控件可以实现呢。不闲扯了,直接上图更有意思。

触手app新版已经改版了,大家请下载。

效果图:

触手app主页效果图:

看到这个效果图后,第一想到的就是RecyclerView貌似可以实现这种效果,但是用RecyclerView自己的api还是有很多问题的,先不说如何实现的吧,看下实现出来的效果图吧:

图片式:

流式布局效果:

多种样式效果:

教你一分钟搞定如何使用:

设置Manager:

  1. RecyclerView chuShouView = (RecyclerView) findViewById(R.id.chushou_view);
  2. chuShouView.setLayoutManager(new ChuShouManager());

设置触摸辅助类ChuShouCallBack:

  1. ItemTouchHelper.Callback callback = new ChuShouCallBack(adapter, maps, ItemTouchHelper.UP | ItemTouchHelper.DOWN);
  2. ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);
  3. itemTouchHelper.attachToRecyclerView(chuShouView);

图片式设置Adapter:

  1. chuShouView.setAdapter(adapter = new ChuShouAdapter(this, maps));

流式布局式设置Adapter:

  1. chuShouView.setAdapter(adapter = new ChuShouScrollAdapter(this, items));

多种样式设置Adapter:

  1. chuShouView.setAdapter(chuShouGridAdapter = new ChuShouGridAdapter(this, gridItems));

这里面的流式布局的Adapter和多种样式的Adapter有一个共同点,它们的item都是带有滑动结构的,因此这里我把它们的结构当成RecyclerView+RecyclerView来处理了,而上面的图片式结构就是RecyclerView+ImageView来处理了,大家可以着重看看ChuShouScrollAdapterChuShouGridAdapter代码:

ChuShouGridAdapteronCreateViewHolder方法:

  1. @Override
  2. public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  3. return new MyHolder<ChuShouGridActivity.GridItem>(View.inflate(context, R.layout.scroll_item_layout, null), context) {
  4. @Override
  5. protected RecyclerView.Adapter<RecyclerView.ViewHolder> getAdapter(List<ChuShouGridActivity.GridItem> list, Context context) {
  6. return new ChuShouGridItemAdapter(list, context);
  7. }
  8. @Override
  9. protected RecyclerView.LayoutManager getLayoutManager(Context context, RecyclerView.Adapter<RecyclerView.ViewHolder> adapter) {
  10. return new ChuShouGridLayoutManager(context, adapter);
  11. }
  12. };
  13. }

ChuShouScrollAdapteronCreateViewHolder方法:

  1. @Override
  2. public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  3. return new MyHolder<ChuShouScrollActivity.ShowItem>(View.inflate(context, R.layout.scroll_item_layout, null), context) {
  4. @Override
  5. protected RecyclerView.Adapter<RecyclerView.ViewHolder> getAdapter(List<ChuShouScrollActivity.ShowItem> list, Context context) {
  6. return new FlowAdapter(list, context);
  7. }
  8. @Override
  9. protected RecyclerView.LayoutManager getLayoutManager(Context context, RecyclerView.Adapter<RecyclerView.ViewHolder> adapter) {
  10. return new FlowLayoutManager();
  11. }
  12. };
  13. }

R.layout.scroll_item_layout代码:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:background="#cccccc"
  6. android:orientation="vertical">
  7. <com.library.chushou.view.SlideRecyclerView
  8. android:id="@+id/container"
  9. android:layout_width="match_parent"
  10. android:layout_height="match_parent" />
  11. </LinearLayout>

使用方面就注意这些了,下面就讲讲是怎么实现该效果的。。。

讲解:

下面就来讲讲如何用RecyclerView如何实现上面的效果了:

先来张自己画的思路草图吧:

这里整体就是一个RecyclerView了,而且在初始的时候,需要定义我们自己的Layoutmanager,代码里面可见(ChuShouManager)该类,该Layoutmanager的功能就是让最后一个item在屏幕的上面显示,第一个item在屏幕中显示,第二个item到倒数第二个item在屏幕的下面显示。所以手机上面显示的永远是RecyclerView中第一个item了,只不过在手指滑动的时候,去改变数据源。

  1. /**
  2. * Created by xiangcheng on 17/4/11.
  3. * 初始化RecyclerView中所有item的位置
  4. */
  5. public class ChuShouManager extends RecyclerView.LayoutManager {
  6. @Override
  7. public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
  8. *******省略代码******
  9. //防止数量没达到1个以上的要求
  10. if (getChildCount() >= 1) {
  11. //第一个item放在屏幕中
  12. if (i == 0) {
  13. layoutDecoratedWithMargins(childAt, 0, 0,
  14. getDecoratedMeasuredWidth(childAt),
  15. getDecoratedMeasuredHeight(childAt));
  16. }
  17. }
  18. //需要判断数量
  19. if (getChildCount() >= 2) {
  20. //从第二个item到倒数第二个放在屏幕下面
  21. if (i >= 1 && i < getItemCount() - 1) {
  22. layoutDecoratedWithMargins(childAt,
  23. 0, getHeight(),
  24. getDecoratedMeasuredWidth(childAt),
  25. getHeight() +getDecoratedMeasuredHeight(childAt));
  26. }
  27. }
  28. //数量要求
  29. if (getChildCount() >= 3) {
  30. //最后一个item放在屏幕上面
  31. if (i == getItemCount() - 1) {
  32. layoutDecoratedWithMargins(childAt,
  33. 0, -getDecoratedMeasuredHeight(childAt),
  34. getDecoratedMeasuredWidth(childAt),0);
  35. }
  36. }
  37. }
  38. @Override
  39. public RecyclerView.LayoutParams generateDefaultLayoutParams() {
  40. //这里就直接定义recyclerView里面item直接占满整个屏幕了
  41. return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
  42. }
  43. }

好了,第一步终于完成啦,下面就是RecyclerViewtouch相关代码控制了,关于touch的控制,我们需要接触到android.support.v7.widget.helper.ItemTouchHelper.Callback该类了:

从源码截图中看到该类是一个静态的抽象类,说明我们要使用的时候,需要去实现该类了。这里定义了一个实现类ChuShouCallBackCallBack抽象类定义了只是定义了我们的Drag(拖拽)动作,实际上我们要用的是SimpleCallback子类,该类实现了我们的Swipe(滑动)动作。因此这里需要屏蔽Drag动作,实现Swipe动作。

屏蔽Drag动作,实现Swipe动作:

  1. public class ChuShouCallBack extends ItemTouchHelper.SimpleCallback {
  2. *****省略代码*****
  3. //该构造器屏蔽了swipDirection
  4. public ChuShouCallBack(RecyclerView.Adapter adapter, List mDatas) {
  5. this(adapter, mDatas, 0);
  6. }
  7. //该构造器接收传进来的swipDirection
  8. public ChuShouCallBack(RecyclerView.Adapter adapter, List mDatas, int swipDirection) {
  9. this(0, swipDirection);
  10. this.mAdapter = adapter;
  11. this.mDatas = mDatas;
  12. }
  13. public ChuShouCallBack(int dragDirs, int swipeDirs) {
  14. super(dragDirs, swipeDirs);
  15. }
  16. *****省略代码*****
  17. }

下面看看RecyclerView滑动Item的监听

  1. @Override
  2. public void onChildDraw(Canvas c, RecyclerView recyclerView, final RecyclerView.ViewHolder viewHolder, float dX, float dY, int act
  3. // super.onChildDraw(c,recyclerView,viewHolder,dX,dY,actionState,isCurrentlyActive);这里就不要执行父类的该方法了,执行后就会让当前item随手势移动了,这样就不是我们想
  4. Log.d(TAG,"dy")
  5. if (height == 0) {
  6. height = recyclerView.getHeight();
  7. }
  8. Log.d(TAG, "dy:" + dY + ",actionState:" + actionState + ",isCurrentlyActive:" + isCurrentlyActive);
  9. Log.d(TAG, "lastDy:" + lastDy);
  10. //add 2017/4/17,此时换了手指再去按住nextView,如果是下拉时:lastDy > 0 && dY <= 0,如果是上拉时:lastDy < 0 && dY >= 0
  11. Log.d(TAG, "height * getSwipeThreshold(viewHolder):" + height * getSwipeThreshold(viewHolder));
  12. if (lastDy > 0 && dY <= 0 || lastDy < 0 && dY >= 0) {
  13. if (lastDy > 0 && dY <= height * getSwipeThreshold(viewHolder) || lastDy < 0 && dY >= 0) {
  14. //这个是当松手时isCurrentlyActive=false
  15. if (!isCurrentlyActive) {
  16. if (valueAnimator == null) {
  17. //从松手一瞬间,从lastDy的位置到0
  18. valueAnimator = ValueAnimator.ofFloat(lastDy, 0);
  19. //这里的下拉或上拉的最大距离是按照swipe的临界值来算的
  20. float maxPullHeight = height * getSwipeThreshold(viewHolder);
  21. //最长的时间是200毫秒
  22. float duration = 200 * (Math.abs(lastDy) / maxPullHeight);
  23. valueAnimator.setDuration((long) duration);
  24. valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  25. @Override
  26. public void onAnimationUpdate(ValueAnimator animation) {
  27. float animatedValue = (float) animation.getAnimatedValue();
  28. float percent = Math.abs(animatedValue / height);
  29. float scaleAlpha = (float) (1.0 - percent * 1.0);
  30. viewHolder.itemView.setAlpha(scaleAlpha);
  31. ((ViewGroup) viewHolder.itemView).getChildAt(0).setScaleX(scaleAlpha);
  32. ((ViewGroup) viewHolder.itemView).getChildAt(0).setScaleY(scaleAlpha);
  33. nextView.setTranslationY(animatedValue);
  34. }
  35. });
  36. valueAnimator.addListener(new AnimatorListenerAdapter() {
  37. @Override
  38. public void onAnimationEnd(Animator animation) {
  39. lastDy = 0;
  40. valueAnimator = null;
  41. }
  42. });
  43. valueAnimator.start();
  44. }
  45. }
  46. } else {
  47. //该种情况就是没有换手指的情况
  48. float percent = Math.abs(dY / height);
  49. float scaleAlpha = (float) (1.0 - percent * 1.0);
  50. viewHolder.itemView.setAlpha(scaleAlpha);
  51. ((ViewGroup) viewHolder.itemView).getChildAt(0).setScaleX(scaleAlpha);
  52. ((ViewGroup) viewHolder.itemView).getChildAt(0).setScaleY(scaleAlpha);
  53. //往下拉
  54. if (dY > 0) {
  55. //获取屏幕上方的item
  56. nextView = recyclerView.getChildAt(recyclerView.getChildCount() - 1);
  57. View childAt = ((ViewGroup) nextView).getChildAt(0);
  58. if (childAt instanceof SlideRecyclerView) {
  59. SlideRecyclerView sl = (SlideRecyclerView) childAt;
  60. if (sl.getScrollY() == 0) {
  61. sl.pullNextScroll();
  62. }
  63. }
  64. nextView.setTranslationY(dY);
  65. pullDown = true;
  66. lastDy = dY;
  67. } else if (dY < 0) {
  68. //往上拉的时候,获取屏幕下面的item
  69. nextView = recyclerView.getChildAt(1);
  70. pullDown = false;
  71. nextView.setTranslationY(dY);
  72. lastDy = dY;
  73. }
  74. }
  75. }

这里看似代码这么长,其实是在下拉的时候,获取到的nextView对应的是屏幕上方的item,也就是RecyclerView的最后一个item,因为最后一个item是放在了屏幕的上面;在上拉的时候,获取到的nextView对应的是屏幕下方的item,也就是RecyclerView的第二个item。

上面的代码只是处理我们的滑动,至于说松手的处理还没说呢。这里也正好说下onSwipe什么时候触发。这里需要介绍一个方法:

  1. /**
  2. * Returns the fraction that the user should move the View to be considered as swiped.
  3. * The fraction is calculated with respect to RecyclerView's bounds.
  4. * <p>
  5. * Default value is .5f, which means, to swipe a View, user must move the View at least
  6. * half of RecyclerView's width or height, depending on the swipe direction.
  7. *
  8. * @param viewHolder The ViewHolder that is being dragged.
  9. * @return A float value that denotes the fraction of the View size. Default value
  10. * is .5f .
  11. */
  12. public float getSwipeThreshold(ViewHolder viewHolder) {
  13. return .5f;
  14. }

源码说是只要滑动位置超过了RecyclerView的width或height时就会触发onSwiped方法,我们这里不需要去动该值就可以了,默认就可以,这里也正好是RecyclerView高度一半的距离,在松手的时候就触发onSwipe方法

接下来看看onSwiped都做了些什么:

  1. @Override
  2. public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
  3. Log.d(TAG, "onSwiped");
  4. lastDy = 0;
  5. refreshData(viewHolder);
  6. if (onSwipedListener != null) {
  7. onSwipedListener.onSwiped(pullDown);
  8. }
  9. }

这里处理了数据跟接口的回调的监听,接下来看看refreshData方法做了些什么:

  1. /**
  2. * 处理swipe时候view的还原以及数据源的刷新
  3. *
  4. * @param viewHolder
  5. */
  6. private void refreshData(RecyclerView.ViewHolder viewHolder) {
  7. //将当前的item进行还原
  8. viewHolder.itemView.setAlpha(1);
  9. ((ViewGroup) viewHolder.itemView).getChildAt(0).setScaleX(1);
  10. ((ViewGroup) viewHolder.itemView).getChildAt(0).setScaleY(1);
  11. if (pullDown) {
  12. //将上面移动的进行还原
  13. nextView.setTranslationY(-height);
  14. //往下拉的时候,将集合整体往后挪一位
  15. Collections.rotate(mDatas, 1);
  16. } else {
  17. //将下面移动的进行还原
  18. nextView.setTranslationY(height);
  19. //往上拉的时候,将集合整体往前挪一位
  20. Collections.rotate(mDatas, -1);
  21. }
  22. //刷新item
  23. mAdapter.notifyDataSetChanged();
  24. }

关于外层的RecyclerView滑动处理就先说这么多,下面来介绍如何处理内层带有滑动结构的RecyclerView,两个都有滑动结构,何时才让内层的RecyclerView,何时让外层的RecyclerView滑动呢:

这个时候来看下里面的SlideRecyclerView内部滑动的处理:

  1. public SlideRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
  2. super(context, attrs, defStyle);
  3. getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
  4. @Override
  5. public void onGlobalLayout() {
  6. getViewTreeObserver().removeGlobalOnLayoutListener(this);
  7. initView();
  8. if (getIsCurrentItem()) {
  9. addOnScrollListener(new OnScrollListener() {
  10. @Override
  11. public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
  12. super.onScrollStateChanged(recyclerView, newState);
  13. }
  14. @Override
  15. public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
  16. super.onScrolled(recyclerView, dx, dy);
  17. scrollY += dy;
  18. Log.d(TAG, "scrollY:" + scrollY);
  19. if (scrollY == 0) {
  20. //如果父recyclerView已经在顶部并且还往上滑的时候,让chuShouCallBack没有swipe动作
  21. if (dy < 0) {
  22. chuShouCallBack.setDefaultSwipeDirs(0);
  23. }
  24. }
  25. if (isSlideToBottom()) {
  26. //如果父recyclerView已经在底部并且还往下拉的时候,让chuShouCallBack没有swipe动作
  27. if (dy > 0) {
  28. chuShouCallBack.setDefaultSwipeDirs(0);
  29. }
  30. }
  31. }
  32. });
  33. }
  34. }
  35. });
  36. }

监听SlideRecyclerView滑动位置来动态设置外层的RecyclerView是否有滑动处理。总结下来是两种情况:一种是SlideRecyclerView滑动到了顶部,此时如果往上滑的时候,需要禁掉外层的RecyclerView的滑动,直接调用chuShouCallBack.setDefaultSwipeDirs(0)方法就可禁掉外层的滑动。另一种是SlideRecyclerView滑动到了底部,此时如果往下滑的时候,也需要禁掉外层的RecyclerView滑动。

说到这的时候很多人好奇为什么监听SlideRecyclerView滑动处理没有打开外层的RecyclerView代码呢。这里打开外层的RecyclerView滑动需要放在ontouch里面处理。因为在SlideRecyclerView滑动监听里面是无法监听到如果滑动到顶部时继续往下滑和滑动到底部时继续往上滑的操作,因此这里就通过ontouch的坐标该变量来是否打开外层的RecyclerView滑动:

  1. @Override
  2. public boolean onInterceptTouchEvent(MotionEvent e) {
  3. if (getIsCurrentItem()) {
  4. switch (e.getAction()) {
  5. case MotionEvent.ACTION_DOWN:
  6. Log.d(TAG, "MotionEvent.ACTION_DOWN");
  7. startY = e.getY();
  8. chuShouCallBack.setDefaultSwipeDirs(0);
  9. break;
  10. case MotionEvent.ACTION_MOVE:
  11. Log.d(TAG, "MotionEvent.ACTION_MOVE");
  12. dataY = e.getY() - startY;
  13. //只有滑动到顶部的时候才会通过判断两点之间的距离来切换item
  14. if (scrollY == 0) {
  15. if (dataY > 0) {
  16. chuShouCallBack.setDefaultSwipeDirs(ItemTouchHelper.UP | ItemTouchHelper.DOWN);
  17. Log.d(TAG, "到了顶部往下拉的时候");
  18. }
  19. }
  20. if (isSlideToBottom()) {
  21. if (dataY < 0) {
  22. chuShouCallBack.setDefaultSwipeDirs(ItemTouchHelper.UP | ItemTouchHelper.DOWN);
  23. Log.d(TAG, "到了底部往上拉的时候");
  24. }
  25. }
  26. if (scrollY != 0 && !isSlideToBottom()) {
  27. chuShouCallBack.setDefaultSwipeDirs(0);
  28. Log.d(TAG, "在中间的位置");
  29. }
  30. break;
  31. case MotionEvent.ACTION_UP:
  32. break;
  33. }
  34. }
  35. return super.onInterceptTouchEvent(e);
  36. }

这里涉及到了三种情况:

(1)SlideRecyclerView滑动到顶部的时候,继续往下滑的时候,需要打开外层的RecyclerView滑动

(2)SlideRecyclerView滑动到底部的时候,继续往上滑的时候,需要打开外层的RecyclerView滑动

(3)SlideRecyclerView滑动到中间某一个位置的时候,不管往上滑还是往下滑需要禁掉外层的RecyclerView滑动

核心代码就这么多了,关于使用方面如果还有什么疑问,可以直接看demo,也可以直接跟我探讨,欢迎提出issue

总结:

  • 结构分析:

    整体外层是一个大的RecyclerView(这里定义成ScrollRecyclerView,为了对外提供自己的ChuShouCallBack),里面的item分两种情况,一种是带有滑动结构,一种是非滑动结构。滑动结构的话又定义了一个RecyclerView(这里定义成SlideRecyclerView,处理滑动的)。

  • 分析item的排列:

    这里就是ChuShouManager的职责了,它负责把最后一个item放在屏幕上方,第一个item放在屏幕中,从第二个item到倒数第二个item放在屏幕下方。

  • 处理touch的动作:

    ChuShouCallBack就是扮演该角色了,用来处理上拉和下拉改变item的透明度和平移量。最后在onSwipe时恢复item状态及改变数据源

  • 处理item本身带有滑动(SlideRecyclerView )和外层RecyclerView滑动冲突:

    这里就是分析何时去禁掉外层RecyclerView滑动,何时打开滑动。原则是当item滑动到顶部时,若再继续往上滑禁掉外层RecyclerView滑动,若再继续往下滑打开外层RecyclerView滑动;当item滑动到中间某一个位置时,此时不管再继续往上滑还是往下滑都是禁掉外层RecyclerView滑动;当item滑动到底部时,若再继续往上滑打开外层RecyclerView滑动,若再继续往下滑禁掉外层RecyclerView滑动。

后续添加:

滑动控件还会有ListViewScrollView

欢迎客官到本店光临:184793647(qq群)

gradle依赖:

  1. allprojects {
  2. repositories {
  3. ...
  4. maven { url 'https://jitpack.io' }
  5. }
  6. }
  7. dependencies {
  8. ...
  9. compile 'com.github.1002326270xc:ChuShouView-master:v1.3'
  10. ...
  11. }

项目文件目录截图:

项目结构图



一分钟搞定触手app主页酷炫滑动切换效果

代码地址如下:
http://www.demodashi.com/demo/12826.html

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

一分钟搞定触手app主页酷炫滑动切换效果的更多相关文章

  1. JS组件系列——又一款MVVM组件:Vue(一:30分钟搞定前端增删改查)

    前言:关于Vue框架,好几个月之前就听说过,了解一项新技术之后,总是处于观望状态,一直在犹豫要不要系统学习下.正好最近有点空,就去官网了解了下,看上去还不错的一个组件,就抽空研究了下.最近园子里vue ...

  2. 转载-30分钟搞定后台登录界面(103个后台PSD源文件、素材网站)

    原文:30分钟搞定后台登录界面(103个后台PSD源文件.素材网站)   目录 一.界面预览 二.PSD源文件预览 三.工具分享 四.资源说明 五.素材下载网站 六.下载 去年八月时要做一个OA系统为 ...

  3. OpenCV3.4.1快速集成到Android studio中,10分钟搞定

    OpenCV3.4.1快速集成到Android studio中,10分钟搞定     转载 https://blog.csdn.net/yu540135101/article/details/8259 ...

  4. 一分钟搞定AlloyTouch图片轮播

      一分钟搞定AlloyTouch图片轮播 轮播图也涉及到触摸和触摸反馈,同时,AlloyTouch可以把惯性运动打开或者关闭,并且设置min和max为运动区域,超出会自动回弹.除了一般的竖向滚动,A ...

  5. 五分钟搞定Go.js

    五分钟搞定Go.js  1.基于html5~因为Go.js是一个依赖于HTML5特性的JavaScript库,所以需要确保您的页面声明它是一个HTML5文档,当然需要加载库 <!DOCTYPE ...

  6. Spring Boot 返回 XML 数据,一分钟搞定!

    Spring Boot 返回 XML 数据,前提必须已经搭建了 Spring Boot 项目,所以这一块代码就不贴了,可以点击查看之前分享的 Spring Boot 返回 JSON 数据,一分钟搞定! ...

  7. zookeeper-架构设计与角色分工-《每日五分钟搞定大数据》

    本篇文章阅读时间5分钟左右 点击看<每日五分钟搞定大数据>完整思维导图   zookeeper作为一个分布式协调系统,很多组件都会依赖它,那么此时它的可用性就非常重要了,那么保证可用性的同 ...

  8. zookeeper核心-zab协议-《每日五分钟搞定大数据》

    上篇文章<paxos与一致性>说到zab是在paxos的基础上做了重要的改造,解决了一系列的问题,这一篇我们就来说下这个zab. zab协议的全称是ZooKeeper Atomic Bro ...

  9. windows+mysql集群搭建-三分钟搞定集群

    注:本文来源:  陈晓婵   <  windows+mysql集群搭建-三分钟搞定集群   > 一:mysql集群搭建教程-基础篇 计算机一级考试系统要用集群,目标是把集群搭建起来,保证一 ...

随机推荐

  1. centos 资源链接

    不时更新.. 安装.启动相关 自动安装的精简的ISO 教你制作属于自己的CentOS 6.4一键自动化安装ISO镜像光盘 initrd介绍 理解 vmlinuz, initrd 和 System.ma ...

  2. hdu 5159(概率)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5159 题解:假设在 x 张牌中选b张牌,那么有 x^b 种选法,如果在 (x-1) 张牌中选 b 张 ...

  3. poj 1981(单位圆覆盖最多点问题模板)

    Circle and Points Time Limit: 5000MS   Memory Limit: 30000K Total Submissions: 7327   Accepted: 2651 ...

  4. Nginx虚拟主机(Virtual Host)配置

    虚拟主机(Virtual Host)可以在一台服务器上绑定多个域名,架设多个不同的网站,一般在开发机或者要部署多个小网站的服务器上需要配置虚拟主机.nginx的虚拟主机配置其实也挺简单,为了使得配置文 ...

  5. AC日记——Paint Pearls hdu 5009

    Paint Pearls 思路: 离散化+dp+剪枝: dp是个n方的做法: 重要就在剪枝: 如果一个长度为n的区间,有大于根号n种颜色,还不如一个一个涂: 来,上代码: #include <c ...

  6. Guava源码学习(五)EventBus

    基于版本:Guava 22.0 Wiki:EventBus 0. EventBus简介 提供了发布-订阅模型,可以方便的在EventBus上注册订阅者,发布者可以简单的将事件传递给EventBus,E ...

  7. 树链剖分【p1505】[国家集训队]旅游

    Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间 ...

  8. MFC学习1

    引用:http://v.youku.com/v_show/id_XMjM3MTI1ODky.html MSG 窗口——一般是程序在屏幕上的不同的矩形区域。 窗口句柄——标识窗口类型的类(资源的标识) ...

  9. Strobogrammatic Number II -- LeetCode

    A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside ...

  10. 洛谷 P2183 [国家集训队]礼物

    题目描述 一年一度的圣诞节快要来到了.每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物.不同的人物在小E心目中的重要性不同,在小E心中分量越重的人,收到的礼物会越多.小E从商店中购买了n件礼物 ...