目錄
實作TextView拖拽顯示
補充:getRawX和get的差別
簡單的自定義 View
xmlns 作用
Android attrs檔案(自定義)屬性詳解
補充:drawable 轉bitmap 空指針
補充:setColor方法:設定顔色
屬性定義時可以同時定義多種類型值
屬性動畫:
Android動态添加View之addView
自定義樣式和主題
實作TextView拖拽顯示
layout:
<LinearLayout
android:id="@+id/rl"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:text="張"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.425"
new View.OnTouchListener() {
int orgX, orgY;
int offsetX, offsetY;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
orgX = (int) event.getX();
orgY = (int) event.getY();
Log.d("TAG", "onTouch: orgX=="+orgX);
Log.d("TAG", "onTouch: orgY=="+orgY);
break;
case MotionEvent.ACTION_MOVE:
offsetX = (int) event.getRawX() - orgX;
offsetY = (int) event.getRawY() - orgY;
Log.d("TAG", "onTouch: event.getRawX()=="+event.getRawX());
Log.d("TAG", "onTouch: event.getRawY()=="+event.getRawY());
Log.d("TAG", "offsetX: offsetX=="+offsetX);
Log.d("TAG", "offsetY: offsetY=="+offsetY);
LinearLayout.LayoutParams p1 = (LinearLayout.LayoutParams) relativeLayout.getLayoutParams();
p1.topMargin = offsetY;//設定像素
p1.leftMargin = offsetX;//設定像素
relativeLayout.setLayoutParams(p1);
break;
}
return true;
}
});
補充:getRawX和get的差別
getX()是表示Widget相對于自身左上角的x坐标。
getRawX()是表示相對于螢幕左上角的x坐标值,這個螢幕左上角是手機螢幕左上角,不管activity是否有titleBar或是否全螢幕。
簡單的自定義 View
package com.example.ceshi;
import android.content.Context;
import android.content.res.TypedArray;
/**
* @ProjectName: ceshi
* @Package: com.example.ceshi
* @ClassName: MyView
* @Description: java類作用描述
* @Author: 作者名
* @CreateDate: 2020/7/30 0030 下午 5:22
* @UpdateUser: 更新者:
* @UpdateDate: 2020/7/30 0030 下午 5:22
*/
public class MyView extends View {
private Paint myPaint;
private Paint myPaint1;
private static final String myString = "Hello CustomView!";
public MyView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
int bg;
String text;
int textColor1;
public MyView(Context context, AttributeSet attr) {
super(context, attr);
myPaint = new Paint();
TypedArray a = context.obtainStyledAttributes(attr, R.styleable.myView);//TypedArray是一個數組容器
float textSize = a.getDimension(R.styleable.myView_textSize, 30);//防止在XML檔案裡沒有定義,就加上了預設值30
int textColor = a.getColor(R.styleable.myView_textColor, 0x34343434);//同上,這裡的屬性是:名字_屬性名
textColor1 = a.getColor(R.styleable.myView_textColor1, 0x34343434);//同上,這裡的屬性是:名字_屬性名
bg = a.getColor(R.styleable.myView_backg, 0xdd0000);//同上,這裡的屬性是:名字_屬性名
text = a.getString(R.styleable.myView_text);
myPaint.setTextSize(textSize);
myPaint.setColor(textColor);
a.recycle();//我的了解是:
// 傳回以前取回的屬性,供以後使用。以前取回的可能就是textSize和textColor初始化的那段
}
/**
* @param
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
myPaint1 = new Paint();
myPaint1.setColor(textColor1);
myPaint1.setColor(Color.BLUE);
canvas.drawCircle(500, 500, 200, myPaint1);
canvas.drawCircle(500, 500, 100, myPaint);
canvas.drawText(text, 0, 0, myPaint);
}
}
layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tes="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<com.example.ceshi.MyView
android:id="@+id/mv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tes:text="zhangjiqun"
tes:textColor="#ff0000"
tes:textColor1="#FFF283"
tes:textSize="50px">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="張"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.425"
tools:text="張 "
調用并實作動畫:
package com.example.ceshi;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
/**
*
*/
public class MainActivity extends AppCompatActivity {
private TextView tv;
Handler handler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
tv.setText(111 + "");
break;
case 2:
tv.setText(222 + "");
break;
case 3:
tv.setText(333 + "");
break;
case 4:
tv.setText(444 + "");
break;
case 5:
tv.setText(555 + "");
break;
}
}
};
private ProgressDialog processDialog;
/**
* @param savedInstanceState
*/
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
final MyView myView=findViewById(R.id.mv);
myView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,"123",
Toast.LENGTH_SHORT).show();
}
});
handler.sendEmptyMessageDelayed(1, 1000);
handler.sendEmptyMessageDelayed(2, 2000);
handler.sendEmptyMessageDelayed(3, 3000);
handler.sendEmptyMessageDelayed(4, 4000);
handler.sendEmptyMessageDelayed(5, 5000);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, MainActivityt.class);
startActivity(intent);
}
});
ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(
myView, "alpha", 1f, 0f, 1f);
objectAnimator.setDuration(2000).setStartDelay(100); ;
objectAnimator.setRepeatCount(1000);
objectAnimator.setRepeatMode(ValueAnimator.RESTART);
objectAnimator.start();
ObjectAnimator objectAnimator1=ObjectAnimator.ofFloat(myView,
"rotation",0f,360f);
myView.setPivotX(400);
myView.setPivotY(400);
objectAnimator1.setRepeatCount(1000);
objectAnimator1.setDuration(500).start();
float fl=myView.getTranslationX();
ObjectAnimator objectAnimator2=ObjectAnimator.ofFloat(myView,
"scale",1f,3f,1f);
objectAnimator2.setDuration(2000).setRepeatCount(2000);
objectAnimator2.start();
ObjectAnimator objectAnimator3=ObjectAnimator.ofFloat(myView,
"scaleX",1f,3f,1f);
objectAnimator3.setDuration(2000).setRepeatCount(2000);
objectAnimator3.start();
String a = "123";
tv.setText(a);
try {
Test();
} catch ( ServiceException e ) {
// e.printStackTrace();
waitCloseAlert("執行線程異常,原因:"+e.getMessage());
}
}
public static void Test()throws ServiceException
{
throw new ServiceException("怎麼說");
}
/**
* 關閉等待警告提示
* */
public void waitCloseAlert(final String message) {
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
if (processDialog != null && processDialog.isShowing()) {
processDialog.dismiss();
}
showAlertDialog(message,null,R.drawable.ic_launcher_background,null);
}
});
}
public void showAlertDialog(String title,String message,Integer icon,final View focusView){
AlertDialog.Builder builder=new AlertDialog.Builder(this);
if(title!=null){
builder.setTitle(title);
}
if(message!=null){
builder.setMessage(message);
}
if(icon!=null){
builder.setIcon(icon);
}
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(focusView!=null){
focusView.requestFocus();
}
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
}
xmlns 作用
xmlns:android="schemas.android.com/apk/res/and…
這個是xml的命名空間,也可以了解為文法檔案。或者文法判斷器什麼的;
這個主要作用是在運作的時候那些控件的屬性都是通過它來識别的,如果上面你寫錯了,不會有任何問題,但是在運作的時候就會有問題,提示你沒有指定寬度等什麼。這個是不用聯網的。
自定義xmlns:xmlns:tes="http://schemas.android.com/apk/res-auto"

xmlns 使用,下面有兩種形式,現在一般使用直接 res-auto;
Android attrs檔案(自定義)屬性詳解
<!-- declare-styleable表示為自定義的屬性-->
<!-- format表示為可接受的參數類型-->
<!--integer int型-->
<!--boolean boolean-->
<!--color 顔色-->
<!--dimension 尺寸-->
<!--enum 枚舉-->
<!--flag 位或運算-->
<!--float float型-->
<!--fraction 百分數-->
<!--reference 資源檔案-->
<!--string 字元串-->
<declare-styleable name="MyView">
<attr name="a" format="integer"></attr>
<attr name="b" format="boolean"></attr>
<attr name="c" format="color"></attr>
<attr name="d" format="dimension"></attr>
<attr name="e"></attr>
<attr name="f"></attr>
<attr name="g" format="float"></attr>
<attr name="h" format="fraction"></attr>
<attr name="i" format="reference"></attr>
<attr name="j" format="string"></attr>
</declare-styleable>
<attr name="e">
<enum name="e1" value="1"></enum>
<enum name="e2" value="2"></enum>
</attr>
<attr name="f">
<flag name="f1" value="1"></flag>
<flag name="f2" value="2"></flag>
</attr>
在layout頭部設定:
xmlns:tes="http://schemas.android.com/apk/res-auto"
使用:
tes:textColor="#ff0000"
1 reference:參考某一資源ID
主要是使用一些圖檔資源的時候使用reference;
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="myView">
<attr name="backg" format="color" />
<attr name="textColor" format="color" />
<attr name="textColor1" format="color" />
<attr name="textSize" format="dimension" />
<attr name="text" format="string" />
<attr name="draw" format="reference" />
</declare-styleable>
</resources>
layout:
<com.example.ceshi.MyView
android:id="@+id/mv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tes:draw="@drawable/ic_launcher_background"
tes:text="zhangjiqun"
tes:textColor="#ff0000"
tes:textColor1="#FFF283"
tes:textSize="50px">
</com.example.ceshi.MyView>
draw = a.getResourceId(R.styleable.myView_draw, R.drawable.ic_launcher_background);
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_background);
canvas.drawBitmap(mBitmap,100,100,myPaint);
整體:
package com.example.ceshi;
import android.content.Context;
/**
* @ProjectName: ceshi
* @Package: com.example.ceshi
* @ClassName: MyView
* @Description: java類作用描述
* @Author: 作者名
* @CreateDate: 2020/7/30 0030 下午 5:22
* @UpdateUser: 更新者:
* @UpdateDate: 2020/7/30 0030 下午 5:22
*/
public class MyView extends View {
private Paint myPaint;
private Paint myPaint1;
private static final String myString = "Hello CustomView!";
public MyView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
int bg;
String text;
int textColor1;
int draw;
public MyView(Context context, AttributeSet attr) {
super(context, attr);
myPaint = new Paint();
TypedArray a = context.obtainStyledAttributes(attr, R.styleable.myView);//TypedArray是一個數組容器
float textSize = a.getDimension(R.styleable.myView_textSize, 30);//防止在XML檔案裡沒有定義,就加上了預設值30
int textColor = a.getColor(R.styleable.myView_textColor, 0x34343434);//同上,這裡的屬性是:名字_屬性名
draw = a.getResourceId(R.styleable.myView_draw, R.drawable.ic_launcher_background);//同上,這裡的屬性是:名字_屬性名
textColor1 = a.getColor(R.styleable.myView_textColor1, 0x34343434);//同上,這裡的屬性是:名字_屬性名
bg = a.getColor(R.styleable.myView_backg, 0xdd0000);//同上,這裡的屬性是:名字_屬性名
text = a.getString(R.styleable.myView_text);
myPaint.setTextSize(textSize);
myPaint.setColor(textColor);
a.recycle();//我的了解是:
// 傳回以前取回的屬性,供以後使用。以前取回的可能就是textSize和textColor初始化的那段
}
/**
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
myPaint1 = new Paint();
myPaint1.setColor(textColor1);
myPaint1.setColor(Color.BLUE);
canvas.drawCircle(500, 500, 200, myPaint1);
canvas.drawCircle(500, 500, 100, myPaint);
canvas.drawText(text, 0, 0, myPaint);
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), draw);
canvas.drawBitmap(mBitmap,100,100,myPaint);
補充:drawable 轉bitmap 空指針
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_background);
上面這個是空指針,原因是這個資源檔案是xml;
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
是以這個BitmapFactory必須使用圖檔資源才是可以的;
2 color:顔色值
name = "名稱">
<attr name = "textColor" format = "color" />
</declare-styleable>
eg:
<TextView
android:layout_width = "42dip"
android:layout_height = "42dip"
android:textColor = "#00FF00"
補充:setColor方法:設定顔色
Color.RED:紅色。
Color.TRANSPARENT:透明。
Color.WHITE:白色。
RGB顔色設定方法
setColor(new Color(int r,int g,int b))
例如 setColor(new Color(220,255,220))
3 boolean:布爾值
name = "名稱">
<attr name = "focusable" format = "boolean" />
</declare-styleable>
eg:
<Button
android:layout_width = "42dip"
android:layout_height = "42dip"
android:focusable = "true"/>
4 dimension:尺寸值
name = "名稱">
<attr name = "layout_width" format = "dimension" />
</declare-styleable>
eg:
<com.lizi.newset.CustomView.attrs.MyView
android:id="@+id/myView"
android:layout_height="match_parent"
android:layout_width="wrap_content"
test:textSize="50px"
test:textColor="#ff00ff"/>
5 float:浮點值
name = "AlphaAnimation">
<attr name = "fromAlpha" format = "float" />
<attr name = "toAlpha" format = "float" />
</declare-styleable>
eg:
<alpha
android:fromAlpha = "1.0"
android:toAlpha = "0.7"
6 string:字元串
name = "MapView">
<attr name = "apiKey" format = "string" />
</declare-styleable>
eg:
<com.google.android.maps.MapView
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
android:apiKey = "0jOkQ80oD1JL9C6HAja99uGXCRiS2CGjKO_bc_g"
7 integer:整型值 || fraction:百分數
name = "AnimatedRotateDrawable">
<attr name = "visible" />
<attr name = "frameDuration" format="integer" />
<attr name = "framesCount" format="integer" />
<attr name = "pivotX" format = "fraction"/>
<attr name = "pivotY" format = "fraction"/>
<attr name = "drawable" />
</declare-styleable>
eg:
<animated-rotate
xmlns:android = "http://schemas.android.com/apk/res/android"
android:drawable = "@drawable/圖檔ID"
android:pivotX = "50%"
android:pivotY = "50%"
android:framesCount = "12"
android:frameDuration = "100"
8 enum:枚舉值
name="名稱">
<attr name="orientation">
<enum name="horizontal" value="0" />
<enum name="vertical" value="1" />
</attr>
</declare-styleable>
eg:
<LinearLayout
xmlns:android = "http://schemas.android.com/apk/res/android"
android:orientation = "vertical"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
9 flag 位或運算
name="名稱">
<attr name="windowSoftInputMode">
<flag name = "stateUnspecified" value = "0" />
<flag name = "stateUnchanged" value = "1" />
<flag name = "stateHidden" value = "2" />
<flag name = "stateAlwaysHidden" value = "3" />
<flag name = "stateVisible" value = "4" />
<flag name = "stateAlwaysVisible" value = "5" />
<flag name = "adjustUnspecified" value = "0x00" />
<flag name = "adjustResize" value = "0x10" />
<flag name = "adjustPan" value = "0x20" />
<flag name = "adjustNothing" value = "0x30" />
</attr>
</declare-styleable>
eg:
<activity
android:name = ".StyleAndThemeActivity"
android:label = "@string/app_name"
android:windowSoftInputMode = "stateUnspecified | stateUnchanged | stateHidden">
<intent-filter>
<action android:name = "android.intent.action.MAIN" />
<category android:name = "android.intent.category.LAUNCHER"
屬性定義時可以同時定義多種類型值
name = "名稱">
<attr name = "background" format = "reference|color" />
</declare-styleable>
eg:
<ImageView
android:layout_width = "42dip"
android:layout_height = "42dip"
android:background = "@drawable/圖檔ID|#00FF00"
Error:(246, 5) error: invalid value '??' for ; must be an integer.
這個錯诶就是在attrs中你有的地方指派類型不對,仔細看看,我的 是有一個空格,但是類型是int;仔細檢查;
Error:(369) duplicate value for resource 'attr/background' with config ''.
這是由于background這個值重複了,一般的都有這個數值,你改個名字;
屬性動畫:
旋轉,縮放,透明度
objectAnimator=ObjectAnimator.ofFloat(
myView, "alpha", 1f, 0f, 1f);
objectAnimator.setDuration(2000).setStartDelay(100); ;
objectAnimator.setRepeatCount(1000);
objectAnimator.setRepeatMode(ValueAnimator.RESTART);
objectAnimator.start();
ObjectAnimator objectAnimator1=ObjectAnimator.ofFloat(myView,
"rotation",0f,360f);
myView.setPivotX(400);
myView.setPivotY(400);
objectAnimator1.setRepeatCount(1000);
objectAnimator1.setDuration(500).start();
float fl=myView.getTranslationX();
ObjectAnimator objectAnimator2=ObjectAnimator.ofFloat(myView,
"scale",1f,3f,1f);
objectAnimator2.setDuration(2000).setRepeatCount(2000);
objectAnimator2.start();
ObjectAnimator objectAnimator3=ObjectAnimator.ofFloat(myView,
"scaleX",1f,3f,1f);
objectAnimator3.setDuration(2000).setRepeatCount(2000);
objectAnimator3.start();
Android動态添加View之addView
layout:
id="@+id/content"
android:layout_width="match_parent"
android:layout_height="66dp"
android:orientation="horizontal">
</LinearLayout>
代碼實作:
/**
* 按鈕點選事件,向容器中添加TextView
* @param
*/
public void addView() {
TextView child = new TextView(this);
child.setTextSize(20);
child.setTextColor(getResources().getColor(R.color.colorAccent));
// 擷取目前的時間并轉換為時間戳格式, 并設定給TextView
child.setText("321");
// 調用一個參數的addView方法
mContainer.addView(child);
}
自定義樣式和主題
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"><!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item></style>
<style name="CeShiTheme" parent="AppTheme"><item name="android:typeface">monospace</item></style>
<style name="my_Style"><!-- 定義與指定View相關的若幹屬性 -->
<item name="android:hint">load from style 1</item></style>
<!-- 定義my_style_1,沒有指定parent,用系統預設的 -->
<style name="my_style_1"><!-- 定義與指定View相關的若幹屬性 -->
<item name="android:hint">load from style 1</item></style>
<!-- 定義my_style_2,用自定義的my_style_1作為parent -->
<style name="my_style_2" parent="@style/my_style_1"><!-- 定義與指定View相關的若幹屬性 -->
<item name="android:textSize">30sp</item>
<item name="android:textColor">#FFFF0000</item>
<item name="android:hint">load from style 2</item></style>
<!-- 定義my_style_3,用android的EditText作為parent -->
<style name="my_style_3" parent="@android:style/Widget.EditText"><!-- 定義與指定View相關的若幹屬性 -->
<item name="android:hint">"load from style 3"</item>
<item name="android:textStyle">bold|italic</item>
<item name="android:typeface">monospace</item>>
<item name="android:background">@drawable/logo</item></style>
<!-- 定義MyTheme,用android的Theme作為parent -->
<style name="MyTheme" parent="@android:style/Theme"><item name="android:textSize">20sp</item>
<item name="android:textColor">#FF0000FF</item>
<item name="android:hint">"load from style 3"</item>
<item name="android:textStyle">bold|italic</item>
<item name="android:typeface">monospace</item>>
<item name="android:background">@drawable/logo</item></style>
</resources>