編輯:關於Android編程
先來看看最終的效果~~
嗯。。一個是頭像上移的 另一個是模仿UC浏覽器的。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPihQp6VgcaGjKcTjsrvKx8u1o6HT0Mj9v+61xMLwo6zU9cO01rvT0MG9v+6joaOho6GjoTwvcD4NCjxwPrK70qq8scLvoaOho6GjIMu1wcu007zytb3E0aOstdrSu7/uyse96cncuMXE7rXEwLKhozwvcD4NCjxwPrnY09pDb29yZGluYXRvckxheW91dKOs0tS8sM+1zbPUpMH0U2Nyb2xsQmVoYXZpb3LKudPDzfjJz9LUvLDT0LrctuDOxNXCPC9wPg0KPGgyIGlkPQ=="基礎概念">基礎概念
其實Behavior就是一個應用於View的觀察者模式,一個View跟隨者另一個View的變化而變化,或者說一個View監聽另一個View。
在Behavior中,被觀察View 也就是事件源被稱為denpendcy,而觀察View,則被稱為child。
首先在布局文件中跟布局設置為CoordinatorLayout,裡面放一個Button和一個TextView。
這裡我們在Activity中做一些手腳,讓Button動起來(不要在意坐標這些細節)
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_easy_behavior); findViewById(R.id.btn).setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_MOVE: v.setX(event.getRawX()-v.getWidth()/2); v.setY(event.getRawY()-v.getHeight()/2); break; } return false; } }); }
此時,Button已經可以跟隨手指移動了。
現在去自定義一個Behavior讓TextView跟隨Button一起動!
創建一個EasyBehavior類,繼承於Behavior
public class EasyBehavior extends CoordinatorLayout.Behavior{//這裡的泛型是child的類型,也就是觀察者View public EasyBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean layoutDependsOn(CoordinatorLayout parent, TextView child, View dependency) { //告知監聽的dependency是Button return dependency instanceof Button; } @Override //當 dependency(Button)變化的時候,可以對child(TextView)進行操作 public boolean onDependentViewChanged(CoordinatorLayout parent, TextView child, View dependency) { child.setX(dependency.getX()+200); child.setY(dependency.getY()+200); child.setText(dependency.getX()+","+dependency.getY()); return true; } }
注意兩個方法
layoutDependsOn() 代表尋找被觀察View
onDependentViewChanged() 被觀察View變化的時候回調用的方法
在onDependentViewChanged中,我們讓TextView跟隨Button的移動而移動。代碼比較簡單,一看就懂。
必須重寫帶雙參的構造器,因為從xml反射需要調用。
接下來,在xml中,給TextView設置我們的Behavior。
運行效果如下:
這樣一個最簡單的behavior就做好了。
這個效果布局嵌套比上一個例子些許復雜,如果看起來吃力,務必去補習CoordinatorLayout!!!!
先定義xml如下:
<framelayout android:background="@color/primary" android:id="@+id/frameLayout" android:layout_gravity="bottom|center_horizontal" android:layout_height="100dp" android:layout_width="match_parent" android:orientation="vertical" app:layout_collapsemode="parallax" app:layout_collapseparallaxmultiplier="0.3"> </framelayout>
有一點值得注意的是,app:layout_anchor=”@id/frameLayout”這個屬性,是附著的意思,這裡我用作給了toolbar,代表toolbar附著在了frameLayout之上。會跟隨frameLayout的scroll而變化Y的值。
如何實現折疊呢,下半部分不用管了,AppBarLayout已經幫我們做好了,我們只要標注相應的scrollflags即可,所以,如上的布局,不做任何處理的話,作為標題的TextView是一直顯示的,於是只要讓TextView跟隨Toolbar變化而變化就可以了。 接下來就創建一個Behavior類!
public class DrawerBehavior extends CoordinatorLayout.Behavior{ private int mFrameMaxHeight = 100; private int mStartY; @Override public boolean layoutDependsOn(CoordinatorLayout parent, TextView child, View dependency) { return dependency instanceof Toolbar; } public DrawerBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onDependentViewChanged(CoordinatorLayout parent, TextView child, View dependency) { } }
現在你應該可以很輕易的看懂這個Behavior的結構了。我們主要大展身手的地方其實是在onDependentViewChanged方法。
@Override public boolean onDependentViewChanged(CoordinatorLayout parent, TextView child, View dependency) { //記錄開始的Y坐標 也就是toolbar起始Y坐標 if(mStartY == 0) { mStartY = (int) dependency.getY(); } //計算toolbar從開始移動到最後的百分比 float percent = dependency.getY()/mStartY; //改變child的坐標(從消失,到可見) child.setY(child.getHeight()*(1-percent) - child.getHeight()); return true; }
裡面監聽了Toolbar的Y坐標變化,然後讓TextView的Y坐標也跟著變化。達到如預覽圖效果。
相信有了以上兩個例子,這個效果對你來說不難了,不就是讓imageView監聽Toolbar然後跟隨Toolbar的唯一變化而進行位移以及縮放麼。
所以具體的解析就不說了,直接上個Behavior代碼
/泛型為child類型 public class CustomBehavior extends CoordinatorLayout.Behavior{ private Context mContext; //頭像的最終大小 private float mCustomFinalHeight; //最終頭像的Y private float mFinalAvatarY; private float mStartAvatarY; private float mStartAvatarX; private int mAvatarMaxHeight; private BounceInterpolator interpolator = new BounceInterpolator(); public CustomBehavior(Context context, AttributeSet attrs) { mContext = context; if (attrs != null) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomBehavior); //獲取縮小以後的大小 mCustomFinalHeight = a.getDimension(R.styleable.CustomBehavior_finalHeight, 0); a.recycle(); } } // 如果dependency為Toolbar @Override public boolean layoutDependsOn(CoordinatorLayout parent, CircleImageView child, View dependency) { return dependency instanceof Toolbar; } //當dependency變化的時候調用 @Override public boolean onDependentViewChanged(CoordinatorLayout parent, CircleImageView child, View dependency) { //初始化屬性 //init(child, dependency); mFinalAvatarY = dependency.getHeight()/2; if(mStartAvatarY == 0){ mStartAvatarY = dependency.getY(); } if(mStartAvatarX == 0){ mStartAvatarX = child.getX(); } if(mAvatarMaxHeight == 0){ mAvatarMaxHeight = child.getHeight(); } //child.setY(dependency.getY()); //讓ImageView跟隨toolbar垂直移動 child.setY(dependency.getY()+dependency.getHeight()/2-mCustomFinalHeight/2); float percent = dependency.getY() / mStartAvatarY; //float x = mStartAvatarX*(1+percent); float x = mStartAvatarX * (1+ interpolator.getInterpolation(percent)); //Log.e("wing","started x "+ mStartAvatarX + " currentX "+ x); //當toolbar 達到了位置,就不改變了。 if(dependency.getY() > dependency.getHeight()/2) { child.setX(x); }else { child.setX(mStartAvatarX + ((mAvatarMaxHeight-mCustomFinalHeight))/2); } CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) child.getLayoutParams(); layoutParams.height = (int) ((mAvatarMaxHeight-mCustomFinalHeight) * percent + mCustomFinalHeight); layoutParams.width = (int) ((mAvatarMaxHeight-mCustomFinalHeight) * percent + mCustomFinalHeight); child.setLayoutParams(layoutParams); return true; } }
還是說說坐標計算相關的吧。舉個例子。如何讓ImageView處於Toolbar中心呢,我的代碼如下
//讓ImageView跟隨toolbar垂直移動 child.setY(dependency.getY()+dependency.getHeight()/2-mCustomFinalHeight/2);
為什麼是這樣? 上個圖就明白了
怎麼樣,不難吧,哈 喜歡的點個贊 給個star哦~~
項目地址 https://github.com/githubwing/CustomBehavior
1. SurfaceView的定義通常情況程序的View和用戶響應都是在同一個線程中處理的,這也是為什麼處理長時間事件(例如訪問網絡)需要放到另外的線程中去(防止阻塞當前
一.相關概念(一)基本概念Intent中文意思指”意圖”,按照Android的設計理念,Android使用Intent來封裝程序的”調
開源項目:Android-ObservableScrollView**項目依賴添加:compile ‘com.github.ksoichiro:android
Android系統較為龐大,要搞清楚系統運行原理需要長期努力。系統啟動部分看了幾遍但沒有總結,今天簡單總結一下。 Android首先重點是啟動zygote進程,這個進程來