Android仿淘寶商品詳情頁(yè)
看到有人在問(wèn)如何實(shí)現(xiàn)淘寶商品詳情頁(yè)效果,獻(xiàn)上效果圖
大致梳理一下思路,這里不提供源碼
狀態(tài)欄透明使用開(kāi)源庫(kù)StatusBarCompat,為了兼容手機(jī)4.4
dependencies { compile ('com.github.niorgai:StatusBarCompat:2.1.4', { exclude group: 'com.android.support' }) } allprojects { repositories { ... maven { url "https://jitpack.io" } } }
標(biāo)題欄圖標(biāo)透明度變化參考Api setAlpha()已過(guò)時(shí)
icon.setImageAlpha(0);
Banner控件為ViewPager,淘寶顯示為正方形,這里需要修改ViewPager measure函數(shù)
public class IdeaViewPager extends ViewPager { private Point point; public IdeaViewPager(Context context) { this(context,null); } public IdeaViewPager(Context context, AttributeSet attrs) { super(context, attrs); WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); point = new Point(); windowManager.getDefaultDisplay().getSize(point); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(point.x,point.x); } }
測(cè)量View高度,獲取到高度集合綁定到ScrollView,根據(jù)ScrollView滑動(dòng)距離判斷是屬于哪一個(gè)Tab選項(xiàng)
public int getMeasureHeight(View view){ int width = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); int height = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); view.measure(width, height); return view.getMeasuredHeight(); }
重新onScrollChanged函數(shù),實(shí)現(xiàn)ViewPager滑動(dòng)速度比其他View慢
@Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (viewPager != null && t != oldt) { viewPager.setTranslationY(t/2); } }
根據(jù)限定距離(Banner)計(jì)算百分比偏移量,實(shí)現(xiàn)顏色漸變、透明度漸變(淘寶商品詳情頁(yè)有二次顏色漸變)
@Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if(viewPager!=null&&t<=point.x-headerHeight&&getOnScrollChangedColorListener()!=null){ getOnScrollChangedColorListener().onChanged(Math.abs(t)/Float.valueOf(point.x-headerHeight)); if(t<=(point.x-headerHeight)/2){ getOnScrollChangedColorListener().onChangedFirstColor(t/(point.x-headerHeight)/2); }else{ getOnScrollChangedColorListener().onChangedSecondColor((t-(point.x-headerHeight)/2)/(point.x-headerHeight)/2); } } int currentPosition = getCurrentPosition(t,arrayDistance); if(currentPosition!=position&&getOnSelectedIndicateChangedListener()!=null){ getOnSelectedIndicateChangedListener().onSelectedChanged(currentPosition); } this.position = currentPosition; }
單一顏色漸變透明度,還原argb通道,修改a值
ideaScrollView.setOnScrollChangedColorListener(new IdeaScrollView.OnScrollChangedColorListener() { @Override public void onChanged(float percentage) { int color = getAlphaColor(percentage>0.9f?1.0f:percentage); header.setBackgroundDrawable(new ColorDrawable(color)); radioGroup.setBackgroundDrawable(new ColorDrawable(color)); icon.setImageAlpha((int) ((percentage>0.9f?1.0f:percentage)*255)); radioGroup.setAlpha((percentage>0.9f?1.0f:percentage)*255); setRadioButtonTextColor(percentage); } @Override public void onChangedFirstColor(float percentage) { } @Override public void onChangedSecondColor(float percentage) { } }); ideaScrollView.setOnSelectedIndicateChangedListener(new IdeaScrollView.OnSelectedIndicateChangedListener() { @Override public void onSelectedChanged(int position) { isNeedScrollTo = false; radioGroup.check(radioGroup.getChildAt(position).getId()); isNeedScrollTo = true; } }); public int getAlphaColor(float f){ return Color.argb((int) (f*255),0x09,0xc1,0xf4); }
Tab選項(xiàng)屬性不能太頻繁,會(huì)有顏色值閃爍情況出現(xiàn),這里需要策略
public void setRadioButtonTextColor(float percentage){ if(Math.abs(percentage-currentPercentage)>=0.1f){ for(int i=0;i<radioGroup.getChildCount();i++){ RadioButton radioButton = (RadioButton) radioGroup.getChildAt(i); radioButton.setTextColor(radioButton.isChecked()?getRadioCheckedAlphaColor(percentage):getRadioAlphaColor(percentage)); } this.currentPercentage = percentage; } }
判斷當(dāng)前屬于哪個(gè)選項(xiàng),根據(jù)滑動(dòng)距離與傳入綁定的View高度集合來(lái)計(jì)算
private int getCurrentPosition(int t, ArrayList<Integer> arrayDistance) { int index = 0; for (int i=0;i<arrayDistance.size();i++){ if(i==arrayDistance.size()-1){ index = i; }else { if(t>=arrayDistance.get(i)&&t<arrayDistance.get(i+1)){ index = i; break; } } } return index; }
切換選項(xiàng)卡以及回到頂部按鈕的具體實(shí)現(xiàn)參考scrollTo函數(shù)
private void scrollToPosition(int position){ scrollTo(0,arrayDistance.get(position)); }
以上代碼實(shí)現(xiàn)了上圖效果,當(dāng)然也可以使用RecyclerView AbsListView做容器。
希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android開(kāi)發(fā)之HTTP訪問(wèn)網(wǎng)絡(luò)
這篇文章主要介紹了Android開(kāi)發(fā)之HTTP訪問(wèn)網(wǎng)絡(luò)的相關(guān)資料,需要的朋友可以參考下2016-07-07Android Universal ImageLoader 緩存圖片
Universal Image Loader for Android的目的是為了實(shí)現(xiàn)異步的網(wǎng)絡(luò)圖片加載、緩存及顯示,支持多線程異步加載,通過(guò)本文給大家介紹Android Universal ImageLoader緩存圖片相關(guān)資料,涉及到imageloader緩存圖片相關(guān)知識(shí),對(duì)imageloader緩存圖片相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)2016-01-01Android如何在root設(shè)備上開(kāi)啟ViewServer詳解
這篇文章主要給大家介紹了關(guān)于Android中如何在root設(shè)備上開(kāi)啟ViewServer的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)各位Android開(kāi)發(fā)者具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-12-12Android中使用TextView實(shí)現(xiàn)文字跑馬燈效果
本文主要介紹了Android中使用TextView實(shí)現(xiàn)文字走馬燈效果的方法解析。具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-04-04使用flutter的showModalBottomSheet遇到的坑及解決
這篇文章主要介紹了使用flutter的showModalBottomSheet遇到的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09Android 解決嵌套Fragment無(wú)法接收onCreateOptionsMenu事件的問(wèn)題
本文主要介紹Android Fragment無(wú)法接收onCreateOptionsMenu事件的問(wèn)題,這里給出解決辦法以及詳細(xì)代碼,希望能幫助有需要的小伙伴2016-07-07rxjava+retrofit實(shí)現(xiàn)多圖上傳實(shí)例代碼
本篇文章主要介紹了rxjava+retrofit實(shí)現(xiàn)多圖上傳實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06Android開(kāi)發(fā)AsmClassVisitorFactory使用詳解
這篇文章主要為大家介紹了Android開(kāi)發(fā)AsmClassVisitorFactory使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06