Android高手进阶篇4-实现侧滑菜单框架,一分钟集成到项目中
先来看下面的这张效果图:
上面这张效果图是百度影音的,现在在Android上很流行,最初是由facebook自己实现的,而后各大应用有跟风之势,那么这种侧滑效果是如何实现的呢?
网上现在这种侧滑菜单的例子很对,也有开源的框架sliderMenu,而且可以定义很多样式,但大部分例子,都只是实现了这种类似效果,没有实现一种可移植的框架,仅仅是单页面效果而已,而且集成起来复杂,鉴于此,我自己实现了一套侧滑菜单的框架:
1、最常用的支持左右策划
2、多个页面切换也好不费力,页面切换的逻辑已经实现好了,集成进来,只需要关注自己项目的业务逻辑
3、支持多个页面集成
4、支持退出业务逻辑
先上我自己实现的效果图:
下面 说一下实现原理:
布局文件采用FrameLayout, 在一个FrameLayout下有二个子布局,一个是菜单,另一个是LeftSliderLayout,而LeftSliderLayout下面可以放二个子布局:第一个是阴影布局(左边阴影),第二个是要拖动的内容。,当向右拖动LeftSliderLayout时,就显示露出菜单布局。而向左拖动LeftSliderLayout时,就覆盖菜单布局。
1.FrameLayout的布局文件local_media_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" > <include android:id="@+id/main_layout_below" layout="@layout/main_layout_below" /> <com.zhaoxufeng.leftsliderlayout.lib.LeftSliderLayout
android:id="@+id/main_slider_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent" > <!-- Shadow Child -->
<ImageView
android:layout_width="15px"
android:layout_height="fill_parent"
android:contentDescription="@null"
android:scaleType="fitXY"
android:src="@drawable/main_side_shadow" /> <!-- Main Child -->
<include android:id="@+id/main_slider_main" layout="@layout/local_media" /> </com.zhaoxufeng.leftsliderlayout.lib.LeftSliderLayout> </FrameLayout>
上面 xml 中main_layout_below是对应的左边菜单Menu布局文件(这个布局文件是固定的),local_media是你要的拖动布局
2、LeftSliderLayout.java代码
package com.zhaoxufeng.leftsliderlayout.lib; import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller; public class LeftSliderLayout extends ViewGroup { private static final String TAG = "LeftSliderLayout" ; private Scroller mScroller;
private VelocityTracker mVelocityTracker; /**
* Constant value for touch state
* TOUCH_STATE_REST : no touch
* TOUCH_STATE_SCROLLING : scrolling
*/
private static final int TOUCH_STATE_REST = 0;
private static final int TOUCH_STATE_SCROLLING = 1;
private int mTouchState = TOUCH_STATE_REST; /**
* Distance in pixels a touch can wander before we think the user is scrolling
*/
private int mTouchSlop; /**
* Values for saving axis of the last touch event.
*/
private float mLastMotionX;
private float mLastMotionY; /**
* Values for VelocityTracker to compute current velocity.
* VELOCITY_UNITS in dp
* mVelocityUnits in px
*/
private static final int VELOCITY_UNITS = 1000;
private int mVelocityUnits; /**
* The minimum velocity for determining the direction.
* MINOR_VELOCITY in dp
* mMinorVelocity in px
*/
private static final float MINOR_VELOCITY = 150.0f;
private int mMinorVelocity; /**
* The width of Sliding distance from left.
* And it should be the same with the width of the View below SliderLayout in a FrameLayout.
* DOCK_WIDTH in dp
* mDockWidth in px
*/
private static final float SLIDING_WIDTH = 270.0f;
private int mSlidingWidth; /**
* The default values of shadow.
* VELOCITY_UNITS in dp
* mVelocityUnits in px
*/
private static final float DEF_SHADOW_WIDTH = 10.0f;
private int mDefShadowWidth; /**
* Value for checking a touch event is completed.
*/
private boolean mIsTouchEventDone = false; /**
* Value for checking slider is open.
*/
private boolean mIsOpen = false; /**
* Value for saving the last offset of scroller ’ x-axis.
*/
private int mSaveScrollX = 0; /**
* Value for checking slider is allowed to slide.
*/
private boolean mEnableSlide = true; private View mMainChild = null;
private OnLeftSliderLayoutStateListener mListener = null; /**
* Instantiates a new LeftSliderLayout.
*
* @param context the associated Context
* @param attrs AttributeSet
*/
public LeftSliderLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} /**
* Instantiates a new LeftSliderLayout.
*
* @param context the associated Context
* @param attrs AttributeSet
* @param defStyle Style
*/
public LeftSliderLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mScroller = new Scroller(context);
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); /**
* Convert values in dp to values in px;
*/
final float fDensity = getResources().getDisplayMetrics().density;
mVelocityUnits = (int) (VELOCITY_UNITS * fDensity + 0.5f);
mMinorVelocity = (int) (MINOR_VELOCITY * fDensity + 0.5f);
mSlidingWidth = (int) (SLIDING_WIDTH * fDensity + 0.5f);
mDefShadowWidth = (int) (DEF_SHADOW_WIDTH * fDensity + 0.5f);
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); // check Measure Mode is Exactly.
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException("LeftSliderLayout only canmCurScreen run at EXACTLY mode!");
}
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException("LeftSliderLayout only can run at EXACTLY mode!");
} // measure child views
int nCount = getChildCount();
for (int i = 2; i < nCount; i++) {
removeViewAt(i);
}
nCount = getChildCount();
if (nCount > 0) {
if (nCount > 1) {
mMainChild = getChildAt(1);
getChildAt(0).measure(widthMeasureSpec, heightMeasureSpec);
} else {
mMainChild = getChildAt(0);
}
mMainChild.measure(widthMeasureSpec, heightMeasureSpec);
} // Set the scrolled position
scrollTo(mSaveScrollX, 0);
} @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int nCount = getChildCount();
if (nCount <= 0) {
return;
} // Set the size and position of Main Child
if (mMainChild != null) {
mMainChild.layout(
l,
t,
l + mMainChild.getMeasuredWidth(),
t + mMainChild.getMeasuredHeight());
} // Set the size and position of Shadow Child
if (nCount > 1) {
int nLeftChildWidth = 0;
View leftChild = getChildAt(0);
ViewGroup.LayoutParams layoutParams = leftChild.getLayoutParams();
if (layoutParams.width == ViewGroup.LayoutParams.FILL_PARENT
|| layoutParams.width == ViewGroup.LayoutParams.MATCH_PARENT) {
nLeftChildWidth = mDefShadowWidth;
} else {
nLeftChildWidth = layoutParams.width;
}
leftChild.layout(
l - nLeftChildWidth,
t,
l,
t + leftChild.getMeasuredHeight());
}
} @Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
Log.d(TAG,"computeScroll exeuted:" + "x:" + mScroller.getCurrX() + "Y:" + mScroller.getCurrY()) ;
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
} @Override
public boolean onTouchEvent(MotionEvent event) { int nCurScrollX = getScrollX(); // check touch point is in the rectangle of Main Child
if (mMainChild != null
&& mTouchState != TOUCH_STATE_SCROLLING
&& mIsTouchEventDone) {
Rect rect = new Rect();
mMainChild.getHitRect(rect);
if (!rect.contains((int)event.getX() + nCurScrollX, (int)event.getY())) {
return false;
}
} if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
} mVelocityTracker.addMovement(event); final int action = event.getAction();
final float x = event.getX(); switch (action) {
case MotionEvent.ACTION_DOWN: {
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
} mIsTouchEventDone = false;
mLastMotionX = x;
break;
} case MotionEvent.ACTION_MOVE: {
// check slider is allowed to slide.
if (!mEnableSlide) {
break;
} // compute the x-axis offset from last point to current point
int deltaX = (int) (mLastMotionX - x);
if (nCurScrollX + deltaX < getMinScrollX()) {
deltaX = getMinScrollX() - nCurScrollX;
mLastMotionX = mLastMotionX - deltaX;
} else if (nCurScrollX + deltaX > getMaxScrollX()) {
deltaX = getMaxScrollX() - nCurScrollX;
mLastMotionX = mLastMotionX - deltaX;
} else {
mLastMotionX = x;
} // Move view to the current point
if (deltaX != 0) {
scrollBy(deltaX, 0);
} // Save the scrolled position
mSaveScrollX = getScrollX();
break;
} case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: { // check slider is allowed to slide.
if (!mEnableSlide) {
break;
} final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(mVelocityUnits); // Set open or close state, when get ACTION_UP or ACTION_CANCEL event.
if (nCurScrollX < 0) {
int velocityX = (int) velocityTracker.getXVelocity();
if (velocityX > mMinorVelocity) {
scrollByWithAnim(getMinScrollX() - nCurScrollX);
setState(true);
}
else if (velocityX < -mMinorVelocity) {
scrollByWithAnim(-nCurScrollX);
setState(false);
} else {
if (nCurScrollX >= getMinScrollX() / 2) {
scrollByWithAnim(- nCurScrollX);
setState(false);
} else {
scrollByWithAnim(getMinScrollX() - nCurScrollX);
setState(true);
}
}
} else {
if (nCurScrollX > 0) {
scrollByWithAnim(-nCurScrollX);
}
setState(false);
} if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
} mTouchState = TOUCH_STATE_REST;
mIsTouchEventDone = true;
break;
} }
return true;
} @Override
public boolean onInterceptTouchEvent(MotionEvent ev) { final int action = ev.getAction(); if (mListener != null && !mListener.OnLeftSliderLayoutInterceptTouch(ev)) {
return false;
} if ((action == MotionEvent.ACTION_MOVE)
&& (mTouchState != TOUCH_STATE_REST)) {
return true;
} final float x = ev.getX();
final float y = ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
mLastMotionX = x;
mLastMotionY = y;
mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;
break; case MotionEvent.ACTION_MOVE:
final int xDiff = (int) Math.abs(mLastMotionX - x);
if (xDiff > mTouchSlop) {
if (Math.abs(mLastMotionY - y) / Math.abs(mLastMotionX - x) < 1)
mTouchState = TOUCH_STATE_SCROLLING;
}
break; case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mTouchState = TOUCH_STATE_REST;
break;
}
return mTouchState != TOUCH_STATE_REST;
} /**
* With the horizontal scroll of the animation
*
* @param nDx x-axis offset
*/
void scrollByWithAnim(int nDx) {
if (nDx == 0) {
return;
} Log.d(TAG,"scrollByWithAnim:" + "x:" + (getScrollX() + "Y:" + Math.abs(nDx))) ;
mScroller.startScroll(getScrollX(), 0, nDx, 0,
Math.abs(nDx)); invalidate();
} /**
* Get distance of the maximum horizontal scroll
*
* @return distance in px
*/
private int getMaxScrollX() {
return 0;
} /**
* Get distance of the minimum horizontal scroll
* @return distance in px
*/
private int getMinScrollX() {
return -mSlidingWidth;
} /**
* Open LeftSlideLayout
*/
public void open() {
Log.d(TAG,"scroll by width:" + (getMinScrollX() - getScrollX())) ;
if (mEnableSlide) {
Log.d(TAG,"scroll by width:" + (getMinScrollX() - getScrollX())) ;
scrollByWithAnim(getMinScrollX() - getScrollX());
setState(true);
}
} /**
* Close LeftSlideLayout
*/
public void close() {
if (mEnableSlide) {
scrollByWithAnim((-1) * getScrollX());
setState(false);
}
} /**
* Determine whether LeftSlideLayout is open
*
* @return true-open,false-close
*/
public boolean isOpen() {
return mIsOpen;
} /**
* Set state of LeftSliderLayout
*
* @param bIsOpen the new state
*/
private void setState(boolean bIsOpen) {
boolean bStateChanged = false;
if (mIsOpen && !bIsOpen) {
bStateChanged = true;
} else if (!mIsOpen && bIsOpen) {
bStateChanged = true;
} mIsOpen = bIsOpen; if (bIsOpen) {
mSaveScrollX = getMaxScrollX();
} else {
mSaveScrollX = 0;
} if (bStateChanged && mListener != null) {
mListener.OnLeftSliderLayoutStateChanged(bIsOpen);
}
} /**
* enable slide action of LeftSliderLayout
*
* @param bEnable
*/
public void enableSlide(boolean bEnable) {
mEnableSlide = bEnable;
} /**
* Set listener to LeftSliderLayout
*/
public void setOnLeftSliderLayoutListener(OnLeftSliderLayoutStateListener listener) {
mListener = listener;
} /**
* LeftSliderLayout Listener
*
*/
public interface OnLeftSliderLayoutStateListener { /**
* Called when LeftSliderLayout’s state has been changed.
*
* @param bIsOpen the new state
*/
public void OnLeftSliderLayoutStateChanged(boolean bIsOpen); /**
* Called when LeftSliderLayout has got onInterceptTouchEvent.
*
* @param ev Touch Event
* @return true - LeftSliderLayout need to manage the InterceptTouchEvent.
* false - LeftSliderLayout don't need to manage the InterceptTouchEvent.
*/
public boolean OnLeftSliderLayoutInterceptTouch(MotionEvent ev);
}
}
LeftSliderLayout有一个Listener。它有二个函数,一个是LeftSliderLayout的打开与关闭的状态改变;另一个是InterceptTouchEvent的回调,主要解决的是在拖动内容中有要处理左右滑动的控件与LeftSliderLayout的左右滑动的事件有冲突,当它返回true时,LeftSliderLayout会处理左右滑动,当它返回false时,就不处理左右滑动的事件。
为了实现侧滑菜单框架,故实现了一个BaseActivity,其他Activity只需要继承这个Activity就行,
3、BaseActivity.java代码
package com.zhaoxufeng.leftsliderlayout.example; import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.*;
import com.zhaoxufeng.leftsliderlayout.R;
import com.zhaoxufeng.leftsliderlayout.lib.LeftSliderLayout; import java.util.ArrayList;
import java.util.List; /**
* 基类Activity,SliderMenu的基础统一框架
* User: zhiwen.nan
* Date: 13-10-7
* Time: 下午8:31
*
*/
public class BaseActivity extends Activity implements LeftSliderLayout.OnLeftSliderLayoutStateListener, View.OnClickListener { private LeftSliderLayout leftSliderLayout;
private ImageView mOpenButton;
private TextView mTitleText;
private ListView mListView;
private List<ListItem> mDataList;
private long waitTime = 2000;
private long touchTime = 0;
private static final String TAG = "BaseActivity" ; public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
} @Override
protected void onResume() {
super.onResume();
bindView();
initialDataList();
ListViewAdapter listViewAdapter = new ListViewAdapter(BaseActivity.this,mDataList) ;
mListView.setAdapter(listViewAdapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
finish();
switch (i) {
case 0:
mTitleText.setText(getText(R.string.categ_local_video_list));
Intent intent = new Intent(BaseActivity.this,LocalMediaActivity.class) ;
startActivity(intent);
break;
case 1:
mTitleText.setText(getText(R.string.cate_leida));
Intent radIntent = new Intent(BaseActivity.this,RadoActivity.class) ;
startActivity(radIntent);
break;
case 2:
mTitleText.setText(getText(R.string.hot_viedo));
Intent hotIntent = new Intent(BaseActivity.this,HotMediaListActivity.class) ;
startActivity(hotIntent);
break;
case 3:
mTitleText.setText(getText(R.string.cate_favrouite_list));
Intent collectIntent = new Intent(BaseActivity.this,CollectListActivity.class) ;
startActivity(collectIntent);
break;
default:
leftSliderLayout.close();
break; }
}
});
} @Override
public void onClick(View view) { } @Override
public void OnLeftSliderLayoutStateChanged(boolean bIsOpen) { if (bIsOpen) {
// Toast.makeText(this, "LeftSliderLayout is open!", Toast.LENGTH_SHORT).show();
Log.d(TAG," leftsilder is open") ;
} else {
// Toast.makeText(this, "LeftSliderLayout is close!", Toast.LENGTH_SHORT).show();
Log.d(TAG," leftsilder is close") ;
} } @Override
public boolean OnLeftSliderLayoutInterceptTouch(MotionEvent ev) { return false;
} private void initialDataList(){
mDataList = new ArrayList<ListItem>() ;
for (int i = 0; i<= 3; i ++) {
ListItem listItem = new ListItem();
listItem.setImageType(i);
mDataList.add(listItem); }
} private void bindView(){
leftSliderLayout = (LeftSliderLayout) findViewById(R.id.main_slider_layout);
leftSliderLayout.setOnLeftSliderLayoutListener(this);
mOpenButton = (ImageView)findViewById(R.id.openButton) ;
mTitleText = (TextView)findViewById(R.id.titleText) ;
mListView = (ListView)findViewById(R.id.listTab) ; mOpenButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(leftSliderLayout.isOpen()) {
leftSliderLayout.close();
} else {
leftSliderLayout.open();
} }
}); } public void openLeftSlider(boolean isToOpen){
if(isToOpen) {
leftSliderLayout.open();
}else {
leftSliderLayout.close();
} } public void enableSlider(boolean isEnable) {
if(isEnable) {
leftSliderLayout.enableSlide(true);
} else {
leftSliderLayout.enableSlide(false);
}
} @Override
public void onBackPressed() {
if(!leftSliderLayout.isOpen()) {
leftSliderLayout.open();
} else {
long currentTime = System.currentTimeMillis();
if((currentTime-touchTime)>=waitTime) {
Toast.makeText(this, "再按一次退出", Toast.LENGTH_SHORT).show();
touchTime = currentTime;
}else {
finish();
//todo
//退出业务逻辑 ,根据项目需求来写
}
} }
}
关于左侧菜单的业务逻辑都在BaseActivity里处理,另外返回的逻辑也在里面处理,顶部统一的导航栏打开菜单栏业务逻辑,还有左侧菜单跳转的业务逻辑
4、LocalMediaActivity.java
package com.zhaoxufeng.leftsliderlayout.example; import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.Contacts;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.*;
import com.zhaoxufeng.leftsliderlayout.R;
import com.zhaoxufeng.leftsliderlayout.lib.LeftSliderLayout;
import com.zhaoxufeng.leftsliderlayout.lib.LeftSliderLayout.OnLeftSliderLayoutStateListener; import java.util.ArrayList;
import java.util.List; /**
* @author zhiwen.nan
* @since 1.0
* 本地视频界面
*/
public class LocalMediaActivity extends BaseActivity { private ListView mListView;
private TextView mTitleText; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.local_media_fragment); mListView = (ListView)findViewById(R.id.localVideoList) ; mTitleText = (TextView)findViewById(R.id.titleText) ;
mTitleText.setText("本地视频"); Cursor cursor = getContentResolver().query(Contacts.People.CONTENT_URI, null, null, null, null);
startManagingCursor(cursor);
ListAdapter listAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_1,
cursor,new String[]{Contacts.People.NAME},new int[]{android.R.id.text1});
mListView.setAdapter(listAdapter); } @Override
public boolean OnLeftSliderLayoutInterceptTouch(MotionEvent ev) { return true;
} }
LocalMediaActivity是自己定义的Activty和业务逻辑界面,只需继承BaseActivity即可,其他Activity类似。
以上就是核心代码,源代码下载:
http://download.csdn.net/detail/nanzhiwen666/6394347
Android高手进阶篇4-实现侧滑菜单框架,一分钟集成到项目中的更多相关文章
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
Android 高手进阶(21) 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明地址:http://blog.csdn.net/xiaanming/article/detail ...
- Android高手进阶教程(二十八)之---Android ViewPager控件的使用(基于ViewPager的横向相册)!!!
分类: Android高手进阶 Android基础教程 2012-09-14 18:10 29759人阅读 评论(35) 收藏 举报 android相册layoutobjectclassloade ...
- Android高手进阶:Adapter深入理解与优化
一般是针对包含多个元素的View,如ListView,GridView,ExpandableListview,的时候我们是给其设置一个Adapter.Adapter是与View之间提供数据的桥梁,也是 ...
- Android高手进阶——Adapter深入理解与优化
Android高手进阶--Adapter深入理解与优化 通常是针对包括多个元素的View,如ListView,GridView.ExpandableListview,的时候我们是给其设置一个Adapt ...
- Android 高手进阶,自己定义圆形进度条
背景介绍 在Android 开发中,我们常常遇到各种各样绚丽的控件,所以,依靠我们Android本身所带的控件是远远不够的,许多时候须要我们自定义控件,在开发的过程中.我们公司遇到了一种须要自己写的一 ...
- 淘宝(阿里百川)手机客户端开发日记第三篇 SlidingPaneLayout实现侧滑菜单
需要的三个布局文件: activity_main.xml :主窗体布局 left.xml : 左侧栏目分类布局 right.xml : 右侧内容详情 需要的组件: android.support.v4 ...
- Android高手进阶教程(五)之----Android 中LayoutInflater的使用!
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://weizhulin.blog.51cto.com/1556324/311450 大 ...
- Android高手进阶教程(七)之----Android 中Preferences的使用!
http://blog.csdn.net/Android_Tutor/article/details/5531849 大家好,我们这一节讲的是Android Preferences 的学习,Prefe ...
- Android高手进阶教程(十七)之---Android中Intent传递对象的两种方法(Serializable,Parcelable)!
[转][原文] 大家好,好久不见,今天要给大家讲一下Android中Intent中如何传递对象,就我目前所知道的有两种方法,一种是Bundle.putSerializable(Key,Object); ...
随机推荐
- appcompat_v7怎么不创建
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 我们建项目时直接把最小SDK选在Android4.0以上不就不需要这个支持库
- js使用s:property标签接收json格式数据
js使用s:property接收json数据时,会出现字符被转译的错误. 错误如下: 引号会被转译成'"'字符,导致解析不了. 错误原因: html的s:property接收不会出错,而js ...
- BZOJ3052 [wc2013] 糖果公园 【树上莫队】
树上莫队和普通的序列莫队很像,我们把树进行dfs,然后存一个长度为2n的括号序列,就是一个点进去当作左括号,出来当作右括号,然后如果访问从u到v路径,我们可以转化成括号序列的区间,记录x进去的时候编号 ...
- lightoj 1296 - Again Stone Game 博弈论
思路:由于数据很大,先通过打表找规律可以知道, 当n为偶数的时候其SG值为n/2; 当n为奇数的时候一直除2,直到为偶数m,则SG值为m/2; 代码如下: #include<stdio.h> ...
- 矩阵乘法快速幂 cojs 1717. 数学序列
矩阵乘法模板: #define N 801 #include<iostream> using namespace std; #include<cstdio> int a[N][ ...
- 实用在线小工具 -- Google URL Shortener
实用在线小工具 -- Google URL Shortener 当你想分享一些你觉得有趣的东西,但是那个链接太长,以至于贴上去一大片.比如在微博上分享一张图片,然后贴上去图片的链接,url ...
- windows server 2008 r2, 每隔一段时间自动关机
前段时间在做Exchange 2010测试的时候,由于windows server 2008 r2试用过期,开机后二个小时就会自动关机,可是我又不想重装系统,加为那样我可能需要重装好多东西,包括 ...
- Web前端面试题小集
一.一个页面上两个div左右铺满整个浏览器,要保证左边的div一直为100px,右边的div跟随浏览器大小变化(比如浏览器为500,右边div为400,浏览器为900,右边div为800),请写出大概 ...
- DELPHI PROTOBUF免费的开源支持库fundamentals5
DELPHI PROTOBUF免费的开源支持库fundamentals5 1.源码URL: https://github.com/fundamentalslib/fundamentals5 2.编译P ...
- Ext Connection
<html> <head> <meta http-equiv="Content-Type" content="text/html; char ...