android画廊怎样做出超炫效果
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android画廊怎样做出超炫效果相关的知识,希望对你有一定的参考价值。
首先来看下面的效果:
从上面的图片可以看到,当添加多张图片的时候,能够在下方形成一个画廊的效果,我们左右拉动图片来看我们添加进去的图片,效果是不是好了很多呢?下面来看看怎么实现吧!
上面的效果类似android里面ViewPage的效果,但是跟ViewPager有所不同,ViewPager每次只能显示一张图片。
其实我们是利用到了View的clipChildren属性,我们在这里要把ViewPager以及它的父窗体都设置为false,如下:
android:clipChildren="false"
因为如果clipChildren属性设置为true,就表明我们要将children给clip掉,就是说对于子元素来说,超出当前view的部分都会被切掉,那我们在这里把它设置成false,就表明超出view的部分,不要切掉,依然显示。
xml代码部分:
<!-- 配置container和pager的clipChildren=false, 并且指定marginLeft 和 marginRight 的值-->
<LinearLayout
android:id="@+id/container"
android:layout_
android:layout_
android:clipChildren="false"
android:gravity="center_horizontal"
android:layerType="software"
android:orientation="horizontal" >
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_
android:layout_
android:layout_marginLeft="110dp"
android:layout_marginRight="110dp"
android:clipChildren="false" >
</android.support.v4.view.ViewPager>
</LinearLayout>
Java代码部分:
// 1.设置幕后item的缓存数目
mViewPager.setOffscreenPageLimit(3);
// 2.设置页与页之间的间距
mViewPager.setPageMargin(10);
// 3.将父类的touch事件分发至viewPgaer,否则只能滑动中间的一个view对象
container.setOnTouchListener(new View.OnTouchListener()
@Override
public boolean onTouch(View v, MotionEvent event)
return mViewPager.dispatchTouchEvent(event);
);
参考技术A 下面上代码,相关解释都放在代码里了。1、建立一个新项目HelloGallery。
2、拷贝wallpaper_0.jpg…wallpaper_9.jpg 10个图片文件到res/drawable目录。
3、res/layout/main.xml文件的内容如下:
XML/html代码
<?xml version="1.0" encoding="utf-8"?>
<framelayout android:layout_height="fill_parent" android:layout_width="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/FrameLayout01">
<imageview android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/ImageView01" android:src="@drawable/wallpaper_0">
</imageview>
<gallery android:layout_height="wrap_content" android:layout_width="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/Gallery01" android:spacing="5dp">
</gallery>
</framelayout>
其中我们使用FrameLayout来实现叠加效果,使用ImageView来显示大图,Gallery来展示画廊,android:spacing="5dp" 属性则是用来设置元素之间的间隔。
4、在res/values/目录中新建一个attrs.xml内容如下:
XML/HTML代码
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<declare -styleable="" name="HelloGallery">
<attr name="android:galleryItemBackground">
</attr></declare>
</resources>
5、在MainHelloGallery.java中的内容如下:
Java代码
package android.basic.lesson13;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.Toast;
public class MainHelloGallery extends Activity
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//定义UI组件
final ImageView iv= (ImageView)findViewById(R.id.ImageView01);
Gallery g = (Gallery) findViewById(R.id.Gallery01);
//设置图片匹配器
g.setAdapter(new ImageAdapter(this));
//设置AdapterView点击监听器,Gallery是AdapterView的子类
g.setOnItemClickListener(new OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id)
//显示点击的是第几张图片
Toast.makeText(MainHelloGallery.this, "" + position,
Toast.LENGTH_LONG).show();
//设置背景部分的ImageView显示当前Item的图片
iv.setImageResource(((ImageView)view).getId());
);
//定义继承BaseAdapter的匹配器
public class ImageAdapter extends BaseAdapter
//Item的修饰背景
int mGalleryItemBackground;
//上下文对象
private Context mContext;
//图片数组
private Integer[] mImageIds = R.drawable.wallpaper_0,
R.drawable.wallpaper_1, R.drawable.wallpaper_2,
R.drawable.wallpaper_3, R.drawable.wallpaper_4,
R.drawable.wallpaper_5, R.drawable.wallpaper_6,
R.drawable.wallpaper_7, R.drawable.wallpaper_8,
R.drawable.wallpaper_9 ;
//构造方法
public ImageAdapter(Context c)
mContext = c;
//读取styleable资源
TypedArray a = obtainStyledAttributes(R.styleable.HelloGallery);
mGalleryItemBackground = a.getResourceId(
R.styleable.HelloGallery_android_galleryItemBackground, 0);
a.recycle();
//返回项目数量
@Override
public int getCount()
return mImageIds.length;
//返回项目
@Override
public Object getItem(int position)
return position;
//返回项目Id
@Override
public long getItemId(int position)
return position;
//返回视图
@Override
public View getView(int position, View convertView, ViewGroup parent)
ImageView iv = new ImageView(mContext);
iv.setImageResource(mImageIds[position]);
//给生成的ImageView设置Id,不设置的话Id都是-1
iv.setId(mImageIds[position]);
iv.setLayoutParams(new Gallery.LayoutParams(120, 160));
iv.setScaleType(ImageView.ScaleType.FIT_XY);
iv.setBackgroundResource(mGalleryItemBackground);
return iv;
android ViewPager 进阶(仿画廊/图书翻页) 与 palette 使用 (含完整Demo)
android ViewPager 仿画廊/图书翻页 与 palette 使用
废话不多说,先来看看完成的效果!
总结实现效果:
- ViewPager 实现无限自动播放
- ViewPager 实现中间大,两边小 [仿画廊效果]
- ViewPager 实现图片叠加[仿图书翻页效果]
- palette 调色板实现识别图片颜色,随着图片的变化来改变背景色的变化
普通ViewPager实现
先不管三七二十一,先吧最基本的ViewPager实现,之后在在基本的ViewPager上修改!
不用复制代码,先看思路就行,底部会给出完整代码!
activity_palette.xml布局:
java代码:
//设置适配器
viewPager.setAdapter(new BannerAdapter(this, mDrawables));
//Pager之间的间距
viewPager.setPageMargin(20);
//预加载
viewPager.setOffscreenPageLimit(3);
//默认第一张图 左右都有图
viewPager.setCurrentItem(1);
BannerAdapter 适配器:
public class BannerAdapter extends PagerAdapter {
private int[] mData;
private Context mContext;
public BannerAdapter(Context ctx, int[] data) {
this.mContext = ctx;
this.mData = data;
}
@Override
public int getCount() {
return mData.length;// 返回数据的个数
}
@Override
public Object instantiateItem(final ViewGroup container, final int position) {//子View显示
View view = View.inflate(container.getContext(), R.layout.banner_item_layout, null);
ImageView imageView = view.findViewById(R.id.iv_icon);
imageView.setImageResource(mData[position]);
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(mContext, "当前条目:" + position, Toast.LENGTH_SHORT).show();
}
});
container.addView(view);//添加到父控件
return view;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;// 过滤和缓存的作用
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);//从viewpager中移除掉
}
}
先来看看目前的效果:
就是一个很简单的ViewPager没什么好说的!
思路分析:
要想完成画廊的效果,那么必须吧viewPager分为以下几步骤:
- 让ViewPager显示出左右两侧的View
- 无限滑动
- 自定义ViewPager 滑动动画,滑动过程中中间大,两边小
- 自动播放
那就来根据思路实现效果吧 :
让ViewPager显示出左右两侧的View
来看看效果:
无限滑动
这个也是真 的简单,直接取%即可实现
来看看效果:
中间大,两边小效果
要想实现这个效果,就要来介绍本篇重中之重! ViewPager.PageTransformer
ViewPager.PageTransformer
先来看使用:
viewPager.setPageTransformer(true, new ScaleTransformer());
- 参数一: 是否逆转,我没看出有什么效果,懂这个参数的记得在评论区留言哦!
- 参数二: 用来控制ViewPager 动画的
public class ScaleTransformer implements ViewPager.PageTransformer {
private static final float MAX_SCALE = 1.0f;//0缩放
private static final float MIN_SCALE = 0.80f;//0.85缩放
@Override
public void transformPage(@NonNull View view, float position) {
}
}
实现implements ViewPager.PageTransformer重写transformPage()方法,有2个参数
/**
* A PageTransformer is invoked whenever a visible/attached page is scrolled.
* This offers an opportunity for the application to apply a custom transformation
* to the page views using animation properties.
*
* <p>As property animation is only supported as of Android 3.0 and forward,
* setting a PageTransformer on a ViewPager on earlier platform versions will
* be ignored.</p>
*/
public interface PageTransformer {
/**
* Apply a property transformation to the given page.
*
* @param page Apply the transformation to this page
* @param position Position of page relative to the current front-and-center
* position of the pager. 0 is front and center. 1 is one full
* page position to the right, and -1 is one page position to the left.
*/
void transformPage(@NonNull View page, float position);
}
这个方法在onPageScrolled页面滑动的过程中回调
@CallSuper
protected void onPageScrolled(int position, float offset, int offsetPixels) {
....省略.......
if (mPageTransformer != null) {
....省略.......
mPageTransformer.transformPage(child, transformPos);
}
}
mCalledSuper = true;
}
transformPage参数:
- 参数一: 当前view
- 参数二:当前view的位置
这里比较抽象,画张图看看
- 红色当前View
- 蓝色 左侧View
- 黄色 右侧View
不滑动状态position变化:
红色 | 蓝色 | 黄色 |
---|---|---|
position = -1 | position = 0 | position = 1 |
滑动状态position变化:
状态 | 红色 | 蓝色 | 黄色 |
---|---|---|---|
左滑动 | position < -1 | 0 < position < -1 | 1 < position < 0 |
右滑动 | -1 < position < 0 | 0 < position < 1 | position > 1 |
先来打印一下看看position的值:
还看不懂? 再来画一张图:
好了,position就介绍到这里!
先简简单单修改代码,先看看效果:
public class ScaleTransformer implements ViewPager.PageTransformer {
private static final float MAX_SCALE = 1.0f;//0缩放
private static final float MIN_SCALE = 0.80f;//0.85缩放
@Override
public void transformPage(@NonNull View view, float position) {
//position != 0 表示左侧和右侧的view
if (position != 0) {
view.setScaleX(MIN_SCALE);
view.setScaleY(MIN_SCALE);
} else {
view.setScaleX(MAX_SCALE);
view.setScaleY(MAX_SCALE);
}
}
}
效果:
可以看到,要实现的效果已经渐渐接近了!
在加上滑动时候放大缩小即可
public class ScaleTransformer implements ViewPager.PageTransformer {
private static final float MAX_SCALE = 1.0f;//0缩放
private static final float MIN_SCALE = 0.80f;//0.85缩放
@Override
public void transformPage(@NonNull View view, float position) {
if (position < 1) {
float scaleFactor = MIN_SCALE + (1 - Math.abs(position)) * (MAX_SCALE - MIN_SCALE);
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else {
view.setScaleX(MIN_SCALE);
view.setScaleY(MIN_SCALE);
}
}
}
这里涉及到一个小算法
float scaleFactor = MIN_SCALE + (1 - Math.abs(position)) * (MAX_SCALE - MIN_SCALE);
指的就是变化过程中view的大小
这段代码要细细的品味一下!!!很关键!!
来看看湿滑的效果:
无限自己滚动
这段代码也是简单的很:
直接上代码不多贝贝:
//用来记录是否按压,如果按压,则不滚动
boolean isDown ;
Timer timer = new Timer();
//定时器播放ViewPager
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
if (!isDown) {
//获取到当前的位置
int page = viewPager.getCurrentItem() + 1;
runOnUiThread(() -> viewPager.setCurrentItem(page));
}
}
};
// 每2.5秒执行一次
timer.schedule(timerTask, 0, 2500);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//viewPager滑动的时候,设置不让滚动
isDown = true;
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
//ViewPager不点击了让滚动
isDown = false;
}
});
这段代码过于简单,就不看效果了!
仿图书效果
这个效果和仿画廊流程一样,也是对PageTransformer的操作,直接上代码了!
public class StackPageTransformer implements ViewPager.PageTransformer {
private final ViewPager viewPager;
private final float SCALE_VALUE = 1f;
//View 之间的偏移量
private final float DEVIATION = 60f;
//旋转
private final float ROTATION = 60f;
//图片是否叠加【默认不叠加】
private final boolean isStack = false;
public StackPageTransformer(ViewPager viewPager) {
this.viewPager = viewPager;
}
@Override
public void transformPage(@NonNull View view, float position) {
Log.i("szjPosition2", position + "");
/*
* 当不滑动状态下:
* position = -1 左侧View
* position = 0 当前View
* position = 1 右侧View
*
* 当滑动状态下:
* 向左滑动: [ position < 0 && position > -1]
* 左侧View position < -1
* 当前View 0 ~ -1
* 右侧View 1 ~ 0
*
* 向右滑动:[position > 0 && position < 1 ]
* 左侧View -1 < position < 0
* 当前View 0 ~ 1
* 右侧View position > 1
*/
int pageWidth = viewPager.getWidth();
//隐藏左侧侧的view
if (position == -1) {
view.setVisibility(View.GONE);
} else {
view.setVisibility(View.VISIBLE);
}
//当前View和右侧的View [让右侧View和当前View叠加起来]
if (position >= 0) {
float translationX;
//这里不要晕! 改变isStack来看看效果吧!!
if (isStack) {
translationX = DEVIATION - (pageWidth) * position;
} else {
translationX = (DEVIATION - pageWidth) * position;
}
Log.i("szjTranslationX", translationX + "");
view.setTranslationX(translationX);
}
//当前view
if (position == 0) {
view.setScaleX(SCALE_VALUE);
view.setScaleY(SCALE_VALUE);
} else {
//左侧已经隐藏了,所以这里值的是右侧View的偏移量
float scaleFactor = Math.min(SCALE_VALUE - position * 0.1f, SCALE_VALUE);
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
}
//向左滑动
if (position < 0 && position > -1) {
//旋转
view.setRotation(ROTATION * position);
view.setAlpha(1 - Math.abs(position));
} else {
//透明度 其他状态不设置透明度
view.setAlpha(1);
}
//向右滑动
if (position > 0 && position < 1) {
view.setRotation(0);
}
}
}
看看效果:
palette 调色板
先添加依赖:
implementation 'com.android.support:palette-v7:26.0.0-alpha1'
简单介绍:
palette 传入一张Bitmap,然后他会通过图片像素点来分析出颜色占比,提取出你需要的颜色!!
使用:
public void initPalette(Bitmap bitmap) {
new Thread(() -> Palette.from(bitmap).generate(palette -> {
//以RGB压缩整数的形式从调色板返回静音和深色。
int darkMutedColor = palette.getDarkMutedColor(Color.TRANSPARENT);
//暗 柔和 [以RGB压缩整数的形式从调色板返回静音和浅色。]
int lightMutedColor = palette.getLightMutedColor(Color.TRANSPARENT);
//暗 鲜艳 [以RGB压缩整数的形式从调色板返回深色和鲜艳的颜色。]
int darkVibrantColor = palette.getDarkVibrantColor(Color.TRANSPARENT);
//量 鲜艳 [以RGB压缩整数的形式从调色板返回明亮的颜色。]
int lightVibrantColor = palette.getLightVibrantColor(Color.TRANSPARENT);
//柔和 [将调色板中的静音颜色作为RGB压缩整数返回。]
int mutedColor = palette.getMutedColor(Color.TRANSPARENT);
//以RGB压缩整数形式返回调色板中最鲜艳的颜色。
int vibrantColor = palette.getVibrantColor(Color.TRANSPARENT);
//从调色板中返回一个明亮且充满活力的样例。可能为空。
Palette.Swatch lightVibrantSwatch = palette.getLightVibrantSwatch();
int hotColor = Color.TRANSPARENT;
if (lightVibrantSwatch != null) {
//谷歌推荐的:图片的整体的颜色rgb的混合痔---主色调
int rgb = lightVibrantSwatch.getRgb();
hotColor = getTranslucentColor(0.7f, rgb);
}
// 拿到颜色 这里就可以给View 设置颜色了
})).start();
}
然后通过随机图片,设置不同的图片来测试一下管用不管用!
来看看效果:
这里用到了动态代码设置渐变,代码很简单,给大家看看吧
/**
* TODO 设置渐变颜色
*
* @param view 需要设置的View
* @param colors 渐变颜色
* @param type 渐变位置 例如:GradientDrawable.Orientation.LEFT_RIGHT 从左到右
* @param radius 圆角
*/
public void setGradualChange(View view, int[] colors, GradientDrawable.Orientation type, int radius) {
GradientDrawable drawable = new GradientDrawable(type, colors);
drawable.setCornerRadius(radius);
view.setBackground(drawable);
}
原创不易,您的点赞就是对我最大的支持!!
以上是关于android画廊怎样做出超炫效果的主要内容,如果未能解决你的问题,请参考以下文章
android 卡片画廊效果及RecycleView、ViewPager、ScrollView之前的冲突解决