導航:首頁 > 源碼編譯 > android的自定義控制項源碼

android的自定義控制項源碼

發布時間:2023-01-12 22:29:30

android自定義控制項總結

每個view的坐標系原點為左上角那個點,水平方向為x軸,右正左負,豎直方向為y軸,下正上負。

canvas.drawColor //繪制區域塗上顏色(設置底色/蒙層)

canvas.drawCircle(float centerX(圓心X坐標),float centerY(圓心Y坐標),float radius(圓的半徑,單位像素),Paint paint)

canvas.drawBitmap

canvas.drawRect(float left,float top,float right,float bottom,Paint paint) //畫矩形

canvas.drawRect(RecF rect,Paint paint)

canvas.drawRect(Rect rect,Paint paint)

canvas.drawPoint(float x(點X軸坐標),float y(點Y軸坐標),Paint paint)//畫點

點的大小 ->paint.setStrokeWidth(width)

點的形狀 ->paint.setStrokeCap(cap)

ROUND(圓形),BUTT(平頭),SQUARE(方頭)

canvas.drawPoints()//批量畫點

canvas.drawOval(float left(左邊界點),float top(上邊界點),float right(右邊界點),float bottom(下邊界點),Paint paint) //畫橢圓

canvas.drawLine(float startX(起點X軸坐標),float startY(起點Y軸坐標),float stopX(終點X軸坐標),float stopY(終點X軸坐標),Paint paint) (setStyle對直線沒有影響)

canvas.drawLines(批量畫線)

canvas.drawRoundRect(float left,float top,float right,float bottom,float rx(圓角的橫向半徑),float ry(圓角的縱向坐標),Paint paint)//畫圓角矩形

canvas.drawRoundRect(RectF rect,float rx, float ry,Paint paint)

canvas.drawArc(float left, float top, float right, float bottom, float startAngle(起始角度,順時針為正,逆時針為負), float sweepAngle(弧形劃過角度), boolean useCenter(是否連接到圓心), Paint paint) //繪制弧形或扇形 根據弧形所在橢圓進行繪制

canvas.drawPath() //通過描述路徑的方式來繪制圖形

path.addXxx() —添加子圖形

path.addCircle(x,y,radius,dir(路徑方向:順時針/逆時針))

path.xxxTo —畫線

path.lineTo()

path.rLineTo()

path.close() —封閉當前圖形

path.setFillType(Path.FillType ft) //設置填充模式

canvas.drawBitmap(Bitmap bitmap,float left,float top,Paint paint);//畫bitmap

canvas.drawBitmap(Bitmap bitmap,Rect src,RectF dst,Paint paint)

canvas.drawBitmap(Bitmap bitmap,Rect src,Rect dst,Paint paint)

canvas.drawBitmap(Bitmap bitmap,Matrix matrix,Paint paint)

canvas.drawText(String text,float x(起點x坐標),float y(起點y坐標),Paint paint) //繪制文字

Paint.setStyle //設置繪制模式

FILL 填充模式(默認)

STROKE 畫線模式

FILL_AND_STROKE 既畫線又填充

Paint.setStrokeWidth //設置線條寬度 (僅在style:Stroke、FILL_AND_STROLE下有效)

Paint.setTextSize //設置文字大小

Paint.setAntiAlias //設置抗鋸齒開關

Paint.setTextSize(float textSize)//設置文字大小

Paint.setStrokeJoin(Paint.Join join) //設置拐角的形狀

MITER//尖角(默認)

BEVEL//平角

ROUND//圓角

Paint.setStokeMiter(float miter)//設置MITER型拐角的延長線的最大值

設置顏色

直接設置顏色

Paint.setColor(int color)

Paint.setARGB(int a,int r,int g,int b)

Paint.setShader(Shader shader) //設置shader

LinearGradient 線性漸變

RadialGradient 輻射漸變

SweepGradient 掃描漸變

BitmapShader 用bitmap的像素來作為圖形或文字的填充

ComposeShader 混合著色器,多個shader混合使用

Paint.setColorFilter(ColorFilter colorFilter) //設置顏色過濾

Paint.setXfermode(Xfermode xfermode) //以要繪制的內容為源圖像,以View中已有內容作為目標圖像,選取一個PorterDuff.Mode作為繪制內容的顏色處理方案。

色彩優化

Paint.setDither(boolean dither) //設置抖動來優化色彩深度降低時的繪制效果

Paint.setFilterBitmap(boolean filter) //設置雙線性過濾優化Bitmap放大繪制的效果

可以理解為 由馬賽克變成模糊狀態

Paint.setPathEffect(PathEffect effect)//使用PathEffect設置形狀的輪廓效果

CornerPathEffect//把所有的拐角變成圓角

DiscretePathEffect//把線條進行隨機的偏離

DashPathEffect//使用虛線

PathDashPathEffect//使用一個Path來繪制虛線

SumPathEffect//組合效果

ComposePathEffect//組合效果,組合有先後順序

Paint.setShadowLayer(float radius,float dx,float dy,int shadowColor)//添加陰影

Paint.setMaskFilter(MaskFilter maskfilter)//在繪制層上方的附加效果

BlurMaskFilter //模糊效果

new BlurMaskFilter(float radius(模糊范圍),BlurMaskFilter.Blur style(模糊類型))

EmbossMaskFilter//浮雕效果

new EmbossMaskFilter(float[] direction(光源的方向),float ambient(環境光強度),float specular(炫光系數),float blurRadius(光線范圍))

獲取繪制的Path

getFillPath(Path src,Path dst)//實際path

getTextPath(Stirng text,int start,int end,float x,float y,Path)/getTextPath(char[] text,int index,int count,float x,float y,Path path)//文字的path

drawTextOnPath()//沿一條Path來繪制文字

StaticLayout //繪制文字,支持換行

paint.setFakeBoldText(booleab fakeBoldText)//是否使用偽粗體

paint.setStrikeThruText()//是否加刪除線

paint.setUnderLineText(boolean underlineText)//是否加下劃線

paint.setTextSkewX(float skewX)//設置文字橫向錯切角度

paint.setTextScaleX(float scaleX)//設置文字橫向放縮

paint.setLetterSpacing(float letterSpacing)//設置字元間距,默認為0

paint.setTextAlign(Paint.Align align)//LEFT、CENTER、RIGHT默認為LEFT

paint.setTextLocale(Locale locale)/paint.setTextLocales(LocaleList locales) //設置繪制所用的地域

paint.setHinting(int mode)//是否啟用字體微調

測量文字尺寸類:

paint.getFontSpacing();//獲取推薦的行距

paint.getFontMetrics();//獲取point的FontMetrics

baseline:基準線

ascent/descent:普通字元的頂部和底部范圍

top/bottom:限制字型的頂部和底部

leading:行的額外間距,即上一行字的bottm與下一行字的top距離

paint.getTextBounds(String text(測量的文字),int start(文字的起始位置),int end(文字的結束位置),Rect bounds(文字顯示範圍的對象))//獲取文字的顯示範圍

paint.measureText(String text)//測量文字佔用的寬度

measureText()>getTextBounds()

paint.getTextWidths(String text,float[] widths)//獲取字元串中每個字元的寬度,並把結果填入參數widths

paint.breakText(String text((要測量的文字),boolean measureForwards(測量的方向),float maxWidth(寬度上限(超出上限會截斷文字)),float[] measuredWidth(用於接受數據))//測量完成後會把文字寬度賦給measureWidth[0]

paint.getRunAdvance(CharSequence text,int start(文字的起始坐標),int end(文字的結束坐標),int contextStart(上下文的起始坐標),int ContextEnd(上下文的結束坐標),boolean isRtl(文字的方向),int offset(字數的偏移))//計算某個字元處游標的x坐標

paint.getOffsetForAdvance(CharSequence text, int start, int end, int contextStart, int contextEnd, boolean isRtl, float advance)//計算出文字中最接近這個位置的字元偏移量

paint.hasGlyph(String s)//檢查指定的字元串是否是一個單獨的字型

canvas.clipRect()//范圍裁剪

canvas.clipPath()//根據范圍裁剪

canvas.translate(float dx,float dy)//位移

canvas.rotate(float degrees,float px,float py)//旋轉

canvas.scale(float sx(橫向縮放倍數),float sy(縱向縮放倍數),float px,float py)//縮放

canvas.skew(float sx(x軸的錯切系數),float sy(y軸的錯切系數))//錯切

canvas.setMatrix(matrix)//用Matrix直接替換Canvas當前的變換矩陣

canvas.concat(matrix)//用Canvas當前的變換矩陣和Matrix相乘

Camera.rotate*()//三維旋轉

1、super.draw()//總調度方法

2、super.onDraw()

3、dispatchDraw()//繪制子View的方法

繪制順序:

draw()總調度方法,view的繪制過程都發生在draw()方法里

1、背景(drawBackground()不能重寫)-------android:background:/View.setBackgroundXxx()

2、主體(onDraw())

3、子View(dispatchDraw())

4、滑動邊緣漸變和滑動條(onDrawForeground())-------android:scrollbarXxx/View.setXXXScrollBarXXX()

5、前景(onDrawForeground())-------android:foreground/View.setForeground()

view.animate().translationX()//x軸偏移

1、如果是自定義控制項,需要添加setter、getter方法

2、ObjectAnimator.ofXXX()創建ObjectAnimator對象

3、用start()方法執行動畫

setDuration(int ration)//設置動畫時長

setInterpolator(Interpolator interpolator)//設置插值器

ViewPropertyAnimator.setListener()/ObjectAnimator.addListener()

ViewPropertyAnimator.setUpdateListener()/ObjectAnimator.addUpdateListener()

ObjectAnimator.addPauseListener()

ViewPropertyAnimator.withStartAction/EndAction()

ArgbEvaluator//顏色漸變動畫

PropertyValuesHolder//同一個動畫中改變多個屬性

PropertyValuesHolders.ofKeyframe()//把同一個屬性拆分

AnimatorSet//多個動畫配合執行

targetSdkVersion>=14,硬體加速默認開啟

view.setLayerType()

LAYER_TYPE_SOFTWARE:使用軟體來繪制View Layer,繪制到Bitmap,並順便關閉硬體加速

LAYER_TYPE_HARDWARE:使用GPU來繪制View Layer,繪制到OpenGL texture(如果硬體加速關閉,那麼行為和LAYER_TYPE_SOFTWARE一致)

LAYER_TYPE_NONE:關閉View Layer

View Layer可以加速無invalidate()(例如動畫)時的刷新效率,但對於需要調用invalidate()的刷新無法加速

硬體加速並不支持所有的繪制操作

1、測量(measure)

View:View在onMeasuer中會計算自己的尺寸然後保存

ViewGroup:ViewGroup在onMeasure中會調用所有子View的measure讓它們進行自我測量,並根據子View

計算出的期望尺寸來計算他們的事跡尺寸和位置然後保存。

2、布局(layout)

View:無子View所以onLayout不做任何處理

ViewGroup:ViewGroup在onLayout中會調用自己所有子View的layout方法,把他們的尺寸、位置傳給他們, 讓他們完成自我布局。

MeasureSpec = mode + size :父類傳遞過來給當前View的一個建議值

MeasureSpec.getMode(int spec)//獲取模式

MeasureSpec.getSize(int spec)//獲取數值

限制分類:

UNSPECIFIED(不限制)

AT_MOST(限制上限)->wrap_content

EXACTLY(限制固定值)->match_parent/具體值

1、重寫onMeasure來修改已有的View尺寸

(1)、重寫onMeasure方法,調用super.onMeasure觸發原有的自我測量。

(2)、在super.onMeasure下用getMeasureWidth與getMeasureHeigh獲取之前測量的結果,使用自己的演算法計算新結果。

(3)、調用setMeasureDimension保存新結果。

2、重寫onMeasure來全新定製自定義View的尺寸

與1區別,保證計算的同時,保證結果滿足父View給出的尺寸限制

(1)重寫onMeasure,計算出View的尺寸

(2)使用resolve讓子View的計算結果符合父View的限制,也可不使用該方法自己定義

3、重寫onMeasure和onLayout來全新定製自定義ViewGroup的內部布局

兩個注意點:

子控制項間的margin值

1、重寫generateLayoutParams()和generateDefaultLayoutParams()

2、獲取margin值 MarginLayoutParams lp = (MarginLayoutParams )child.getLayoutParams()

子控制項間的padding值

1、測量後直接getPaddingLeft、getPaddingTop、getPaddingRight、getPaddingBottom

重寫onMeasure來計算內部布局

(1)調用每個子View的measure來計運算元View的尺寸

結合layout_xxx和自己可用空間

(2)計運算元View的位置並保存子View的尺寸和位置

(3)計算自己的尺寸並用setMeasureDimension保存

重寫onLayout來擺放子View

(1)調用每個子View的layout,讓他們保存自己的位置和尺寸

view工作原理

觸摸事件

1、ACTION_DOWN:手指剛接觸屏幕,按下去的那一瞬間

2、ACTION_MOVE:手指在屏幕上移動

3、ACTION_UP:手指從屏幕上松開的瞬間

事件序列:從ACTION_DOWN -> ACTION_UP

ViewGroup:
DispatchTouchEvent
• return true:表示該View內部消化掉了所有事件
• return false:表示事件在本層不再繼續進行分發,並交由上層控制項的onTouchEvent方法進行消費
• return super.dispatchTouchEvent(ev):默認事件將分發給本層的事件攔截onInterceptTouchEvent方法 進行處理
OnInterceptTouchEvent
• return true:表示將事件進行攔截,並將攔截到的事件交由本層控制項的onTouchEvent進行處理
• return false:表示不對事件進行攔截,事件得以成功分發到子View
• return super.onInterceptTouchEvent(ev):默認表示不攔截該事件,並將事件傳遞給下一層View的 dispatchTouchEvent
OnTouchEvent 默認false
• return true:表示onTouchEvent處理完事件後消費了此次事件
• return fasle:表示不響應事件,那麼該事件將會不斷向上層View的onTouchEvent方法傳遞,直到某個View的 onTouchEvent方法返回true
• return super.dispatchTouchEvent(ev):表示不響應事件,結果與return false一樣
子View不存在分發:
• DispatchTouchEvent 事件分發
• OnTouchEvent 默認true

如下圖為事件分發流程圖:

---------------------- 以上總結部分源自Hencoder教程 ------------------------------

❷ Android 紅包雨效果自定義控制項

思路:利用Path繪制動畫軌跡,再使用PathMeasure獲取軌跡中的坐標位置實時改變view的坐標完成紅包動畫。

封裝一個紅包容器view用於管理大量紅包view的顯示、動畫、消失、回收利用

單個紅包view動畫軌跡設置

適配器:用於定義紅包view的樣式、軌跡路線、動畫屬性、數據

使用方式,在布局中添加view

在界面中定義適配器,添加紅包數據

源碼地址: https://github.com/LucasDevelop/CustomView 。中的(Falling)部分

❸ 如何打造Android自定義的下拉列表框控制項

一、概述
Android中的有個原生的下拉列表控制項Spinner,但是這個控制項有時候不符合我們自己的要求,
比如有時候我們需要類似windows 或者web網頁中常見的那種下拉列表控制項,類似下圖這樣的:

這個時候只有自己動手寫一個了。其實實現起來不算很難,
本文實現的方案是採用TextView +ImageView+PopupWindow的組合方案。
先來看看我們的自己寫的控制項效果圖吧:(源碼在文章下面最後給出哈!)

二、自定義下拉列表框控制項的實現
1. 自定義控制項用到的布局文件和資源:
結果框的布局頁面:dropdownlist_view.xml:
<?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"
android:orientation="horizontal"
android:id="@+id/compound"
android:background="@drawable/dropdown_bg_selector" >

<TextView
android:id="@+id/text"
android:layout_width="250dp"
android:layout_height="40dp"
android:paddingLeft="10dp"
android:text="文本文字"
android:gravity="center_vertical"
android:textSize="14sp"
android:padding="5dp"
android:singleLine="true" />
<ImageView
android:id="@+id/btn"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_toRightOf="@+id/text"
android:src="@drawable/dropdown"
android:padding="5dp"
android:layout_centerVertical="true"
android:gravity="center"/>
</RelativeLayout>

下拉彈窗列表布局頁面:dropdownlist_popupwindow.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<ListView
android:id="@+id/listView"
android:layout_width="280dp"
android:layout_height="wrap_content"
android:divider="#666666"
android:dividerHeight="1dp"
></ListView>

</LinearLayout>

selector資源文件:
dropdown_list_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@color/dropdownlist_item_press"/>
<item android:drawable="@color/dropdownlist_item"/>
</selector>

dropdown_bg_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@color/dropdownlist_press"/>
<item android:drawable="@color/dropdownlist_bg"/>
</selector>

2. 自定義下拉列表框控制項類的實現:
我們採用了TextView+ImageView+PopupWindow的組合方案,所以我的自定義控制項需要重寫ViewGroup,由於我們已經知道了,布局方向為豎直方向,所以這里,
我直接繼承LinearLayout來寫這個控制項。具體實現代碼如下:
package com.czm.xcdropdownlistview;

import java.util.ArrayList;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;

@SuppressLint("NewApi")
/**
* 下拉列表框控制項
* @author caiming
*
*/
public class XCDropDownListView extends LinearLayout{

private TextView editText;
private ImageView imageView;
private PopupWindow popupWindow = null;
private ArrayList<String> dataList = new ArrayList<String>();
private View mView;
public XCDropDownListView(Context context) {
this(context,null);
// TODO Auto-generated constructor stub
}
public XCDropDownListView(Context context, AttributeSet attrs) {
this(context, attrs,0);
// TODO Auto-generated constructor stub
}
public XCDropDownListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
initView();
}

public void initView(){
String infServie = Context.LAYOUT_INFLATER_SERVICE;
LayoutInflater layoutInflater;
layoutInflater = (LayoutInflater) getContext().getSystemService(infServie);
View view = layoutInflater.inflate(R.layout.dropdownlist_view, this,true);
editText= (TextView)findViewById(R.id.text);
imageView = (ImageView)findViewById(R.id.btn);
this.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(popupWindow == null ){
showPopWindow();
}else{
closePopWindow();
}
}
});
}
/**
* 打開下拉列表彈窗
*/
private void showPopWindow() {
// 載入popupWindow的布局文件
String infServie = Context.LAYOUT_INFLATER_SERVICE;
LayoutInflater layoutInflater;
layoutInflater = (LayoutInflater) getContext().getSystemService(infServie);
View contentView = layoutInflater.inflate(R.layout.dropdownlist_popupwindow, null,false);
ListView listView = (ListView)contentView.findViewById(R.id.listView);

listView.setAdapter(new XCDropDownListAdapter(getContext(), dataList));
popupWindow = new PopupWindow(contentView,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
popupWindow.setBackgroundDrawable(getResources().getDrawable(R.color.transparent));
popupWindow.setOutsideTouchable(true);
popupWindow.showAsDropDown(this);
}
/**
* 關閉下拉列表彈窗
*/
private void closePopWindow(){
popupWindow.dismiss();
popupWindow = null;
}
/**
* 設置數據
* @param list
*/
public void setItemsData(ArrayList<String> list){
dataList = list;
editText.setText(list.get(0).toString());
}
/**
* 數據適配器
* @author caiming
*
*/
class XCDropDownListAdapter extends BaseAdapter{

Context mContext;
ArrayList<String> mData;
LayoutInflater inflater;
public XCDropDownListAdapter(Context ctx,ArrayList<String> data){
mContext = ctx;
mData = data;
inflater = LayoutInflater.from(mContext);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return mData.size();
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
// 自定義視圖
ListItemView listItemView = null;
if (convertView == null) {
// 獲取list_item布局文件的視圖
convertView = inflater.inflate(R.layout.dropdown_list_item, null);

listItemView = new ListItemView();
// 獲取控制項對象
listItemView.tv = (TextView) convertView
.findViewById(R.id.tv);

listItemView.layout = (LinearLayout) convertView.findViewById(R.id.layout_container);
// 設置控制項集到convertView
convertView.setTag(listItemView);
} else {
listItemView = (ListItemView) convertView.getTag();
}

// 設置數據
listItemView.tv.setText(mData.get(position).toString());
final String text = mData.get(position).toString();
listItemView.layout.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
editText.setText(text);
closePopWindow();
}
});
return convertView;
}

}
private static class ListItemView{
TextView tv;
LinearLayout layout;
}

}

三、如何使用該自定義下拉列表框控制項
使用該控制項和使用普通的自帶的控制項一樣,首先需要在布局文件中引用該控制項:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.czm.xcdropdownlistview.MainActivity"
tools:ignore="MergeRootFrame" >

<com.czm.xcdropdownlistview.XCDropDownListView
android:id="@+id/drop_down_list_view"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true" />

</RelativeLayout>

其次,就是在代碼中使用該控制項:
package com.czm.xcdropdownlistview;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
/**
* 使用下拉列表框控制項 示例
* @author caiming
*
*/
public class MainActivity extends Activity {

XCDropDownListView dropDownListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

dropDownListView = (XCDropDownListView)findViewById(R.id.drop_down_list_view);
ArrayList<String> list = new ArrayList<String>();
for(int i = 0;i< 6;i++){
list.add("下拉列表項"+(i+1));
}
dropDownListView.setItemsData(list);

}

}

對了,這個控制項中,我沒有實現點擊item項回調介面,這個可能對有些寫慣了回調的可能覺得少了寫什麼的感覺,有興趣的你可以自己添加相關回調操作哈,這個大家應該都會把。

❹ android中自定義時間控制項如何實現下面的時間,求源碼

我這里有demo,你可以自己琢磨一下


❺ Android 自定義控制項 layout

Android 繪制流程

View :View主要執行layout方法,使用 serFrame 方法來設置本身 View 的四個頂點的位置,確定View本身的位置。
ViewGroup :ViewGroup主要執行onLayout方法,遞歸遍歷所有子View,確定子View的位置。

我們來看ViewRootImpl中的 performLayout() 方法

看到這里,那host.getMeasuredWidth() / host.getMeasuredHeight()是什麼?它是直接調用View中的方法,其實就是經過measure後的DecorView的測量寬度和高度。在 Android 自定義控制項 measure 中有說明。

2.3.2.1 我們先來看ViewGroup中的 layout() 方法

ViewGroup裡面的layout最終會調入到父類View中的layout,View的layout後面講解。這里可以先告訴大家,最終會調用View的onLayout方法,而ViewGroup的onLayout是抽象方法,所以它的子類LinearLayout必須要實現。

2.3.2.2 我們再來看LinearLayout中的 onLayout() 方法。

2.3.2.3 挑一個縱向的吧,我們再來看LinearLayout中的 layoutVertical() 方法。

2.3.2.4 我們再來看LinearLayout中的 setChildFrame() 方法。

又一次回到了View的layout方法,接下來就看View分發的layout。

我們先來看View中的 layout() 方法。

我們先來看View中的 onLayout() 方法。

空空如也,其實View的布局由父容器決定,所以空實現是正常的,當然也可以在自定義View中進行更改。

《Android 視圖模塊 全家桶》

Android開發之自定義控制項(二)---onLayout詳解
自定義View Layout過程 - 最易懂的自定義View原理系列(3)

❻ Android自定義控制項 | 小紅點的三種實現(終結)

上一篇通過在父控制項繪制前景的方式展示小紅點,在布局文件中配置標記控制項就能為任意子控制項添加小紅點。實現方案是」布局文件中配置帶小紅點控制項 id,在父控制項中獲取它們的坐標,並在其右上角繪制圓圈「。但這個方案有一個漏洞,當子控制項做動畫,即子控制項尺寸發生變化時,小紅點不會聯動。效果入下圖:

在父控制項的 draw() , dispatchDraw() , drawChild() 中打 log,子控制項做動畫時都未能捕獲到聯動的事件。

突然想起 androidx.coordinatorlayout.widget.CoordinatorLayout 中的 Behavior ,在 onDependentViewChanged() 中可以實時獲得關聯控制項的屬性變化。它是如何做到的?沿著調用鏈往上查找:

當關聯子控制項發生變化時,會遍歷關聯控制項並將變換通過 onDependentViewChanged() 傳遞出去。沿著調用鏈再往上:

CoordinatorLayout 在 onAttachedToWindow() 時注冊了 View 樹觀察者,子控制項屬性變化時必定會觸發 View樹重繪,這樣就可以在 onPreDraw() 中監聽到它們的屬性變化。

將這套機制照搬到自定義容器控制項 TreasureBox :

這樣當需要繪制小紅點的子控制項屬性發生變化時,標記控制項就可以在 onPreDraw() 中收到通知:

每次 View 樹重繪前都可以在 onPreDraw() 中實時獲取子控制項的寬高及坐標,為了避免過度重繪,只有當屬性變化時,才觸發父控制項重繪。需要記憶上次重繪的屬性,通過比較就能知道屬性是否發生變更:

還需要變更下小紅點繪制邏輯,之前的邏輯如下:

如果沿用這套繪制邏輯,即使父控制項監聽到子控制項重繪,小紅點也不會跟著聯動。那是因為 View 的 getTop() 和 getRight() 不包含位移值:

而 getX() 和 getY() 則包含了位移值:

只需要將繪制邏輯中的 v.right 和 v.top 換成 v.x 和 v.y ,小紅點就能和動畫聯動了。為控制項添加位移和縮放動畫,測試一下:

GG思密達~
。位移動畫的確會聯動,但縮放並沒有~

打了 log 才發現,View 通過 setScale() 的方式進行動畫時,它的寬高和坐標並不會發生變化。。。

但必然是有一個屬性的值變化了,雖然暫且不知道它是啥?

只能打開 View 源碼,遍歷所有 get 開頭的函數,然後把它們的值列印在 onPreDraw() 中。經過多次嘗試,終於找到了一個函數,它的返回值和子控制項縮放動畫聯動:

當子控制項做縮小動畫時,該函數返回的 Rect 中的 left 會變大而 right 會變小。

函數的返回值在 mLeft , mRight , mTop , mBottom 的基礎上疊加了 matrix 的值。做動畫的屬性值最終都會反映到 matrix 上,這樣一分析好像能自圓其說,即該函數會實時返回 view 因動畫而改變的屬性值。

如此一來,只需要記憶上一次的 Rect ,就能在下次重繪前通過比較得知子控制項是否做了動畫:

繪制小紅點邏輯也要做響應改動:

大功告成,效果如下:

❼ 如何打造Android自定義的下拉列表框控制項

一、概述
Android中的有個原生的下拉列表控制項Spinner,但是這個控制項有時候不符合我們自己的要求,
比如有時候我們需要類似windows
或者web網頁中常見的那種下拉列表控制項,類似下圖這樣的:
這個時候只有自己動手寫一個了。其實實現起來不算很難,
本文實現的方案是採用TextView
+ImageView+PopupWindow的組合方案。
先來看看我們的自己寫的控制項效果圖吧:(源碼在文章下面最後給出哈!)
二、自定義下拉列表框控制項的實現
1.
自定義控制項用到的布局文件和資源:
結果框的布局頁面:dropdownlist_view.xml:
<?xml
version="1.0"
encoding="utf-8"?>

❽ android自定義控制項之文件選擇

不多說,先上圖:

列舉當前目錄下的所有文件,如果是選擇目錄,則不顯示文件,如果是選擇文件,則需要顯示文件。

新建目錄,就是在當前路徑下新建目錄,同時新建後的目錄要能夠及時顯示在文件列表中。

需要讀寫許可權,添加第三方許可權請求庫:

使用:

DialogFragment與Dialog有一些不同的地方,其中show方法需要傳入FragmentManager

另外需在onCreateVie方法初始化布局,以及獲取到控制項

另外就是RecycleView,之所以採用RecycleView,是因為發現如果用ListView,內存會不斷增加,很難降下來。

其中CommonAdapter繼承自BaseAdapter,是通用的Adapter,兼容ListView:

這一部分邏輯有FileProvider類完成; 這里需要注意的是,有些手機不支持讀取根目錄,所以改為讀取"/mnt/"作為根目錄就行讀取。

另外跳轉目錄都是改變當前路徑,然後再刷新數據。

同時在其內部定義了FileData類:

文件選擇,可以通過當前路徑路徑以及列表索引來唯一確定路徑;都是,當跳轉目錄後,索引應該重置。

這里採用WeakReference記錄選擇的控制項,但選擇其他目錄或者文件時,之前的控制項需要重置一下狀態。

https://github.com/xiaoyifan6/videocreator

該源碼主要用於圖片合成gif或者視頻,其中文件選擇彈窗是自己寫的。感覺這個彈出應該有許多地方可以用到,所以寫下這篇文章,方便以後參考查看。

❾ 如何打造Android自定義的下拉列表框控制項

TextView +ImageView+PopupWindow的組合方案。
先來看看我們的自己寫的控制項效果圖吧:(源碼在文章下面最後給出哈!)

二、自定義下拉列表框控制項的實現
1. 自定義控制項用到的布局文件和資源:
結果框的布局頁面:dropdownlist_view.xml:
<?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"
android:orientation="horizontal"
android:id="@+id/compound"
android:background="@drawable/dropdown_bg_selector" >

<TextView
android:id="@+id/text"
android:layout_width="250dp"
android:layout_height="40dp"
android:paddingLeft="10dp"
android:text="文本文字"
android:gravity="center_vertical"
android:textSize="14sp"
android:padding="5dp"
android:singleLine="true" />
<ImageView
android:id="@+id/btn"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_toRightOf="@+id/text"
android:src="@drawable/dropdown"
android:padding="5dp"
android:layout_centerVertical="true"
android:gravity="center"/>
</RelativeLayout>

下拉彈窗列表布局頁面:dropdownlist_popupwindow.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<ListView
android:id="@+id/listView"
android:layout_width="280dp"
android:layout_height="wrap_content"
android:divider="#666666"
android:dividerHeight="1dp"
></ListView>

</LinearLayout>

selector資源文件:
dropdown_list_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@color/dropdownlist_item_press"/>
<item android:drawable="@color/dropdownlist_item"/>
</selector>

dropdown_bg_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@color/dropdownlist_press"/>
<item android:drawable="@color/dropdownlist_bg"/>
</selector>

2. 自定義下拉列表框控制項類的實現:
我們採用了TextView+ImageView+PopupWindow的組合方案,所以我的自定義控制項需要重寫ViewGroup,由於我們已經知道了,布局方向為豎直方向,所以這里,

閱讀全文

與android的自定義控制項源碼相關的資料

熱點內容
gcc編譯vi文件 瀏覽:61
安卓連airpods怎麼找耳機 瀏覽:925
加密貨幣轉賬教程 瀏覽:227
程序員小灰hashmap 瀏覽:836
國語pdf版 瀏覽:182
少兒編程作品美麗的小房子 瀏覽:970
伺服器卡在網頁上怎麼辦 瀏覽:54
用python自製編譯器 瀏覽:951
android分享新浪微博客戶端 瀏覽:26
系統中伺服器在哪裡下載地址 瀏覽:1001
新a4安卓手機怎麼投屏 瀏覽:173
pdftoemf 瀏覽:886
java介面可以實現介面嗎 瀏覽:59
vb編程10個隨機函數 瀏覽:21
程序員個人簡介100 瀏覽:772
土木工程師演算法工程師 瀏覽:92
javaexcel導入oracle 瀏覽:880
如何設置異地伺服器 瀏覽:882
為什麼安卓手機藍牙耳機不會彈窗 瀏覽:547
linuxf77編譯器安裝教程 瀏覽:949