
首先,获取需要改变的Button 通过Button myButton = findviewById(Ridxxx);
之后有2种方式改变坐标
第一种,带动画的改变
//位移动画 从左到右参数分别为//x轴方向起始位置x差值 ,x轴方向结束位置x差值 , y轴方向起始位置y差值 ,y轴方向结束位置y差值
TranslateAnimation translateAnimation = new TranslateAnimation(fromXDelta,toXDelta,fromYDelta,toYDelta);
translateAnimationsetDuration(300); //设置动画世界
buttonsetAnimation(translateAnimation);
上面的示例只是许多动画中的一种简单地位移动画,如果有兴趣可以查阅一下android动画方面的知识
第二种,直接改变控件的位置
这种方法里面也有2种不用的情况
//这是第一种 直接付给此button新的xy坐标buttonsetX();
buttonsetY();
//这是第二种 让button有一个位移到指定地点
buttonsetTranslationX();
buttonsetTranslationY();
第一种直接改变了xy坐标,第二种是添加了坐标位移但是控件本身的xy坐标还是在原来的位置
public static Bitmap createBitmap (Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)
返回一个不可改变的位图,该位图来自源位图的子集,并根据可选的矩阵进行转换。它被初始化为跟源位图有同样的密度。
参数
source 产生子位图的源位图;
x 子位图第一个像素在源位图的X坐标
y 子位图第一个像素在源位图的y坐标
width 子位图每一行的像素个数
height 子位图的行数
m 对像素值进行变换的可选矩阵
filter 如果为true,源图要被过滤。该参数仅在matrix包含了超过一个翻转才有效
返回值
一个描述了源图指定子集的位图。
异常
IllegalArgumentException 如果x,y,width,height的值超出了源图的维度,该异常会被抛出。
最近项目中有个需求,点击某一个按钮以外的位置触发按钮的点击事件。 但是这整个view 都是第三方的。
通过父容器的dispatchTouchEvent(MotionEvent ev) 对事件进行控制和分发。
(1)找到要触发的按钮,获取他的坐标 通过递归找到对应的控件
(2)判断点击是否在控件上
/
判断是否点击在view上
@param pointX
@param pointY
@param view
@return
/
private boolean isPointInView(float pointX, float pointY, View view) {
if (view ==null) {
return false;
}
int[] location =new int[2];
viewgetLocationOnScreen(location);
int x = location[0];
int y = location[1];
if (pointX >= x && pointX <= x + viewgetWidth() && pointY >= y && pointY <= y + viewgetHeight()) {
return true;
}
return false;
}
(3) 如果不在控件的位置,则通过传递 控件的MotionEvent 设置MotionEvent 的location ,分发childdispatchTouchEvent 事件
private boolean dispatchChildTouchEvent(MotionEvent ev, View child) {
MotionEvent transformedEvent = MotionEventobtain(ev);
if (downPosX ==0 ||downPosY ==0) {
int wd = Mathmax(childgetWidth(), 1);
int hg = Mathmax(childgetHeight(), 1);
Random random =new Random();
downPosX = randomnextFloat() (wd -1);
downPosY = randomnextFloat() (hg -1);
}
transformedEventsetLocation(downPosX, downPosY);
Loggerd(TAG, "dispatchChildTouchEvent"+" posx " +downPosX +" posy " +downPosY);
return childdispatchTouchEvent(transformedEvent);
}
上一篇通过在父控件绘制前景的方式展示小红点,在布局文件中配置标记控件就能为任意子控件添加小红点。实现方案是”布局文件中配置带小红点控件 id,在父控件中获取它们的坐标,并在其右上角绘制圆圈“。但这个方案有一个漏洞,当子控件做动画,即子控件尺寸发生变化时,小红点不会联动。效果入下图:
在父控件的 draw() , dispatchDraw() , drawChild() 中打 log,子控件做动画时都未能捕获到联动的事件。
突然想起 androidxcoordinatorlayoutwidgetCoordinatorLayout 中的 Behavior ,在 onDependentViewChanged() 中可以实时获得关联控件的属性变化。它是如何做到的?沿着调用链往上查找:
当关联子控件发生变化时,会遍历关联控件并将变换通过 onDependentViewChanged() 传递出去。沿着调用链再往上:
CoordinatorLayout 在 onAttachedToWindow() 时注册了 View 树观察者,子控件属性变化时必定会触发 View树重绘,这样就可以在 onPreDraw() 中监听到它们的属性变化。
将这套机制照搬到自定义容器控件 TreasureBox :
这样当需要绘制小红点的子控件属性发生变化时,标记控件就可以在 onPreDraw() 中收到通知:
每次 View 树重绘前都可以在 onPreDraw() 中实时获取子控件的宽高及坐标,为了避免过度重绘,只有当属性变化时,才触发父控件重绘。需要记忆上次重绘的属性,通过比较就能知道属性是否发生变更:
还需要变更下小红点绘制逻辑,之前的逻辑如下:
如果沿用这套绘制逻辑,即使父控件监听到子控件重绘,小红点也不会跟着联动。那是因为 View 的 getTop() 和 getRight() 不包含位移值:
而 getX() 和 getY() 则包含了位移值:
只需要将绘制逻辑中的 vright 和 vtop 换成 vx 和 vy ,小红点就能和动画联动了。为控件添加位移和缩放动画,测试一下:
GG思密达~
。位移动画的确会联动,但缩放并没有~
打了 log 才发现,View 通过 setScale() 的方式进行动画时,它的宽高和坐标并不会发生变化。。。
但必然是有一个属性的值变化了,虽然暂且不知道它是啥?
只能打开 View 源码,遍历所有 get 开头的函数,然后把它们的值打印在 onPreDraw() 中。经过多次尝试,终于找到了一个函数,它的返回值和子控件缩放动画联动:
当子控件做缩小动画时,该函数返回的 Rect 中的 left 会变大而 right 会变小。
函数的返回值在 mLeft , mRight , mTop , mBottom 的基础上叠加了 matrix 的值。做动画的属性值最终都会反映到 matrix 上,这样一分析好像能自圆其说,即该函数会实时返回 view 因动画而改变的属性值。
如此一来,只需要记忆上一次的 Rect ,就能在下次重绘前通过比较得知子控件是否做了动画:
绘制小红点逻辑也要做响应改动:
大功告成,效果如下:
getRowX:触摸点相对于屏幕的坐标
getX: 触摸点相对于按钮的坐标
getRawX()获取的是屏幕上的原生(original raw)x坐标,而getX(int pointerIndex)只是说获取的是指定的触控点坐标,getX()就是获取第一个触控点的坐标。所以,getRawX()就是说,获取的是相对于屏幕左上角的x坐标,而getX()是获取相对控件左上角的x坐标。
使用自定义控件,先计算得到每个圆心的x轴坐标,然后绘制出圆心,长条,文字
StepViewjava
使用方法
ps:
使用RecyclerView通过控制item的显示隐藏即可实现
itemxml
ativityxml
Adapterjava
对于很多游戏使用屏幕控制一般需要考虑长按事件,比如在动作类的游戏中需要长按发射武器,结合Android Button模型,我们实现一个带的Button的长按,为了更清晰的显示原理,Android开发网这里使用ImageButton作为基类
public class RepeatingImageButton extends ImageButton {
private long mStartTime; //记录长按开始
private int mRepeatCount; //重复次数计数
private RepeatListener mListener;
private long mInterval = 500; //Timer触发间隔,即每05秒算一次按下
public RepeatingImageButton(Context context) {
this(context, null);
}
public RepeatingImageButton(Context context, AttributeSet attrs) {
this(context, attrs, androidRattrimageButtonStyle);
}
public RepeatingImageButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setFocusable(true); //允许获得焦点
setLongClickable(true); //启用长按事件
}
public void setRepeatListener(RepeatListener l, long interval) { //实现重复按下事件listener
mListener = l;
mInterval = interval;
}
@Override
public boolean performLongClick() {
mStartTime = SystemClockelapsedRealtime();
mRepeatCount = 0;
post(mRepeater);
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (eventgetAction() == MotionEventACTION_UP) { // 本方法原理同onKeyUp的一样,这里处理屏幕事件,下面的onKeyUp处理Android手机上的物理按键事件
removeCallbacks(mRepeater);
if (mStartTime != 0) {
doRepeat(true);
mStartTime = 0;
}
}
return superonTouchEvent(event);
}
//处理导航键事件的中键或轨迹球按下事件
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEventKEYCODE_DPAD_CENTER:
case KeyEventKEYCODE_ENTER:
superonKeyDown(keyCode, event);
return true;
}
return superonKeyDown(keyCode, event);
}
//当按键d起通知长按结束
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEventKEYCODE_DPAD_CENTER:
case KeyEventKEYCODE_ENTER:
removeCallbacks(mRepeater); //取消重复listener捕获
if (mStartTime != 0) {
doRepeat(true); //如果长按事件累计时间不为0则说明长按了
mStartTime = 0; //重置长按计时器
}
}
return superonKeyUp(keyCode, event);
}
private Runnable mRepeater = new Runnable() { //在线程中判断重复
public void run() {
doRepeat(false);
if (isPressed()) {
postDelayed(this, mInterval); //计算长按后延迟下一次累加
}
}
};
private void doRepeat(boolean last) {
long now = SystemClockelapsedRealtime();
if (mListener != null) {
mListeneronRepeat(this, now - mStartTime, last -1 : mRepeatCount++);
}
}
下面是重复Button Listener接口的定义,调用时在Button中先使用setRepeatListener()方法实现RepeatListener接口
public interface RepeatListener {
void onRepeat(View v, long duration, int repeatcount); //参数一为用户传入的Button对象,参数二为延迟的毫秒数,第三位重复次数回调。
}
}
本类大家可以直接在自己的View中implements实现RepeatListener接口即可
以上就是关于Android开发 在代码中怎么动态改变Button坐标全部的内容,包括:Android开发 在代码中怎么动态改变Button坐标、Android bitmap如何获取坐标、android 模拟view中的某个控件点击等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)