Android开发 在代码中怎么动态改变Button坐标

Android开发 在代码中怎么动态改变Button坐标,第1张

首先,获取需要改变的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中的某个控件点击等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9431339.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-28
下一篇2023-04-28

发表评论

登录后才能评论

评论列表(0条)

    保存