自定義控件
-
獲得LayoutInflater實(shí)例的三種方法:
LayoutInflater layoutInflater = getLayoutInflater();
LayoutInflater layoutInflater =(LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
LayoutInflater layoutInflater = LayoutInflater.from(MainActivity.this);
-
View的工作流程:
- 構(gòu)造器---> 初始化
-
onMeasure()
定大小 -
onLayout()
定位置 -
onDraw()
繪制 -
invalidate()
刷新
-
自定義控件的三種主要形式:
- 繼承已有的控件來實(shí)現(xiàn)自定義控件椭蹄。
- 繼承一個(gè)布局文件實(shí)現(xiàn)自定義控件。
- 通過繼承View類來實(shí)現(xiàn)自定義控件史侣。
代碼示例:做一個(gè)圓形的紅色按鈕憔杨,中間有一個(gè)白色數(shù)字缀棍,數(shù)字起始為20然低,每次點(diǎn)擊減少1.
public class TestRedButton extends View implements View.OnClickListener{
private Paint mPaint;
private Rect mRect;
private int num = 20;
public TestRedButton(Context context) {
this(context, null);
}
public TestRedButton(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TestRedButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
Init();
}
public void Init(){
mPaint = new Paint();
mRect = new Rect();
this.setOnClickListener(this);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 設(shè)置畫布為紅色
mPaint.setColor(Color.RED);
// 畫出Circle
canvas.drawCircle(getWidth()/2, getHeight()/2, getWidth()/2, mPaint);
// 中間有一個(gè)白色數(shù)字
mPaint.setColor(Color.WHITE);
mPaint.setTextSize(60);
// mRect是文字四周的邊距
String text = String.valueOf(num);
mPaint.getTextBounds(text, 0, text.length(), mRect);
canvas.drawText(text, getWidth()/2 - mRect.width()/2, getHeight()/2 + mRect.height()/2, mPaint);
}
@Override
public void onClick(View v) {
num--;
invalidate();
}
}
- 自定義視圖屬性
- 在values中創(chuàng)建新的XML文件鹿蜀,并按格式寫屬性庵佣。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TestRedButton">
<attr name="backgroundColor" format="color" />
<attr name="text" format="integer" />
<attr name="textSize" format="dimension"/>
</declare-styleable>
</resources>
2. 在`Init()`中添加
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TestRedButton);
mBackgroundColor = typedArray.getColor(R.styleable.TestRedButton_backgroundColor, Color.RED);
mNums = typedArray.getInteger(R.styleable.TestRedButton_text, 0);
mTextSize = typedArray.getDimensionPixelSize(R.styleable.TestRedButton_textSize, 36);
3. 將得到的返回值代入畫布满哪。
mPaint.setColor(mBackgroundColor);
mPaint.setTextSize(mTextSize);
4. 在引用此自定義控件的XML文件中插入xmlns:app="http://schemas.android.com/apk/res-auto"
婿斥,就可以設(shè)置自定義屬性了 。
Fragment
- Fragment是activity的界面中的一部分哨鸭。
- 多個(gè)Fragment組合到一個(gè)activity中民宿。
- 多個(gè)activity中可重用一個(gè)Fragment
- 總結(jié):
- Fragment相當(dāng)于模塊化的一段activity
- 具有自己的生命周期,接收自己的事件
- 在activity運(yùn)行時(shí)被添加或刪除
創(chuàng)建Fragment的兩種方法
- 在xml中添加fragment控件像鸡,并
android:name="com.example.hx.demo.TestFragment"
添加指定fragment活鹰。- 創(chuàng)建一個(gè)class extends Fragment, 并覆寫
onCreate()
和onCreateView()
方法 - 解析一個(gè)xml文件坟桅,并返回其view华望。
- 創(chuàng)建一個(gè)class extends Fragment, 并覆寫
public class TestFragment extends Fragment{
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// 解析一個(gè)XML文件,并返回view仅乓。
View view = inflater.inflate(R.layout.activity_item_info, container, true);
return view;
}
}
3. 在主xml中添加fragment
<?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">
<fragment
android:id="@+id/fragment_test"
android:name="com.example.hx.demo.TestFragment"
android:layout_width="match_parent"
android:layout_height="100dp"/>
</LinearLayout>
- 從Activety代碼中添加赖舟。
1. 在xml中加入ViewGroup,作為Fragment的容器夸楣。
<LinearLayout
android:id="@+id/fragment_view_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"/>
2. 在主Activity的`onCreate()`方法中添加:
public class TestFtagmentActivity extends AppCompatActivity{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment_test);
setTitle(getIntent().getStringExtra("appName"));
// 獲取管理器
FragmentManager fragmentManager = getFragmentManager();
// 通過管理器獲取事務(wù)處理
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// 創(chuàng)建一個(gè)TestFragment 實(shí)例對(duì)象
TestFragment testFragment = new TestFragment();
// 將其添加到ViewGroup
fragmentTransaction.add(R.id.fragment_view_group, testFragment, "fragment_tag");
// 刪除
fragmentfragmentTransaction.remove(testFragment).commit();
// 找到fragment:方法一:
fragmentManager.findFragmentById(R.id.fragment_test);
// 方法二:
fragmentManager.findFragmentByTag("fragment_tag");
}
}
#Handler
- 它直接繼承自`Object`宾抓,一個(gè)Handler允許發(fā)送和處理Message或者Runnable對(duì)象,并且會(huì)關(guān)聯(lián)到主線程的MessageQueue中豫喧。每個(gè)Handler具有一個(gè)單獨(dú)的線程石洗,并且關(guān)聯(lián)到一個(gè)消息隊(duì)列的線程,就是說一個(gè)Handler有一個(gè)固有的消息隊(duì)列紧显。當(dāng)實(shí)例化一個(gè)Handler的時(shí)候讲衫,它就承載在一個(gè)線程和消息隊(duì)列的線程,這個(gè)Handler可以把Message或Runnable壓入到消息隊(duì)列孵班,并且從消息隊(duì)列中取出Message或Runnable涉兽,進(jìn)而操作它們。
>Handler主要有兩個(gè)作用:在工作線程中發(fā)送消息篙程;在UI線程中獲取枷畏、處理消息。
- 上面介紹到Handler可以把一個(gè)Message對(duì)象或者Runnable對(duì)象壓入到消息隊(duì)列中虱饿,進(jìn)而在UI線程中獲取Message或者執(zhí)行Runnable對(duì)象(*其實(shí)post發(fā)出的Runnable對(duì)象最后都被封裝成message對(duì)象了*)拥诡,所以Handler把壓入消息隊(duì)列有兩大體系触趴,是立即執(zhí)行還是延遲執(zhí)行:
1. Post:Post允許把一個(gè)Runnable對(duì)象入隊(duì)到消息隊(duì)列中。它的方法有:
- `post(Runnable)`
- `postAtTime(Runnable,long)`
- `postDelayed(Runnable,long)`
2. sendMessage:sendMessage允許把一個(gè)包含消息數(shù)據(jù)的Message對(duì)象壓入到消息隊(duì)列中渴肉。它的方法有:
- `sendEmptyMessage(int)`
- `sendMessage(Message)`
- `sendMessageAtTime(Message,long)`
- `sendMessageDelayed(Message,long)`
>[兩個(gè)Button實(shí)現(xiàn)暫停和開始](http://blog.sina.com.cn/s/blog_77c6324101016jp8.html)
- 實(shí)現(xiàn)倒計(jì)時(shí)Demo
public class HandlerActivity extends AppCompatActivity {
public static final int WHAT = 666;
private Handler mHandler;
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
setTitle(getIntent().getStringExtra("appName"));
mTextView = (TextView) findViewById(R.id.handler_text_view);
mHandler = new Handler();
MyHandler myHandler = new MyHandler();
Message message = mHandler.obtainMessage();
message.arg1 = 10;
message.what = WHAT;
myHandler.sendMessageDelayed(message, 1000);
}
private class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case WHAT:
mTextView.setText(msg.arg1+"");
msg = obtainMessage();
msg.arg1 = Integer.valueOf((String) mTextView.getText()) - 1;
msg.what = WHAT;
break;
}
if (Integer.valueOf((String) mTextView.getText()) > 0){
sendMessageDelayed(msg, 1000);
}
}
}
}