編輯:關於Android編程
最關鍵的是onTouchEvent這個方法明天應該就會繼續介紹比這要更加多的於事件相關的,比如事件分發等,今天是簡單的事件,不多說,如下:
單指 4個動作 + x值 和 y 值
@Override public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event); }
重寫onTouchEvent就好了,這裡面有好幾個事件,准確說是一組事件分別是:
MotionEvent.ACTION_DOWN 手指按下 MotionEvent.ACTION_MOVE 手指移動 ACTION_UP 手指抬起 ACTION_CANCEL 取消,這裡看來和up沒什麼區別,和事件分發有關,這裡就不詳細講了,可能明天就學了(笑);以上就是簡單的介紹,接下來實現一個簡單的案例 簡單的畫畫板
package com.zhouzhou.flowlayoutdemo; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.util.TypedValue; import android.view.MotionEvent; import android.view.View; /** * Created by zhousaito on 2016/9/7. */ public class TouchView extends View { private Paint mPaint; private Path mPath; private float mLastX; private float mLastY; private int mPenColor; private int mPenSize; public TouchView(Context context) { this(context, null); } public TouchView(Context context, AttributeSet attrs) { this(context, attrs, R.style.MyDefStyle); } public TouchView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.TouchView, defStyleAttr, R.style.MyDefStyle); for (int i = 0; i < array.getIndexCount(); i++) { int index = array.getIndex(i); switch (index) { case R.styleable.TouchView_penColor: mPenColor = array.getColor(index, Color.RED); break; case R.styleable.TouchView_penSize: mPenSize = array.getDimensionPixelSize(index, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, getResources().getDisplayMetrics())); break; } } mPaint = new Paint(); mPath = new Path(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.WHITE); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(mPenSize); mPaint.setColor(mPenColor); //畫上線條 canvas.drawPath(mPath,mPaint); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mLastX = event.getX(); mLastY = event.getY(); mPath.moveTo(mLastX, mLastY); break; case MotionEvent.ACTION_MOVE: mPath.lineTo(event.getX(), event.getY()); mLastX = event.getX(); mLastY = event.getY(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: break; } //重寫繪制 invalidate(); return true; } }
這裡加了一些屬性和style
在 attrs.xml文件中定義<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;">
然後代碼引用上就好了,這樣,簡單的畫板就完成了,哈哈
接下來學一下 Matrix API 我沒怎麼搞懂,還是說一下吧,
用畫圖來解釋吧,Matrix 矩陣,有幾種方式
1.縮放,這個簡單,就要知道mMatrix.postScale(0.5f,0.5f,100,100);
前面是縮放比例,後面是旋轉中心點,不寫就是繞著父控件的左上角縮放
2.旋轉,mMatrix.postRotate(10,100,100); 和縮放差不多,
3.平移 mMatrix.postTranslate(10,10); 就是移動
4.傾斜 mMatrix.postSkew(0.1f,0);
上面4個屬性簡單,我就不寫了,網上一大堆,其實學屬性動畫時候就有學到這些,就傾斜沒有,然而這屬性並不常用,其實我想上gif 圖片的,感覺自己想傻吊一樣,這上gif,太占資源吧,4個屬性4個圖
event.getActionMasked(); 並不是event.getAction(),而是通過event.getActionMasked()這值來判斷,是否多手指的觸控的
MotionEvent.ACTION_POINTER_DOWN 按下
MotionEvent.ACTION_MOVE 移動(和單手指一樣的)
MotionEvent.ACTION_POINTER_UP 抬起
這樣就可以做對應的事情了,
**[0] 主要和單手指沖突時,可以根據event.getPointerCount()
來判斷多少個手指,然後做對應的事情**
今天是繼承ViewGroup來實現自定義控件
FlowLayout(流式布局) 其實很簡單,但是自己沒那麼有邏輯,先不廢話了
[1] TODO --> onLayout() -->裡面的值
[2] 用recycleView來實現一個流式布局
[3] 必須到onMeasure中寫 measureChildren(); 才可以顯示 不然不能顯示
第一步 繼承viewGroup
public class FlowLayout extends ViewGroup {
public FlowLayout(Context context) {
super(context);
}
public FlowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
繼承完之後,我們的目標是flowLayout 所以更具需求來寫
/**
* MeasureSpec.UNSPECIFIED
* --->子控件自己的大小來顯示,所以怎麼設置值都沒什麼用
* 二級緩存繪制
* [1] TODO --> onLayout() -->裡面的值
* [2] 用recycleView來實現一個流式布局
* [3] 必須到onMeasure中寫 measureChildren(); 才可以顯示 不然不能顯示
* @param changed
* @param l 父控件的位置
* @param t
* @param r
* @param b
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//流式布局 從左邊到右邊開始排
int left = l;
int maxHeight =0;
int top = t;
//總寬度
int width = r - l;
for (int i = 0; i < getChildCount(); i++) {
//得到子類控件
View view = getChildAt(i);
// Log.e("自定義標簽", "類名==FlowLayout" + "方法名==onLayout=====:" );
//
if (left + view.getMeasuredWidth() > width) {
top += maxHeight;
maxHeight=0;
left =l;
}
view.layout(left,top,left+view.getMeasuredWidth(),top+view.getMeasuredHeight());
left+=view.getMeasuredWidth();
maxHeight = Math.max(maxHeight, view.getMeasuredHeight());
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
/**
* 要寫這個才能顯示
*/
// measureChildren(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
measureChildren(widthMeasureSpec,heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
這樣大概實現了一下,因為沒有重寫onMeasure()方法,所以,flowLayout的寬和高不管用,都是滿上了父控件(可以說match_parent,因為表現是充滿的)
這樣的話,如果給 flowlayout 加一個padding的話,就看出來,我們的工程並沒有完成
先說好,布局是6個textView和6個機器人圖標交錯,就是幾行復制的,哈哈
就成這樣了,發現是自己沒有處理padding和margin
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int left = getPaddingLeft();
int maxHeight = 0;
int top = getPaddingTop();
int width = r - l - getPaddingLeft() - getPaddingRight();
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
if (left + view.getMeasuredWidth() > width) {
top += maxHeight;
maxHeight = 0;
left = getPaddingLeft();
}
view.layout(left + params.leftMargin,
top + params.topMargin,
left + params.leftMargin + view.getMeasuredWidth(),
top + params.topMargin + view.getMeasuredHeight());
left += view.getMeasuredWidth() + params.leftMargin + params.rightMargin;
maxHeight = Math.max(maxHeight, view.getMeasuredHeight() + params.topMargin + params.bottomMargin);
}
}
加了些padding的處理效果 (背景我去了,看著頭暈(笑))
接下來寫onMeasure() 方法,來決定 父控件自身的寬度,從而可以通過高和寬,來進行顯示,這樣,可以平常使用就差不多了,哈哈
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
/**
* 要寫這個才能顯示
*/
// measureChildren(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
measureChildren(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width = 0;
int height = 0;
//只要不是固定的 就
if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) {
int left = getPaddingLeft();
int maxHeight = 0;
int top = getPaddingTop();
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
//相加後,通過原來的
if (left + view.getMeasuredWidth() + params.rightMargin + params.leftMargin > widthSize - getPaddingRight()) {
top += maxHeight;
maxHeight = 0;
//在這裡得到的是left的,相當於這排排滿了的最大寬度
width = Math.max(width, left);
left = getPaddingLeft();
}
left += view.getMeasuredWidth() + params.rightMargin + params.leftMargin;
maxHeight = Math.max(maxHeight, view.getMeasuredHeight() + params.topMargin + params.bottomMargin);
}
height = maxHeight + top + getPaddingTop() + getPaddingBottom();
switch (widthMode) {
case MeasureSpec.AT_MOST:
width = Math.min(width,widthSize);
break;
case MeasureSpec.UNSPECIFIED:
width = widthSize;
break;
}
switch (heightMode) {
case MeasureSpec.AT_MOST:
//容器的高度
height = Math.min(heightSize, height);
break;
case MeasureSpec.UNSPECIFIED:
//容器的高度
height = heightSize;
break;
}
}else {
//固定的就用自己固定的高和寬
width =widthSize;
height = heightSize;
}
setMeasuredDimension(width, height);
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
寫完這些,哈哈,基本完成了,簡單的繼承了viewGroup然後,自己寫了一個簡單的容器,flowlayout,效果如下
結果,還是比較丑,哈哈
以上就今天的學習類容,哈哈,又寫了2 小時多,努力努力!!!
1、為什麼要有AIDL?為什麼要有AIDL呢,官方文檔介紹AIDL中有這麼一句話:Note: Using AIDL is necessary only ifyou all
在輸入框中輸入我們想要輸入的信息就會出現其他與其相關的提示信息,這種效果在Android中是用AutoCompleteTextView實現的。<AutoComple
在Android程序開發中,我們經常會去用到Shape這個東西去定義各種各樣的形狀,首先我們了解一下Shape下面有哪些標簽,都代表什麼意思: solid:填充 andr
github對應地址:https://github.com/hejunlin2013/TVSample,截至到當前發稿,已突破200star,如果喜歡的話,可以star,