android view 滑动 伸展 伸缩,Android奇效开发之可伸缩View(带互相挤压效果)上篇

本文介绍了如何在Android中实现一个可伸缩的View特效,当点击按钮时,相邻的按钮会相互挤压变化宽度,通过动画效果实现平滑过渡。详细讲解了实现原理和代码实现,包括改变View宽度的步骤和使用LayoutParams调整权重。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android特效开发之可伸缩View(带互相挤压效果)上篇

本文由manymore13原创,转载请标明出处 http://blog.youkuaiyun.com/manymore13/article/details/12799061

本次我要向大家介绍一个Android特效,这个特效也是我在某款软件中看到的,至于软件叫什么,我今天就不说

它的名字。我就不免费为它做广告了。

11104414.gif

好了,我来上一张动态效果图 在下面,屏幕小的请往下拉。

我不知道原软件是怎么个实现法,在这里我只是说说我的实现方法,代码可能不太好,这只是本人的一个idea 原理很简单!

特效实现原理:

改变按钮的宽度,每次当你点击按钮时,只有两个按钮改变宽度,一个变长,一个变短,只是这个变化是慢慢

进行,不是秒变的,你懂的,这就是动画效果。你点击短的按钮后会渐渐地变长,长的按钮会随着被压缩,其他按钮宽度不变。

我写这篇文章想起到一个抛砖引玉的效果,希望读者看了这篇文章后继续写个更好的文章。当然你不要忘记我啊,

记得要与我和大家分享。

下面是本次Demo运行后的效果图:

11104415.gif

可以看到view被挤压的效果,点击短的view会慢慢长大。在短的view慢慢长大的同时,最长的view会慢慢缩小,而且每次动画结束后都

有一个最长的view 。我这里所说的view在本次Demo中是按钮,当然你也可以换成其他的控件,或者是ViewGroup的子类也行。

public class PinchActivity extends Activity implements View.OnClickListener {

private final static String TAG = "MainActivity";

// 屏幕宽度

private int screentWidth = 0;

// View可伸展最长的宽度

private int maxWidth;

// View可伸展最小宽度

private int minWidth;

// 当前点击的View

private View currentView;

// 显示最长的那个View

private View preView;

// 主布局ViewGroup

private LinearLayout mainContain;

// 标识符 动画是否结束

private boolean animationIsEnd = true;

// 变大操作

private static final int OPE_BIG = 1;

// 变小操作

private static final int OPE_SMALL = 2;

// 当前操作 -1表示无效操作

private int currentOpe = -1;

// 前进的步伐距离

private static final int STEP = 10;

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

initCommonData();

initViewData();

measureWidth(screentWidth);

}

private void initViewData() {

mainContain = (LinearLayout) this.findViewById(R.id.main_contain);

View child;

int childCount = mainContain.getChildCount();

for (int i = 0; i < childCount; i++) {

child = mainContain.getChildAt(i);

child.setOnClickListener(this);

}

}

private void initCommonData()

{

DisplayMetrics metric = new DisplayMetrics();

getWindowManager().getDefaultDisplay().getMetrics(metric);

screentWidth = metric.widthPixels; // 屏幕宽度(像素)

}

private void setCurrentViewParams() {

if (currentView == null) {

return;

}

LayoutParams params = currentView.getLayoutParams();

if (params == null) {

return;

}

int realWidth = params.width;

int nextWidth = 0;

if (currentOpe == OPE_BIG) {

nextWidth = realWidth + STEP;

} else if (currentOpe == OPE_SMALL) {

nextWidth = realWidth - STEP;

}

if (nextWidth > maxWidth) {

nextWidth = maxWidth;

} else if (nextWidth < minWidth) {

nextWidth = minWidth;

}

params.width = nextWidth;

currentView.setLayoutParams(params);

if (nextWidth == maxWidth || nextWidth == minWidth) {

animationIsEnd = true;

onOffClickable();

stopAnimation();

return;

}

mHandler.sendEmptyMessageDelayed(1, 20);

}

// 初始化宽度 测量max min 长度

private void measureWidth(int screenWidth) {

int halfWidth = screenWidth / 2;

maxWidth = halfWidth - 50;

minWidth = (screenWidth - maxWidth) / (mainContain.getChildCount() - 1);

View child;

int childCount = mainContain.getChildCount();

for (int i = 0; i < childCount; i++) {

child = mainContain.getChildAt(i);

LayoutParams params = child.getLayoutParams();

if (i == 0) {

preView = child;

params.width = maxWidth;

} else {

params.width = minWidth;

}

child.setLayoutParams(params);

}

}

// 这里用handler更新界面

private Handler mHandler = new Handler() {

@Override

public void handleMessage(Message msg) {

if (msg.what == 1) {

setCurrentViewParams();

}

}

};

// 停止动画

private void stopAnimation() {

currentOpe = -1;

currentView = null;

}

private void startAnimation() {

if (currentView == null || currentOpe == -1) {

Log.d(TAG, "无效动画");

return;

}

animationIsEnd = false;

onOffClickable();

mHandler.sendEmptyMessage(1);

}

@Override

public void onClick(View v) {

int id = v.getId();

switch (id) {

case R.id.btnOne:

currentView = mainContain.getChildAt(0);

break;

case R.id.btnTwo:

currentView = mainContain.getChildAt(1);

break;

case R.id.btnThree:

currentView = mainContain.getChildAt(2);

break;

case R.id.btnFour:

currentView = mainContain.getChildAt(3);

break;

}

Log.i(TAG, ((Button) currentView).getText().toString() + " click");

if (currentView != null && animationIsEnd) {

int currentViewWidth = currentView.getWidth();

if (currentViewWidth == maxWidth) {

currentOpe = OPE_SMALL;

} else {

currentOpe = OPE_BIG;

}

clickEvent(currentView);

startAnimation();

}

}

private void clickEvent(View view) {

View child;

int childCount = mainContain.getChildCount();

for (int i = 0; i < childCount; i++) {

child = mainContain.getChildAt(i);

if (preView == child) {

LinearLayout.LayoutParams params = (android.widget.LinearLayout.LayoutParams) child

.getLayoutParams();

params.weight = 1.0f;

child.setLayoutParams(params);

} else {

LinearLayout.LayoutParams params = (android.widget.LinearLayout.LayoutParams) child

.getLayoutParams();

params.weight = 0.0f;

params.width = minWidth;

child.setLayoutParams(params);

}

}

preView = view;

printWeight();

}

private void printWeight() {

View child;

int childCount = mainContain.getChildCount();

for (int i = 0; i < childCount; i++) {

child = mainContain.getChildAt(i);

LinearLayout.LayoutParams params = (android.widget.LinearLayout.LayoutParams) child

.getLayoutParams();

Log.i("mm1", ((Button) child).getText() + ": " + params.weight);

}

}

//

private void onOffClickable()

{

View child;

boolean clickable = animationIsEnd;

int childCount = mainContain.getChildCount();

for (int i = 0; i < childCount; i++) {

child = mainContain.getChildAt(i);

child.setClickable(clickable);

}

}

}

改变控件的宽度或者高度:

1.获取参数类LayoutParams params =  View.getLayoutParams()

2. 设置控件高度或者宽度属性params.width 、params.height

3.设置完属性后不要忘记view.setLayoutParams(params);

LayoutParams 这个类是根据你父控件来获取的,比如我代码中:

LinearLayout.LayoutParams params = (android.widget.LinearLayout.LayoutParams) child.getLayoutParams();

child是一个Button ,在XML中它的父控件是LinearLayout,所以我这里有上面的强转, LinearLayout.LayoutParams 不仅有设置控件宽度和高度的属性,还有一个本次Demo重点用到的一个属性android:layout_weight ,想必大家在开发中用到这个属性的不在少数吧!

android:layout_weight

Indicates how much of the extra space in the LinearLayout will be allocated to the view associated

with these LayoutParams. Specify 0 if the view should not be stretched. Otherwise the extra pixels will be pro-rated among all views whose weight is greater than 0.

大概意思是View根据比例享用多余空间。这个比例就是你设置的这个值的大小,如果你设置它的值为0的话,就等于你没设置这个值,不等于零的话,就按你设的比例来瓜分LinearLayout中的多余空间。具体用法有不懂的请去seach。

最后说一些本次Demo中主要有以下三点不足:

1. 特效动画死板,变化速度死板;

2. 特效动画不能设置动画时间,如遇到高分辨率的机型,动画时间会变长。

3. view只能水平伸缩,不能竖直伸缩。

以上三点不足将在下篇为大家解决。

好了,上述就是本次特效讲解的全部内容,有什么地方说的有误的,欢迎您指正!欢迎拍砖!欢迎留言,如对你有帮助,请不要吝惜你手中的鼠标左键,点赞一个!

11104416.gif

11104416.gif欢迎您进入manymore13个人博客!

11104416.gif1楼suannai0314刚刚您的文章已被推荐到优快云首页,感谢您的分享。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值