我想要创建一个在按下时改变大小(稍微小一点)的按钮,再次释放按钮后,大小应该变回正常大小。我正在使用 Scale xml 来实现这一点,但它重新定位了自己即使我不释放按钮。
按钮在这里我指的是图像视图。
这是我的源代码:-
imgSpin = (ImageView) findViewById(R.id.iv_spins);
imgSpin.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
imgSpin.startAnimation(mAnimation);
spinslot();
break;
case MotionEvent.ACTION_UP:
imgSpin.clearAnimation();
imgSpin.setEnabled(false);
break;
}
return true;
}
});
我的体重秤 Xml :-
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="200"
android:fromXScale=".8"
android:fromYScale=".8"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0" >
</scale>
我的 XML:-
<LinearLayout
android:id="@+id/layout_status"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight=".2"
android:orientation="horizontal" >
<View
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".5" />
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2.1"
android:background="@drawable/bootser" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2.5"
android:background="@drawable/bet_bg"
android:gravity="center_vertical"
android:orientation="horizontal"
android:weightSum="1" >
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_weight=".2"
android:src="@drawable/leftarrow" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:layout_weight=".6"
android:gravity="center"
android:text="Bet"
android:textColor="@android:color/white" />
<ImageView
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:layout_weight=".2"
android:src="@drawable/rightarrow" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2.5"
android:background="@drawable/container"
android:gravity="center" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="winning"
android:textColor="@android:color/white" />
</LinearLayout>
<ImageView
android:id="@+id/iv_spins"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.9"
android:background="@drawable/spin" />
<View
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".5" />
</LinearLayout>
我尝试使用 paramLayout,但是因为我在 XML 中设置了权重,所以它不会对动画产生影响。
我已经在使用这种方法了:-
case MotionEvent.ACTION_DOWN:
ViewGroup.LayoutParams params = imgSpin.getLayoutParams();
// Button new width
params.width = params.width - (params.width *90/100);
imgSpin.setLayoutParams(params);
break;
params.width 总是让我返回零所以我尝试用重量来做这个,通过使用重量我的视图在点击时出现故障..我希望它平滑所以我更喜欢缩放
第二种方法:-
case MotionEvent.ACTION_DOWN:
LinearLayout.LayoutParams params = (android.widget.LinearLayout.LayoutParams) imgSpin
.getLayoutParams();
// Button new width
params.weight = 1.7f;
imgSpin.setLayoutParams(params);
// imgSpin.startAnimation(mAnimation);
// spinslot();
break;
case MotionEvent.ACTION_UP:
LinearLayout.LayoutParams params2 = (android.widget.LinearLayout.LayoutParams) imgSpin
.getLayoutParams();
// Button new width
params2.weight = 1.9f;
imgSpin.setLayoutParams(params2);
// imgSpin.clearAnimation();
imgSpin.setEnabled(false);
break;
}
return true;
有效但不流畅
请告诉我怎么做
谢谢
这是你想要的:-
imgSpin.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
ObjectAnimator scaleDownX = ObjectAnimator.ofFloat(imgSpin,
"scaleX", 0.8f);
ObjectAnimator scaleDownY = ObjectAnimator.ofFloat(imgSpin,
"scaleY", 0.8f);
scaleDownX.setDuration(1000);
scaleDownY.setDuration(1000);
AnimatorSet scaleDown = new AnimatorSet();
scaleDown.play(scaleDownX).with(scaleDownY);
scaleDown.start();
spinslot();
break;
case MotionEvent.ACTION_UP:
ObjectAnimator scaleDownX2 = ObjectAnimator.ofFloat(
imgSpin, "scaleX", 1f);
ObjectAnimator scaleDownY2 = ObjectAnimator.ofFloat(
imgSpin, "scaleY", 1f);
scaleDownX2.setDuration(1000);
scaleDownY2.setDuration(1000);
AnimatorSet scaleDown2 = new AnimatorSet();
scaleDown2.play(scaleDownX2).with(scaleDownY2);
scaleDown2.start();
imgSpin.setEnabled(false);
break;
}
return true;
}
});
只需在您的 xml 中进行一些更改即可:-
<ImageView
android:id="@+id/iv_spins"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.9"
android:adjustViewBounds="true"
android:background="@drawable/spin"
android:scaleX="1"
android:scaleY="1" />
利用scaleDown.play(scaleDownX).with(scaleDownY),它会保持动画的位置,不会恢复到原来的位置
希望它能解决你的问题 干杯
在 /res/animator 中创建两个 XML
reduce_size.xml
<?xml version="1.0" encoding="utf-8"?>
<set android:ordering="sequentially"
xmlns:android="http://schemas.android.com/apk/res/android">
<set>
<objectAnimator
android:propertyName="scaleX"
android:duration="300"
android:valueTo="0.9f"
android:valueType="floatType"/>
<objectAnimator
android:propertyName="scaleY"
android:duration="300"
android:valueTo="0.9f"
android:valueType="floatType"/>
</set>
</set>
重新获得大小.xml
<?xml version="1.0" encoding="utf-8"?>
<set android:ordering="sequentially"
xmlns:android="http://schemas.android.com/apk/res/android">
<set>
<objectAnimator
android:propertyName="scaleX"
android:duration="1000"
android:valueTo="1f"
android:startOffset="300"
android:valueType="floatType"/>
<objectAnimator
android:propertyName="scaleY"
android:duration="1000"
android:valueTo="1f"
android:startOffset="300"
android:valueType="floatType"/>
</set>
</set>
用法
在
MotionEvent.ACTION_DOWN
AnimatorSet reducer = (AnimatorSet) AnimatorInflater.loadAnimator(mContext,R.animator.squeeze_in);
reducer.setTarget(view);
reducer.start();
在
MotionEvent.ACTION_UP
AnimatorSet regainer = (AnimatorSet) AnimatorInflater.loadAnimator(mContext,R.animator.squeeze_out);
regainer.setTarget(view);
regainer.start();
自 API 21 (Lollipop) 以来,基于 stateListAnimator 属性的 xml-only 解决方案可用。这是一个布局示例,在按下时缩放到其原始大小的 0.9:
<!-- res/layout/my_layout.xml -->
<LinearLayout ...
android:stateListAnimator="@animator/zoom_out_animator">...</layout>
<!-- res/animator/zoom_out_animator -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<set>
<objectAnimator
android:propertyName="scaleX"
android:valueTo="1.0"
android:duration="@android:integer/config_shortAnimTime"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
<objectAnimator
android:propertyName="scaleY"
android:valueTo="1.0"
android:duration="@android:integer/config_shortAnimTime"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</set>
</item>
<item android:state_pressed="true">
<set>
<objectAnimator
android:propertyName="scaleX"
android:valueTo="0.9"
android:duration="@android:integer/config_shortAnimTime"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
<objectAnimator
android:propertyName="scaleY"
android:valueTo="0.9"
android:duration="@android:integer/config_shortAnimTime"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</set>
</item>
</selector>
您还可以在官方素材示例应用程序Owl中找到示例。看看onboarding_topic_item.xml.
几个类似的问题:
您可以在 touchlistener 上按如下方式以编程方式执行此操作
new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction == MotionEvent.ACTION_DOWN) {
// scale your value
float reducedvalue = (float)0.7;
v.setScaleX(reducedvalue);
v.setScaleY(reducedvalue);
}
else if (event.getAction == MotionEvent.ACTION_UP) {
v.setScaleX(1);
v.setScaleY(1);
}
}
}
很简单,但是你得知道Android API是如何处理每个监听器的调用的。
这是诀窍:
1- TouchListener 中的 onTouch 方法将首先被调用。
1.1-如果onTouch方法返回true,那么onLongClick(在LongClickListener中)或onClick(在ClickListener中)将被忽略(都不会再被调用)。
2- 如果 onTouch 方法返回 false,则检查 onLongClick 是否返回 true,因此 onClick 将不会被调用,但如果它返回 false,则 onClick 也将被调用。
举个例子:
targetButton.setOnLongClickListener(v -> {
targetButton.animate().scaleX(1.2f).scaleY(1.2f).setDuration(0);
Log.d("Button", "onLong: ");
return true;
});
targetButton.setOnClickListener(v -> {
Log.d("Button", "onClick: ");
});
targetButton.setOnTouchListener((v, event) -> {
Log.d("Button", "onTouch: ");
if (event.getAction() == MotionEvent.ACTION_UP) {
recordButton.animate().scaleX(1.0f).scaleY(1.0f).setDuration(0);
}
// if you want to make it pretty increase the size when click also
/* else if (event.getAction() == MotionEvent.ACTION_DOWN) {
targetButton.animate().scaleX(1.2f).scaleY(1.2f).setDuration(0);
} */
return false;
});
在这个例子中,如果我检测到长按,我会尝试增加按钮的大小,否则会对 onClick 方法做一些事情,如果用户释放按钮,我会再次减小按钮的大小。
如果您希望每次调用 onLongClick 时都调用 onClick,只需让 onLongClick 返回 false;
你可以添加 fillafter 属性:android:fillAfter="true"
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="200"
android:fromXScale=".8"
android:fromYScale=".8"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="true"
android:toXScale="1.0"
android:toYScale="1.0" >
</scale>
<ImageView
android:id="@+id/iv_spins"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.9"
android:adjustViewBounds="true"
android:background="@drawable/spin"
android:scaleX="1"
android:scaleY="1"
/>
Kotlin 解决方案
fun View.addElasticTouchEffect() {
this.setOnTouchListener { view, motionEvent ->
when (motionEvent.action) {
MotionEvent.ACTION_DOWN -> {
this.animate().scaleX(0.96f).scaleY(0.96f).setDuration(100).start()
}
MotionEvent.ACTION_UP,
MotionEvent.ACTION_CANCEL -> {
this.animate().scaleX(1f).scaleY(1f).setDuration(100).start()
if (motionEvent.action == MotionEvent.ACTION_UP) {
this.performClick()
}
}
}
return@setOnTouchListener true
}
}
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.ivAddress.addElasticTouchEffect()
binding.ivAddress.setOnClickListener {
// on click
}
}
}
希望对你有帮助