Android群英传笔记——第五章:Android Scroll分析
Android群英传笔记——第五章:Android Scroll分析
滑动事件算是Android比较常用的效果了,而且滑动事件他本身也是有许多的知识点,今天,我们就一起来耍耍Scroll吧
一.滑动效果是如何产生的
滑动一个View的本质其实就是移动一个View,改变其当钱所在的位置,他的原理和动画效果十分的相似,就是通过不断的改变View的坐标来实现这一效果,动态且不断的改变View的坐标,从而实现View跟随用户触摸滑动而滑动
但是在讲解滑动效果之前,需要先了解一下Android中窗口坐标体系和屏幕的触控事件——MotionEvent
1.Android坐标系
在物理学上,要描述一个物体的运动,就必须选定一个参考系,所谓滑动,正是相对于参考系的运动,在Android,系统将屏幕最左上角的顶点作为Android坐标系的原点,从这个点向右是X轴正方向,从这个点向下是Y轴正方向,如图
系统提供了getLocationOnScreen(intlocation[])来获取Android坐标中的位置,即该视图左上角Android的坐标,另外,在触摸事件中使用getRawX(),getRawY()方法来获取坐标同样是Android坐标系中的坐标。
2.视图坐标系
Android中除了上面所说的这种坐标系之外们还有一个视图坐标系,他描述了子视图在父视图的位置关系,这两个坐标系并不复杂也不矛盾,他们的作用是相辅相成的,与Android坐标系类似,视图坐标系同样的以原点向右为X正方向,以原点向下为Y方法,只不过在视图坐标系中,原点不再是Android坐标系中的屏幕左上角,而是以父视图左上角为坐标原点,看图
在触控事件中通过getX,getY来获取的坐标就是视图坐标中的坐标
3.触控事件——MotionEvent
触控事件MotionEvent在用户的交互中,占着举足轻重的位置,学好触控事件是掌握后续内容的基础,首先,我们来看看MotionEvent中封装的一些常量,他定义了触摸事件的不同类型。
//单点触摸按下的动作
public static final int ACTION_DOWN = 0;
//单点触摸离开的动作
public static final int ACTION_UP = 1;
//单点触摸移动的动作
public static final int ACTION_MOVE = 2;
//单点触摸取消
public static final int ACTION_CANCEL = 3;
//单点触摸超出边界
public static final int ACTION_OUTSIDE = 4;
//多点触摸按下的动作
public static final int ACTION_POINTER_DOWN = 5;
//多点触摸离开的动作
public static final int ACTION_POINTER_UP = 6;
通常情况下,我们会在onTouchEvent(MotionEvent event)方法中通过event.getAction()来获取触摸事件的类型,并使用switch来判断,这个代码模块是固定的
@Override
public boolean onTouchEvent(MotionEvent event) {
//获取当前输入点的X,Y坐标(视图坐标)
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//处理输入的按下动作
break;
case MotionEvent.ACTION_MOVE:
//处理输入的移动动作
break;
case MotionEvent.ACTION_UP:
//处理输入的离开动作
break;
}
return true;
}
在不涉及多点触控的前提下,通常可以使用以下代码来完成触摸事件的监听,不过这里只是一个代码模块,后面我们会讲具体的逻辑的
在Android中,系统提供了非常多的方法来获取坐标值,相对距离等,方法丰富固然好,但也给初学者带来了很多的困扰,不知道在什么情况下使用下图总结人一下一些常用的API
这些方法可以分成两个类别
- View提供的获取坐标方法
getTop():获取到的是View自身的顶部到其父布局顶部的距离
getLeft():获取到的是View自身的左边到其父布局左边的距离
getRight():获取到的是View自身的右边到其父布局右边的距离
getBottom():获取到的是View自身的底部到其父布局底部的距离
- MotionEvent提供的方法
getX():获取点击事件距离控件左边的距离,即视图坐标
getY():获取点击事件距离控件顶部的距离,即视图坐标
getRawX:获取点击事件整个屏幕左边的距离,即绝对坐标
getRawY:获取点击事件整个屏幕顶部的距离,即绝对坐标
相信现在大家对滑动都有一点点的认知了吧,我们再继续往下看
二.实现滑动的七种方法
当了解了Android坐标系和触控事件之后,我们再来看一看如何使用系统提供的API来实现动态的修改一个View的坐标,即滑动效果,而不管采用哪种方式,其实现的思路基本上是一样的,当触摸View的时候,系统几下View的坐标,从而获得到相对于之前坐标的偏移量,并通过偏移量来修改View的坐标,这样不断的重复就实现了滑动的过程。
下面我们通过实例来看看Android中如何实现滑动的效果没定义一个View,简单的实现一个布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.lgl.scrollviewdemo.DragView
android:layout_width="100dp"
android:layout_height="100dp" />
</RelativeLayout>
默认的显示样子
1.layout方法
我们都知道,在View的绘制上,会调用onLayout()方法来设置显示的位置,同样可以修改View的left,top,right,bottom四个属性来控制View的坐标,与前面提供的模板代码一样,每次调用onTouchEvent()的时候,我们来获取点的坐标,这里的逻辑很清楚,真的,我们来看看
//触摸事件
@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
int lastX = 0;
int lastY = 0;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//记录触摸点的坐标
lastX = rawX;
lastY = rawY;
break;
case MotionEvent.ACTION_MOVE:
//计算偏移量
int officeX = rawX - lastX;
int officeY = rawY - lastY;
//在当前的left,top,right,bottom基础上加上偏移量
layout(getLeft()+officeX,getTop()+officeY,getRight()+officeX,getBottom()+officeY);
//重新设置初始值
lastX = rawX;
lastY = rawY;
break;
case MotionEvent.ACTION_UP:
//处理输入的离开动作
break;
}
return true;
}
这里我们就可以移动这个View了
2.offsetLeftAndRight()与offsetTopAndBottom()
这个方法相当于系统提供的一个对左右,上下移动的封装,当计算出偏移量的时候,只需要使用如下的代码就可以完成View的重新布局,效果和使用Layout()方法是一样的
//同时对左右偏移
offsetLeftAndRight(officeX);
//同时对上下偏移
offsetTopAndBottom(officeY);
3.LayoutParams
LayoutParams保留了一个View的布局参数,因此可以在程序中,通过改变LayoutParams来动态改变一个布局的位置参数,从而改变View位置的效果,我们可以很方便的在程序中使用getLayoutParams()来获取一个View的LayoutParams,当然,在计算偏移量的方法和Layout方法中计算offset是一样的,当获取到偏移量之后,可以通过setLayoutParams来改变LayoutParams,代码如下
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();
layoutParams.leftMargin = getLeft()+officeX;
layoutParams.topMargin = getTop()+officeY;
setLayoutParams(layoutParams);
不过这里需要注意的是,通过getLayoutParams()获取layoutParams时,需要根据View所在的跟布局的类型来设置不同的类型,,比如View放在LinearLayout里那就是 LinearLayout.LayoutParams,比如在RelativeLayout里就是 RelativeLayout.LayoutParams,不然系统是无法获取到layoutParams的.
在通过一个layoutParams来改变一个View的位置时,通常改变的是这个view的Margin属性,所以除了使用布局的layoutParams属性外,还需要 ViewGroup.MarginLayoutParams来实现这样的功能
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
layoutParams.leftMargin = getLeft()+officeX;
layoutParams.topMargin = getTop()+officeY;
setLayoutParams(layoutParams);
我们可以发现,用ViewGroup更好,都不用去管父布局是什么
4.scrollTo与scrollBy
在一个View当中,系统提供了scrollTo与scrollBy这两种方式来实现移动一个View的位置,这两种方法的区别也很好理解,to和by, scrollTo(x,y);表示移动到一个具体的 点,scrollBy(dx,dy);表示移动的增量
int officeX = rawX - lastX;
int officeY = rawY - lastY;
scrollBy(officeX,officeY);
但是,当我们拖动View的时候,你会发现View并没有移动,难道我们写错了?方法没有写错,View也的确移动了,但是他移动的并不是我们想要的东西,他只是移动了view的content,即让View的内容移动了,如果用ViewGroup使用to和by的话,那所有的子View都将移动,要是在View中使用的话,,那么移动的就是View的内容了,我们举个例子,比如TextView,content就是他的文本,ImageView,drawable就是对象
相信通过上面的分析,你也应该知道为什么不能再View里面使用这个两个方法来拖动这个view了,那么我们就该View所在的ViewGroup中使用scrollBy方法来移动这个view
((View)getParent()).scrollBy(officeX,officeY);
但是,当再次拖动View的时候,你会发现View虽然移动了,但却在乱动,并不是我们想要的跟随触摸点的移动而移动,这里需要先了解一下视图移动的一些知识,大家在理解这个问题的时候,不妨想象一下手机是一个中空的盖板,盖板下面是一个巨大的画布,也就是我们想要显示的视图,当把这个盖板盖在画布的某处时,透过中间空着的矩形,我们看见了手机屏幕上显示的视图,而画布上其他的视图,则被盖板盖住了无法看见,我们的视图和这个例子事项相似,我们没有看见视图,但并不代表它不存在,有可能只是在屏幕外面而已,当调用scrollBy的方法时,可以想象外面的盖板在移动,这么说比较抽象,我们来看一下具体的例子
上图,中间的矩形相当于屏幕,即可是区域,后面的content相当于画布,代表视图,大家可以看到,只有视图的中间部分目前是可视的,其他部分都不可见,可见区域中设置一个button,他的坐标是(20.10),下面我们使用scrollBy方法来进行移动后如图
我们会发现,虽然设置scrollBy(20.10),偏移量均为XY的正方向,但是屏幕的可视区域,Button却向反方向移动了,这就是参考系选择的不同,而产生的不同效果。
通过上面的分析,可以发现,我们将scrollBy的参数dx,dy设置成正数,那么content将向坐标轴负方向移动,反之,则正方向
int officeX = rawX - lastX;
int officeY = rawY - lastY;
scrollBy(-officeX,-officeY);
再去试验一下,大家可以发现,效果和前面的几种方法相同了,类似的,我们使用scrollTo也是可以实现的
5.Scroller
既然提到scrollTo与scrollBy,那就不得不提一下Scroller类了,Scroller和scrollTo与scrollBy十分的相似,有着千丝万缕的关系,那么他们有什么具体的区别尼?要解答这个问题,首先我们来看一个小栗子,假设要完成这样的一个效果:点击button,让一个viewgroup的子View移动100像素,问题看似很简单,只要使用scrollBy的方法就可以,的确,用这个方法确实可以,可是那都是一瞬间完成的事情,很突兀,而Scroller就可以实现平滑的效果,而不再是一瞬间的事情.
说道Scroller的原理,其实他与前面使用scrollTo与scrollBy的方法原理是一样的,下面我们通过一个小栗子来演示一下
- 初始化scroller
首先,通过他的构造方法来创建一个scroller对象
//初始化mScroller
mScroller = new Scroller(context);
- 重写computeScroll,实现模拟滑动
下面我们需要重写computeScroll这个方法,他是使用Scroller的核心,系统在绘制View的同时,会在onDraw()方法中调用这个方法,这个方法实际上就是使用了ScrollTo()方法再结合Scroller对象,帮助获取到当前的滚动值,我们可以通过不断的瞬息移动一个小的距离来实现整体上的平滑移动效果,通常情况下,computeScroll的代码可以利用标准的写法:
/**
* 模拟滑动
*/
@Override
public void computeScroll() {
super.computeScroll();
//判断Scroller是否执行完毕
if(mScroller.computeScrollOffset()){
((View)getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
}
//通过重绘来不断调用computeScroll
invalidate();
}
Scroller类提供了computeScrollOffset()来判断是否完成了整个页面的滑动,,同时也提供了getCurrX(),getCurrY()来获取当前滑动坐标,上面唯一要注意的就是invalidate()了,因为只能在computeScroll中获得模拟过程中的scrollX,scrollY,坐标,但computeScroll方法是不会自动调用的,只能通过invalidate——》OnDraw——》computeScroll来简介调用,所以需要这个invalidate,而当模拟过程结束的时候,computeScrollOffset返回的是false,从而结束循环
- startScroll开启模拟过程
最后,万事俱备只欠东风了,我们需要使用平滑移动事件,使用Scroller类的startScroll()方法来开启平滑过程,startScroll有两个重载的方法
- public void startScroll(int startX,int startY,int dx,int dy)
- public void startScroll(int startX,int startY,int dx,int dy)
可以看到他们的区别分别是具有指定的持续时长,而另一个每有,这个非常好理解,与在动画中的设置时间是一样的,而其他四个坐标,就是起始和偏移量,通过上述的步骤,就可以完成一个平移的效果了,下面我们回到实例,在构造分钟初始化Scroller对象,然后重写computeScroll方法,最后需要监听手指离开屏幕的事件,并在该事件之后调用startScroll()完成平移,所以我们在ACTION_UP中
case MotionEvent.ACTION_UP:
//处理输入的离开动作
View view = ((View)getParent());
mScroller.startScroll(view.getScrollX(),view.getScrollY(),view.getScrollX(),view.getScrollY());
invalidate();
break;
6.属性动画
在本书中第七章将会详细介绍,这里就不重复了
7.ViewDragHelper
这就是今天的好菜了,Google在其support库中为我们提供了一个DrawerLayout和SlidingPaneLayout两个布局来帮助开发者实现策划效果,这两个布局,大大的方便了我们自己创建自己的滑动布局,然而,这两个强大的布局背后,却隐藏着一个鲜为人知,却功能强大的类——ViewDragHelper,通过ViewDragHelper,基本可以实现各种不同的侧滑,拖放需求,因此这个方法也是各种滑动解决方案的终极绝招
ViewDragHelper虽然很强大,但是使用也是本章节最复杂 的,我们需要了解ViewDragHelper的基本使用方法的基础上,通过不断的练习去掌握它,我们这里就实现一个 QQ滑动侧边栏的布局,我么来看看具体怎么实现的
- 初始化ViewDragHelper
首先,自认是初始化ViewDragHelper,ViewDragHelper通常定义在一个ViewGroup中,通过其静态方法初始化
mViewDragHelper = ViewDragHelper.create(this,callback);
他的第一个参数是要监听的View,第二个参数是一个Callback回调,,这个回调是整个业务的核心,
- 拦截事件
接下来,要重写拦截事件,将事件传递给ViewDragHelper进行处理
//事件拦截
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mViewDragHelper.shouldInterceptTouchEvent(ev);
}
//触摸事件
@Override
public boolean onTouchEvent(MotionEvent event) {
//将触摸事件传递给ViewDragHelper
mViewDragHelper.processTouchEvent(event);
return true;
}
- 处理computeScroll()
没错,使用ViewDragHelper也是需要重写computeScroll的,因为ViewDragHelper内部也是通过Scroller来实现平移的,我们可以这样使用
@Override
public void computeScroll() {
if(mViewDragHelper.continueSettling(true)){
ViewCompat.postInvalidateOnAnimation(this);
}
}
- 处理回调Cakkback
我们可以直接的new出来
//侧滑回调
private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
//何时开始触摸
@Override
public boolean tryCaptureView(View child, int pointerId) {
//如果当前触摸的child是mMainView开始检测
return mMainView == child;
}
//处理水平滑动
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
return left;
}
//处理垂直滑动
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return 0;
}
//拖动结束后调用
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
//手指抬起后缓慢的移动到指定位置
if(mMainView.getLeft() <500){
//关闭菜单
mViewDragHelper.smoothSlideViewTo(mMainView,0,0);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
}else{
//打开菜单
mViewDragHelper.smoothSlideViewTo(mMainView,300,0);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
}
}
};
通过一步步的分析,现在要实现QQ的侧滑,是不是非常简单了尼,下面自定义一个viewGroup来完成整个编码的实例
//XML加载组建后回调
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mMenuView = getChildAt(0);
mMainView = getChildAt(1);
}
//组件大小改变时回调
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = mMenuView.getMeasuredWidth();
}
最后通过整个ViewDragHelper来实现侧滑的代码如下
package com.lgl.scrollviewdemo;
import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
/**
* QQ侧滑
* Created by lgl on 16/3/22.
*/
public class DragViewGroup extends FrameLayout{
//侧滑类
private ViewDragHelper mViewDragHelper;
private View mMenuView,mMainView;
private int mWidth;
public DragViewGroup(Context context) {
super(context);
initView();
}
public DragViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public DragViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
//初始化数据
private void initView() {
mViewDragHelper = ViewDragHelper.create(this,callback);
}
//XML加载组建后回调
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mMenuView = getChildAt(0);
mMainView = getChildAt(1);
}
//组件大小改变时回调
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = mMenuView.getMeasuredWidth();
}
//事件拦截
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mViewDragHelper.shouldInterceptTouchEvent(ev);
}
//触摸事件
@Override
public boolean onTouchEvent(MotionEvent event) {
//将触摸事件传递给ViewDragHelper
mViewDragHelper.processTouchEvent(event);
return true;
}
//侧滑回调
private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
//何时开始触摸
@Override
public boolean tryCaptureView(View child, int pointerId) {
//如果当前触摸的child是mMainView开始检测
return mMainView == child;
}
//处理水平滑动
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
return left;
}
//处理垂直滑动
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return 0;
}
//拖动结束后调用
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
//手指抬起后缓慢的移动到指定位置
if(mMainView.getLeft() <500){
//关闭菜单
mViewDragHelper.smoothSlideViewTo(mMainView,0,0);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
}else{
//打开菜单
mViewDragHelper.smoothSlideViewTo(mMainView,300,0);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
}
}
};
@Override
public void computeScroll() {
if(mViewDragHelper.continueSettling(true)){
ViewCompat.postInvalidateOnAnimation(this);
}
}
}
当然,这里只是非常简单的模拟了一下,在Cakkback中系统给我们提供了很多的方法来监听
- onViewCaptured
//用户触摸到view回调
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
}
- onViewDragStateChanged
//拖拽状态改变时,比如idle,dragging
@Override
public void onViewDragStateChanged(int state) {
super.onViewDragStateChanged(state);
}
- onViewPositionChanged
//位置发生改变,常用语滑动scale效果
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
}
使用DragViewGroup可以帮助我们非常好的处理滑动,但同时DragViewGroup也是比较复杂的,需要开发者对事件拦截,滑动处理比较认知,所以还是建议初学者循循渐进,好了,今天的笔记就记到这里了,前面的都太枯燥了,我们马上就可以学习到一些很好玩的东西了
笔记下载链接:http://pan.baidu.com/s/1c0U7k2W 密码:9v0g
Demo下载:http://download.csdn.net/detail/qq_26787115/9469887
Android群英传笔记——第五章:Android Scroll分析的更多相关文章
- Android群英传笔记——第七章:Android动画机制和使用技巧
Android群英传笔记--第七章:Android动画机制和使用技巧 想来,最 近忙的不可开交,都把看书给冷落了,还有好几本没有看完呢,速度得加快了 今天看了第七章,Android动画效果一直是人家中 ...
- Android群英传笔记——第六章:Android绘图机制与处理技巧
Android群英传笔记--第六章:Android绘图机制与处理技巧 一直在情调,时间都是可以自己调节的,不然世界上哪有这么多牛X的人 今天就开始读第六章了,算日子也刚好一个月了,一个月就读一半,这效 ...
- Android群英传笔记——第三章:Android控件架构与自定义控件讲解
Android群英传笔记--第三章:Android控件架构与自定义控件讲解 真的很久没有更新博客了,三四天了吧,搬家干嘛的,心累,事件又很紧,抽时间把第三章大致的看完了,当然,我还是有一点View的基 ...
- Android群英传笔记——第四章:ListView使用技巧
Android群英传笔记--第四章:ListView使用技巧 最近也是比较迷茫,但是有一点点还是要坚持的,就是学习了,最近离职了,今天也是继续温习第四章ListView,也拖了其实也挺久的了,list ...
- Android群英传笔记——第十章:Android性能优化
Android群英传笔记--第十章:Android性能优化 随着Android应用增多,功能越来越复杂,布局也越来越丰富了,而这些也成为了阻碍一个应用流畅运行,因此,对复杂的功能进行性能优化是创造高质 ...
- Android群英传笔记——第九章:Android系统信息和安全机制
Android群英传笔记--第九章:Android系统信息和安全机制 本书也正式的进入尾声了,在android的世界了,不同的软件,硬件信息就像一个国家的经济水平,军事水平,不同的配置参数,代表着一个 ...
- Android群英传笔记——第十二章:Android5.X 新特性详解,Material Design UI的新体验
Android群英传笔记--第十二章:Android5.X 新特性详解,Material Design UI的新体验 第十一章为什么不写,因为我很早之前就已经写过了,有需要的可以去看 Android高 ...
- Android群英传笔记——第二章:Android开发工具新接触
Android群英传笔记--第二章:Android开发工具新接触 其实这一章并没什么可讲的,前面的安装Android studio的我们可以直接跳过,如果有兴趣的,可以去看看Google主推-Andr ...
- Android群英传笔记——第一章:Android体系与系统架构
Android群英传笔记--第一章:Android体系与系统架构 图片都是摘抄自网络 今天确实挺忙的,不过把第一章的笔记做一下还是可以的,嘿嘿 1.1 Google的生态圈 还是得从Android的起 ...
随机推荐
- Python rich comparisons 自定义对象比较过程和返回值
Classes wishing to support the rich comparison mechanisms must add one or more of the following new ...
- UE4实现闪烁效果
官网文档链接:http://docs.unrealengine.com/latest/CHN/Engine/Rendering/Materials/ExpressionReference/Math/i ...
- Android获取当前网络状态
Android获取当前网络状态 效果图 有网络 没有网络 源码 下载地址(Android Studio工程):http://download.csdn.net/detail/q4878802/9052 ...
- Dynamics CRM 依赖组件类型为应用程序功能区导致的无法删除实体问题的解决方法
看到有人问到这个问题,这边就简单描述下解决方法,主要是针对第一次碰到这个问题云里雾里的朋友,错误如下 在我们建lookup关联的时候有下图中的这么个设置,对于很多新手默认就是下图这样不会去做改动,因为 ...
- EBS 客户表结构
客户表/联系人/PARTY关联 HZ_PARTIES 客户账户表 HZ_CUST_ACCOUNTS SELECT hp.party_number --客户注册标识 , hp.party_name ...
- jQuery Ajax 使用 ($.ajax、$.post、$.get)
项目中只要涉及到前后台的交互,数据状态之间的交互,ajax是必不可少的.一般项目中jquery方式的ajax用的还是比较多的.封装的比较好,用起来也顺手,兼容浏览器之间的差异. 操作的方式有三种: 1 ...
- 2. React JSX语法及特点介绍
什么是JSX JSX 是一种类 XML 语言,全称是 JavaScript XML .React 可以不使用 JSX来编写组件,但是使用JSX可以让代码可读性更高.语义更清晰.对 Re ...
- Dynamics CRM 电子邮件服务器配置文件Advanced配置中关闭SSL
在新建电子邮件服务器配置文件时Advanced中的Use SSL for Incoming/Outgoing Connection默认都是启用的而且无法编辑,启用SSL当然是为了安全的考虑,但当客户的 ...
- svn propset svn:ignore
1 添加svn:ignore svn propset svn:ignore ".settings target .classpath .project element.iml" . ...
- iOS开发之八:UISlider、UISegmentedControl、UIPageControl的使用
本文的三种控件,用的也非常多,而我也是经常图懒,而去打开原来的项目去拷贝,现在记录一下,就不用去项目中去找这些控件的用法了. 一.UIActivityIndicatorView 的使用 UIActiv ...