Android仿小紅書(shū)歡迎界面
1,覺(jué)得小紅書(shū)的歡迎界面感覺(jué)很漂亮,就想來(lái)學(xué)習(xí)學(xué)習(xí)一下來(lái)實(shí)現(xiàn)類似于這種效果 。 原效果圖如下:
2,根據(jù)效果我們來(lái)一點(diǎn)點(diǎn)分析
第一步:首先看一下我們的主界面布局文件視圖效果如下:
main_activity.xml文件代碼如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@color/white" android:orientation="vertical" > <com.qianmo.xiaohongshuwelcome.parallaxpager.ParallaxContainer android:id="@+id/parallax_container" android:layout_width="match_parent" android:layout_height="match_parent"/> <ImageView android:id="@+id/iv_man" android:layout_width="67dp" android:layout_height="202dp" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="10dp" android:background="@drawable/intro_item_manrun_1" android:visibility="visible" /> </RelativeLayout>
可以看到我們主界面的布局文件主要是兩個(gè)控件,一個(gè)是包含上面小人行走效果的ImageView,然后是一個(gè)自定義ParallaxContainer控件,這個(gè)自定義控件的具體是什么我們先不要管,后面再和大家來(lái)慢慢解釋
第二步:看一下我們主界面的MainActivity的代碼
MainActivity.java
package com.qianmo.xiaohongshuwelcome; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.ImageView; import com.qianmo.xiaohongshuwelcome.parallaxpager.ParallaxContainer; /** * @author zhongdaxia 2014-12-15 */ public class MainActivity extends Activity { ImageView iv_man; ImageView rl_weibo; ParallaxContainer parallaxContainer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //獲取當(dāng)前窗體 final Window window = getWindow(); window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_main); /** * 動(dòng)畫(huà)支持11以上sdk,11以下默認(rèn)不顯示動(dòng)畫(huà) * 若需要支持11以下動(dòng)畫(huà),也可導(dǎo)入https://github.com/JakeWharton/NineOldAndroids */ if (android.os.Build.VERSION.SDK_INT > 10) { iv_man = (ImageView) findViewById(R.id.iv_man); parallaxContainer = (ParallaxContainer) findViewById(R.id.parallax_container); if (parallaxContainer != null) { parallaxContainer.setImage(iv_man); parallaxContainer.setLooping(false); iv_man.setVisibility(View.VISIBLE); parallaxContainer.setupChildren(getLayoutInflater(), R.layout.view_intro_1, R.layout.view_intro_2, R.layout.view_intro_3, R.layout.view_intro_4, R.layout.view_intro_5, R.layout.view_intro_6 ,R.layout.view_login); } } else{ setContentView(R.layout.view_login); } } }
我們看到代碼很簡(jiǎn)單,主要是這幾句有用的代碼:
if (parallaxContainer != null) { parallaxContainer.setImage(iv_man); parallaxContainer.setLooping(false); iv_man.setVisibility(View.VISIBLE); parallaxContainer.setupChildren(getLayoutInflater(), R.layout.view_intro_1, R.layout.view_intro_2, R.layout.view_intro_3, R.layout.view_intro_4, R.layout.view_intro_5, R.layout.view_intro_6 ,R.layout.view_login); }
① 將我們小人走路的那個(gè)ImageView添加到自定義控件ParallaxContainer中
② 將我們每一個(gè)的布局文件set到ParallaxContainer控件中去
這里給出R.layout.view_intro_1.xml文件代碼,其他的類似,就不給出來(lái)了(這里的x_in、x_out、y_in等屬性注意一下)
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ImageView android:id="@+id/iv_0" android:layout_width="103dp" android:layout_height="19dp" android:layout_centerInParent="true" android:src="@drawable/intro1_item_0" app:x_in="1.2" app:x_out="1.2" /> <ImageView android:id="@+id/iv_1" android:layout_width="181dp" android:layout_height="84dp" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginLeft="13dp" android:layout_marginTop="60dp" android:src="@drawable/intro1_item_1" app:x_in="0.8" app:x_out="0.8" /> <ImageView android:id="@+id/iv_2" android:layout_width="143dp" android:layout_height="58dp" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginTop="109dp" android:src="@drawable/intro1_item_2" app:x_in="1.1" app:x_out="1.1" /> <ImageView android:id="@+id/iv_3" android:layout_width="48dp" android:layout_height="48dp" android:src="@drawable/intro1_item_3" app:x_in="0.8" app:x_out="0.8" app:a_in="0.8" app:a_out="0.8" android:layout_below="@+id/iv_0" android:layout_toRightOf="@+id/iv_5" android:layout_toEndOf="@+id/iv_5" android:layout_marginLeft="21dp" android:layout_marginStart="21dp" android:layout_marginTop="12dp"/> <ImageView android:id="@+id/iv_4" android:layout_width="fill_parent" android:layout_height="128dp" android:layout_alignParentBottom="true" android:layout_marginBottom="29dp" android:background="@drawable/intro1_item_4" app:a_in="0.8" app:a_out="0.8" app:x_in="0.8" app:x_out="0.8" /> <ImageView android:id="@+id/iv_5" android:layout_width="260dp" android:layout_height="18dp" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_marginBottom="16dp" android:layout_marginLeft="15dp" android:src="@drawable/intro1_item_5" app:a_in="0.9" app:a_out="0.9" app:x_in="0.9" app:x_out="0.9" /> <ImageView android:id="@+id/iv_6" android:layout_width="24dp" android:layout_height="116dp" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_marginBottom="35dp" android:layout_marginLeft="46dp" android:src="@drawable/intro1_item_6" app:x_in="0.6" app:x_out="0.6" /> <ImageView android:id="@+id/iv_7" android:layout_width="45dp" android:layout_height="40dp" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_marginBottom="23dp" android:layout_marginLeft="76dp" android:src="@drawable/intro1_item_7" app:a_in="0.3" app:a_out="0.3" app:x_in="0.5" app:x_out="0.5" /> </RelativeLayout>
第三步:好了現(xiàn)在我們一定很好奇ParallaxContainer里面的內(nèi)容,那我們從上面的方法慢慢去看,首先看一下ParallaxContainer中的setImage()方法,代碼如下:
ImageView iv; //將小人圖片添加進(jìn)來(lái) public void setImage(ImageView iv) { this.iv = iv; }
貌似沒(méi)有什么,只是將它賦值給成員變量iv,我們接著看下一個(gè)setUpChildren()方法
//添加子view public void setupChildren(LayoutInflater inflater, int... childIds) { if (getChildCount() > 0) { throw new RuntimeException("setupChildren should only be called once when ParallaxContainer is empty"); } //創(chuàng)建打氣筒 ParallaxLayoutInflater parallaxLayoutInflater = new ParallaxLayoutInflater( inflater, getContext()); //將所有的view添加到本控件上去 for (int childId : childIds) { View view = parallaxLayoutInflater.inflate(childId, this); viewlist.add(view); } //添加視覺(jué)view pageCount = getChildCount(); for (int i = 0; i < pageCount; i++) { View view = getChildAt(i); addParallaxView(view, i); } //更新ViewPagerAdapter的數(shù)量 updateAdapterCount(); //創(chuàng)建viewpager viewPager = new ViewPager(getContext()); viewPager.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); viewPager.setId(R.id.parallax_pager); //給viewpager添加滑動(dòng)監(jiān)聽(tīng) attachOnPageChangeListener(); //設(shè)置適配器 viewPager.setAdapter(adapter); //將viewpager添加到主控件中 addView(viewPager, 0); }
讓我們一行行代碼慢慢分析
if (getChildCount() > 0) { throw new RuntimeException("setupChildren should only be called once when ParallaxContainer is empty"); }
//創(chuàng)建打氣筒 ParallaxLayoutInflater parallaxLayoutInflater = new ParallaxLayoutInflater( inflater, getContext());
首先看一下這段代碼只是if判斷是否已經(jīng)調(diào)用過(guò)setUpChildren()方法,沒(méi)什么重要的,在看創(chuàng)建ParallaxLayoutInflater打氣筒對(duì)象,我們來(lái)看看ParallaxLayoutInflater的具體代碼,沒(méi)什么重要的,只是里面有一個(gè)ParallaxFactory類我們沒(méi)見(jiàn)過(guò),留心一下!
package com.qianmo.xiaohongshuwelcome.parallaxpager; import android.content.Context; import android.view.LayoutInflater; public class ParallaxLayoutInflater extends LayoutInflater { protected ParallaxLayoutInflater(LayoutInflater original, Context newContext) { super(original, newContext); setUpLayoutFactory(); } private void setUpLayoutFactory() { if (!(getFactory() instanceof ParallaxFactory)) { setFactory(new ParallaxFactory(this, getFactory())); } } @Override public LayoutInflater cloneInContext(Context newContext) { return new ParallaxLayoutInflater(this, newContext); } }
再看下面一段代碼,主要是將所有的布局文件添加到viewList集合中去,并填充到我們的布局中,我們繼續(xù)往下看
//將所有的view添加到本控件上去 for (int childId : childIds) { View view = parallaxLayoutInflater.inflate(childId, this); viewlist.add(view); }
下面一段代碼主要是看拿到對(duì)應(yīng)所有的子view,關(guān)鍵是我們的addParallaxView()方法,具體代碼如下:
//添加視覺(jué)view pageCount = getChildCount(); for (int i = 0; i < pageCount; i++) { View view = getChildAt(i); addParallaxView(view, i); }
/** * 添加視覺(jué)view方法 * * @param view * @param pageIndex */ private void addParallaxView(View view, int pageIndex) { //通過(guò)遞歸方法拿到最小單元的view if (view instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) view; for (int i = 0, childCount = viewGroup.getChildCount(); i < childCount; i++) { addParallaxView(viewGroup.getChildAt(i), pageIndex); } } //創(chuàng)建視覺(jué)差view綁定,并添加到集合中去 ParallaxViewTag tag = (ParallaxViewTag) view.getTag(R.id.parallax_view_tag); if (tag != null) { tag.index = pageIndex; parallaxViews.add(view); } }
通過(guò)遞歸將每個(gè)布局文件中的最小單元view保存到parallaxView集合中去,但是等等,這里我們又發(fā)現(xiàn)了一個(gè)新的類ParallaxViewTag,讓我們來(lái)具體代碼
package com.qianmo.xiaohongshuwelcome.parallaxpager; public class ParallaxViewTag { //綁定每一個(gè)view對(duì)應(yīng)的是哪一個(gè)下標(biāo)的 protected int index; //x軸進(jìn)入的速度 protected float xIn; protected float xOut; protected float yIn; protected float yOut; protected float alphaIn; protected float alphaOut; }
貌似很簡(jiǎn)單,xIn、xOut貌似很熟悉和我們之前的布局文件屬性app:x_in等屬性對(duì)應(yīng)了, 這樣我們就懂了,這個(gè)類是相當(dāng)于一個(gè)tag類,用于記錄我們?cè)O(shè)置的特殊一些屬性,然是我們這里有一個(gè)疑問(wèn),下面這個(gè)代碼是get到tag,那我們是在哪里set里面的屬性呢?
ParallaxViewTag tag = (ParallaxViewTag) view.getTag(R.id.parallax_view_tag);
這時(shí)候我們要看看我們前面提到過(guò)的一個(gè)陌生類ParallaxFactory,看一下具體代碼
package com.qianmo.xiaohongshuwelcome.parallaxpager; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import com.qianmo.xiaohongshuwelcome.R; public class ParallaxFactory implements LayoutInflater.Factory { private final LayoutInflater.Factory factory; private ParallaxLayoutInflater mInflater; private static final String[] sClassPrefixList = { "android.widget.", "android.webkit.", "android.view." }; public ParallaxFactory(ParallaxLayoutInflater inflater, LayoutInflater.Factory factory) { mInflater = inflater; this.factory = factory; } @Override public View onCreateView(String name, Context context, AttributeSet attrs) { View view = null; if (context instanceof LayoutInflater.Factory) { view = ((LayoutInflater.Factory) context).onCreateView(name, context, attrs); } if (factory != null && view == null) { view = factory.onCreateView(name, context, attrs); } if (view == null) { view = createViewOrFailQuietly(name, context, attrs); } if (view != null) { onViewCreated(view, context, attrs); } return view; } protected View createViewOrFailQuietly(String name, Context context, AttributeSet attrs) { if (name.contains(".")) { return createViewOrFailQuietly(name, null, context, attrs); } for (final String prefix : sClassPrefixList) { final View view = createViewOrFailQuietly(name, prefix, context, attrs); if (view != null) { return view; } } return null; } protected View createViewOrFailQuietly(String name, String prefix, Context context, AttributeSet attrs) { try { return mInflater.createView(name, prefix, attrs); } catch (Exception ignore) { return null; } } /** * 主要是在viewCreated的時(shí)候?qū)ag和view綁定起來(lái) * * @param view * @param context * @param attrs */ protected void onViewCreated(View view, Context context, AttributeSet attrs) { int[] attrIds = {R.attr.a_in, R.attr.a_out, R.attr.x_in, R.attr.x_out, R.attr.y_in, R.attr.y_out,}; TypedArray a = context.obtainStyledAttributes(attrs, attrIds); if (a != null) { if (a.length() > 0) { ParallaxViewTag tag = new ParallaxViewTag(); tag.alphaIn = a.getFloat(0, 0f); tag.alphaOut = a.getFloat(1, 0f); tag.xIn = a.getFloat(2, 0f); tag.xOut = a.getFloat(3, 0f); tag.yIn = a.getFloat(4, 0f); tag.yOut = a.getFloat(5, 0f); view.setTag(R.id.parallax_view_tag, tag); } a.recycle(); } } }
主要看onViewCreated()方法,可以看到,這里我們將對(duì)應(yīng)的每個(gè)屬性的值都set到了我們ParallaxViewTag中,我們接著看下面的代碼,調(diào)用updateAdapterCount()方法讓適配器去更新adapter的數(shù)量,這里我們可以看到適配器是繼承PagerAdapter類,用于ViewPager的適配器,這里使用LinkedList來(lái)存儲(chǔ)View,這個(gè)方法很好,贊一下
//更新ViewPagerAdapter的數(shù)量 updateAdapterCount(); //具體代碼 //被調(diào)用的時(shí)候好像是0 private void updateAdapterCount() { adapter.setCount(isLooping ? Integer.MAX_VALUE : pageCount); } //下面是adapter的具體代碼 package com.qianmo.xiaohongshuwelcome.parallaxpager; import android.content.Context; import android.support.v4.view.PagerAdapter; import android.view.View; import android.view.ViewGroup; import java.util.LinkedList; import static android.view.ViewGroup.LayoutParams; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; public class ParallaxPagerAdapter extends PagerAdapter { private int count = 0; private final Context context; private final LinkedList<View> recycleBin = new LinkedList<View>(); public ParallaxPagerAdapter(Context context) { this.context = context; } public void setCount(int count) { this.count = count; } @Override public int getCount() { return count; } @Override public Object instantiateItem(ViewGroup container, int position) { View view; if (!recycleBin.isEmpty()) { view = recycleBin.pop(); } else { view = new View(context); view.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT)); } container.addView(view); return view; } @Override public void destroyItem(ViewGroup container, int position, Object object) { View view = (View) object; container.removeView(view); recycleBin.push(view); } @Override public boolean isViewFromObject(View view, Object object) { return view.equals(object); } }
我們繼續(xù)往下看,后面的就是創(chuàng)建viewpager對(duì)象,并addview到主控件上,在attachOnPagerChangeListener()方法中添加viewpager的滑動(dòng)監(jiān)聽(tīng)
/創(chuàng)建viewpager viewPager = new ViewPager(getContext()); viewPager.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); viewPager.setId(R.id.parallax_pager); //給viewpager添加滑動(dòng)監(jiān)聽(tīng) attachOnPageChangeListener(); //設(shè)置適配器 viewPager.setAdapter(adapter); //將viewpager添加到主控件中 addView(viewPager, 0);
這里我們?cè)趏nPageScrollStateChanged()方法判斷是否開(kāi)啟下面小人行走的動(dòng)畫(huà),通過(guò)onPageScrolled()方法監(jiān)聽(tīng)滑動(dòng)的具體偏移量,通過(guò)view.setTranslationX()方法來(lái)改變對(duì)應(yīng)的屬性
protected void attachOnPageChangeListener() { mCommonPageChangeListener = new ViewPager.OnPageChangeListener() { /** * 此方法是在狀態(tài)改變的時(shí)候調(diào)用,其中arg0這個(gè)參數(shù) 有三種狀態(tài)(0,1,2)。arg0 ==1的時(shí)辰默示正在滑動(dòng),arg0==2的時(shí)辰默示滑動(dòng)完畢了,arg0==0的時(shí)辰默示什么都沒(méi)做。 * @param state */ @Override public void onPageScrollStateChanged(int state) { Log.v(TAG, "onPageScrollStateChanged" + state); iv.setBackgroundResource(R.drawable.man_run); final AnimationDrawable animationDrawable = (AnimationDrawable) iv.getBackground(); switch (state) { case 0: //處于展示階段 finishAnim(animationDrawable); break; case 1: //正在滑動(dòng) isEnd = false; animationDrawable.start(); break; case 2: //滑動(dòng)完畢 finishAnim(animationDrawable); break; } } //判斷是否還是在左邊 boolean isleft = false; /** * onPageScrolled(int arg0,float arg1,int arg2) ,當(dāng)頁(yè)面在滑動(dòng)的時(shí)候會(huì)調(diào)用此方法,在滑動(dòng)被停止之前,此方法回一直得到調(diào)用。其中三個(gè)參數(shù)的含義分別為: * @param pageIndex 當(dāng)前頁(yè)面,及你點(diǎn)擊滑動(dòng)的頁(yè)面 * @param offset 當(dāng)前頁(yè)面偏移的百分比 * @param offsetPixels 當(dāng)前頁(yè)面偏移的像素位置 */ @Override public void onPageScrolled(int pageIndex, float offset, int offsetPixels) { // Log.v(TAG, "onPageScrolled" + pageIndex + " offset" + offset + " offsetPixels" + offsetPixels); if (offsetPixels < 10) { isleft = false; } if (pageCount > 0) { pageIndex = pageIndex % pageCount; } if (pageIndex == 3) { if (isleft) { } else { iv.setX(iv.getLeft() - offsetPixels); } } ParallaxViewTag tag; for (View view : parallaxViews) { tag = (ParallaxViewTag) view.getTag(R.id.parallax_view_tag); if (tag == null) { continue; } if ((pageIndex == tag.index - 1 || (isLooping && (pageIndex == tag.index - 1 + pageCount))) && containerWidth != 0) { // make visible view.setVisibility(VISIBLE); // slide in from right view.setTranslationX((containerWidth - offsetPixels) * tag.xIn); // slide in from top view.setTranslationY(0 - (containerWidth - offsetPixels) * tag.yIn); // fade in view.setAlpha(1.0f - (containerWidth - offsetPixels) * tag.alphaIn / containerWidth); } else if (pageIndex == tag.index) { // make visible view.setVisibility(VISIBLE); // slide out to left view.setTranslationX(0 - offsetPixels * tag.xOut); // slide out to top view.setTranslationY(0 - offsetPixels * tag.yOut); // fade out view.setAlpha(1.0f - offsetPixels * tag.alphaOut / containerWidth); } else { view.setVisibility(GONE); } } } @Override public void onPageSelected(int position) { Log.v(TAG, "onPageSelected" + position); currentPosition = position; } }; viewPager.setOnPageChangeListener(mCommonPageChangeListener); }
4,這里基本上就把源碼分析完了,so,既然分析完別人的源碼了下面就是結(jié)合到自己項(xiàng)目中去用了,當(dāng)我們,想要實(shí)現(xiàn)一個(gè)翻頁(yè)從頂部斜飛入的view,那我們的布局文件代碼可以如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@color/transparent"> <ImageView android:id="@+id/iv_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginLeft="133dp" android:layout_marginTop="39dp" android:src="@drawable/ic_launcher" app:x_in="1" app:x_out="1" app:y_in="0.6" app:y_out="0.9"/> <ImageView android:id="@+id/iv_11" android:layout_width="44dp" android:layout_height="47dp" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="66dp" android:layout_marginLeft="140dp" android:src="@drawable/ic_launcher" app:x_in="1" app:x_out="1" app:y_in="-1.3" app:y_out="-1.3"/> </RelativeLayout>
來(lái)看一下我們的效果:
這是Github下載地址,由于要源碼的同學(xué)可以去下載一下,See You Next Time !?。?/p>
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!
相關(guān)文章
Android 新手引導(dǎo)蒙層效果實(shí)現(xiàn)代碼示例
本篇文章主要介紹了Android 新手引導(dǎo)蒙層效果實(shí)現(xiàn)代碼示例,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-01-01android實(shí)現(xiàn)音樂(lè)播放器進(jìn)度條效果
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)音樂(lè)播放器進(jìn)度條效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04android特賣列表倒計(jì)時(shí)卡頓問(wèn)題的解決方法
這篇文章主要為大家詳細(xì)介紹了android特賣列表倒計(jì)時(shí)卡頓問(wèn)題的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09Android EditText限制輸入整數(shù)和小數(shù)的位數(shù)的方法示例
這篇文章主要介紹了Android EditText限制輸入整數(shù)和小數(shù)的位數(shù)的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08Android中SurfaceView和普通view的區(qū)別及使用
SurfaceView第一印象它是一個(gè)view,因?yàn)樗^承了View,本文主要介紹了SurfaceView和普通view的區(qū)別及使用,感興趣的小伙伴們可以參考一下2021-06-06Android程序開(kāi)發(fā)通過(guò)HttpURLConnection上傳文件到服務(wù)器
這篇文章主要介紹了Android程序開(kāi)發(fā)通過(guò)HttpURLConnection上傳文件到服務(wù)器的相關(guān)資料,需要的朋友可以參考下2016-01-01Android?MaterialButton使用實(shí)例詳解(告別shape、selector)
我們平時(shí)寫(xiě)布局,當(dāng)遇到按鈕需要圓角、或者描邊等,通常的方法是新建一個(gè)xml文件,在shape標(biāo)簽下寫(xiě),然后通過(guò)android:background或setBackground(drawable)設(shè)置,這篇文章主要給大家介紹了關(guān)于Android?MaterialButton使用詳解的相關(guān)資料,需要的朋友可以參考下2022-09-09Android日期選擇器實(shí)現(xiàn)年月日三級(jí)聯(lián)動(dòng)
這篇文章主要為大家詳細(xì)介紹了Android日期選擇器實(shí)現(xiàn)年月日三級(jí)聯(lián)動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01Android View添加 Listener 實(shí)例代碼
在開(kāi)發(fā)中為控件添加Listener是非常常見(jiàn)的工作,最簡(jiǎn)單的添加Listener方式可以這樣2013-05-05