日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

自定义控件:视差特效

發(fā)布時(shí)間:2025/4/16 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 自定义控件:视差特效 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

ParallaxEffects 視差特效

  • 了解ImageView 的scaleType 屬性
  • 掌握ListView 的overScrollBy()方法

應(yīng)用場(chǎng)景:QQ 空間,微信朋友圈,微博,需要快速定位的列表效果圖

界面初始化

填充ListView

自定義ParallaxListView 繼承ListView

public class ParallaxListView extends ListView {public ParallaxListView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}public ParallaxListView(Context context, AttributeSet attrs) {super(context, attrs);}public ParallaxListView(Context context) {super(context);} }

填充ListView 的數(shù)據(jù)

public class Cheeses {public static final String[] NAMES = new String[]{"宋江", "盧俊義", "吳用","公孫勝", "關(guān)勝", "林沖", "秦明", "呼延灼", "花榮", "柴進(jìn)", "李應(yīng)", "朱仝", "魯智 深","武松", "董平", "張清", "楊志", "徐寧", "索超", "戴宗", "劉唐", "李逵", "史進(jìn)", " 穆弘","雷橫", "李俊", "阮小二", "張橫", "阮小五", " 張順", "阮小七", "楊雄", "石秀", " 解珍"," 解寶", "燕青", "朱武", "黃信", "孫立", "宣贊", "郝思文", "韓滔", "彭玘", "單廷珪 ","魏定國(guó)", "蕭讓", "裴宣", "歐鵬", "鄧飛", " 燕順", "楊林", "凌振", "蔣敬", "呂方 ","郭盛", "安道全", "皇甫端", "王英", "扈三娘", "鮑旭", "樊瑞", "孔明", "孔亮", " 項(xiàng)充","李袞", "金大堅(jiān)", "馬麟", "童威", "童猛", "孟康", "侯健", "陳達(dá)", "楊春", "鄭天壽 ","陶宗旺", "宋清", "樂和", "龔?fù)?#34;, "丁得孫", "穆春", "曹正", "宋萬", "杜遷", "薛永 ", "施恩","周通", "李忠", "杜興", "湯隆", "鄒淵", "鄒潤(rùn)", "朱富", "朱貴", "蔡福", "蔡慶", " 李立","李云", "焦挺", "石勇", "孫新", "顧大嫂", "張青", "孫二娘", " 王定六", "郁保四", " 白勝","時(shí)遷", "段景柱"}; }

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity" ><com.example.parallax.widget.ParallaxListView android:id="@+id/plv"android:layout_width="match_parent"android:layout_height="match_parent"/> </RelativeLayout>

MainActivity 填充數(shù)據(jù)

protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);plv = (ParallaxListView) findViewById(R.id.plv);plv.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, Cheeses.NAMES)); }

ListView 添加Header

創(chuàng)建header 布局文件

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><ImageView android:id="@+id/iv_header"android:layout_width="match_parent"android:layout_height="160dp"android:contentDescription="@null"android:scaleType="centerCrop"android:src="@drawable/parallax_img"/> </RelativeLayout>

第10 行scaleType 為圖片的填充模式

圖片填充模式對(duì)比

  • matrix:圖片寬高不變,以ImageView 左上角為基準(zhǔn)向右向下填充ImageView
  • fixXY:圖片寬高分別拉伸或壓縮,以ImageView 左上角為基準(zhǔn)向右向下填充滿ImageView 的寬和高
  • fitStart:圖片寬高分別拉伸或壓縮,以ImageView 左上角為基準(zhǔn)向右向下填充滿ImageView 的寬,ImageView的高不用管
  • fitCenter:圖片寬高分別拉伸或壓縮,圖片居中顯示,填充滿ImageView 的寬,ImageView 的高不用管
  • fitEnd:圖片寬高分別拉伸或壓縮,以ImageView 左下角為基準(zhǔn)向右向上填充滿ImageView 的寬,ImageView的高不用管
  • center:圖片寬高不變,圖片居中顯示,填充ImageView
  • centerCrop:圖片寬高分別拉伸或壓縮,圖片居中顯示,直到填充滿ImageView
  • centerInside:原圖比ImageView 小,圖片居中顯示,填充ImageView,原圖比ImageView 大,圖片寬高分別拉伸或壓縮,直到填充滿ImageView 的寬或高即可

MainActivity.java 中添加頭布局

protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);plv = (ParallaxListView) findViewById(R.id.plv);View headerView = View.inflate(this,R.layout.layout_header, null);//添加頭布局,需要在setAdapter 前添加plv.addHeaderView(headerView);plv.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,Cheeses.NAMES)); }

下拉放大

overScrollBy()方法參數(shù)解析

ParallaxListView 需要重寫overScrollBy()方法,api 要求9 以上

/*** 滑動(dòng)到ListView 兩端才會(huì)調(diào)用*/ @Override protected boolean overScrollBy(int deltaX, int deltaY, int scrollX,int scrollY, int scrollRangeX, int scrollRangeY,int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {//deltaY 豎直方向滑動(dòng)的瞬時(shí)變化量,頂部下拉為-,底部上拉為+//scrollY 兩端滑動(dòng)超出的距離,頂部為-,底部為+//scrollRangeY 豎立方向滑動(dòng)的范圍//maxOverScrollY 豎立方向最大的滑動(dòng)位置//isTouchEvent 是否是用戶觸摸拉動(dòng),true 表示用戶手指觸摸拉動(dòng),false 表示慣性System.out.println("deltaY:" + deltaY + " scrollY:" + scrollY+ " scrollRangeY:" + scrollRangeY + " maxOverScrollY:"+ maxOverScrollY + " isTouchEvent:" + isTouchEvent);return super.overScrollBy(deltaX, deltaY, scrollX, scrollY,scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); }

? 理解deltaY 及isTouchEvent 參數(shù)的含義

動(dòng)態(tài)改變頭布局的高度

ParallaxListView 添加setParallaxImage()方法

private ImageView headerImage; public void setParallaxImage(ImageView imageView){headerImage = imageView; }

MainActivity 調(diào)用ParallaxListView 的setParallaxImage()方法

protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);plv = (ParallaxListView) findViewById(R.id.plv);View headerView = View.inflate(this,R.layout.layout_header, null);final ImageView headerImage = (ImageView) headerView.findViewById(R.id.iv_header);//等view 的樹狀結(jié)構(gòu)渲染完畢時(shí),再將headerImage 設(shè)置到plv 中headerImage.getViewTreeObserver().addOnGlobalLayoutListener(newOnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {//寬高已經(jīng)測(cè)量完畢plv.setParallaxImage(headerImage);//移除監(jiān)聽,避免下次渲染時(shí)還調(diào)用headerImage.getViewTreeObserver().removeGlobalOnLayoutListener(this);}});//添加頭布局,需要在setAdapter 前添加plv.addHeaderView(headerView);plv.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, Cheeses.NAMES)); }

第7-18 行view 樹狀結(jié)構(gòu)渲染完畢時(shí),再將頭布局中ImageView 設(shè)置到ParallaxListView 中,這樣在
ParallaxListView 的setParallaxImage()方法中才能獲取到ImageView 的寬高
獲取頭部ImageView 的高度

private int orignalHeight; private int drawableHeight;public void setParallaxImage(ImageView imageView){headerImage = imageView;//ImageView 初始高度orignalHeight = imageView.getHeight();//圖片原始高度drawableHeight = imageView.getDrawable().getIntrinsicHeight(); }

頂部下拉時(shí)動(dòng)態(tài)設(shè)置頭部ImageView 的高度

/*** 滑動(dòng)到ListView 兩端才會(huì)調(diào)用*/ @Override protected boolean overScrollBy(int deltaX, int deltaY, int scrollX,int scrollY, int scrollRangeX, int scrollRangeY,int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {//deltaY 豎直方向滑動(dòng)的瞬時(shí)變化量,頂部下拉為-,底部上拉為+//scrollY 兩端滑動(dòng)超出的距離,頂部為-,底部為+//scrollRangeY 豎立方向滑動(dòng)的范圍//maxOverScrollY 豎立方向最大的滑動(dòng)位置//isTouchEvent 是否是用戶觸摸拉動(dòng),true 表示用戶手指觸摸拉動(dòng),false 表示慣性System.out.println("deltaY:" + deltaY + " scrollY:" + scrollY+ " scrollRangeY:" + scrollRangeY + " maxOverScrollY:"+ maxOverScrollY + " isTouchEvent:" + isTouchEvent);//頂部下拉,用戶觸摸時(shí),將deltaY 累加給Headerif(deltaY < 0 && isTouchEvent){int newHeight = headerImage.getHeight()+Math.abs(deltaY);//新高度小于圖片原始高度才允許累加變化量if(newHeight <= drawableHeight){//讓新的值生效headerImage.getLayoutParams().height = newHeight;headerImage.requestLayout();}}return super.overScrollBy(deltaX, deltaY, scrollX, scrollY,scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); }

第16-24 行動(dòng)態(tài)設(shè)置頭部ImageView 的高度

回彈動(dòng)畫

ParallaxListView 重寫onTouchEvent()方法

@Override public boolean onTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_UP://松手時(shí),把currentHeight 恢復(fù)到orignalHeightint currentHeight = headerImage.getHeight();//300->160 300,299,280,250,200,...160 隨時(shí)間生成300 到160 間的值ValueAnimator animator = ValueAnimator.ofInt(currentHeight,orignalHeight);animator.setDuration(500);//動(dòng)畫更新的監(jiān)聽animator.addUpdateListener(new AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {//獲取隨時(shí)間變化得到的currentHeight 到orignalHeight 間的值int value = (Integer) animation.getAnimatedValue();//讓新的值生效headerImage.getLayoutParams().height = value;headerImage.requestLayout();}});//設(shè)置插值器實(shí)現(xiàn)回彈效果animator.setInterpolator(new OvershootInterpolator(2));animator.start();break;default:break;}return super.onTouchEvent(ev); }

第8-23 行手指抬起時(shí),用屬性動(dòng)畫實(shí)現(xiàn)headerImage 恢復(fù)到初始高度

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的自定义控件:视差特效的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。