Android 学习总结 & 自定义Dialog

1,740 阅读7分钟

控件

WebView

用于加载网页元素:

继承关系:WebView -> MockView

  • 加载URL(网络或本地assets文件夹下的html文件)
Webview.loadUrl("https://...")     //可以加载assets文件夹下的html文件
Webview.loadUrl("file:///android_asset/….")
  • 加载html代码
Webview.loadData();     //可能出现乱码
Webview.loadDataWithBaseUrl();
  • Native和JavaScript相互调用

  • 网页的前进后退:(语句的含义可以之间根据字面意思理解)

Webview.canGoBack()
Webview.goBack()
Webview.canGoForward()
Webview.goForward()
Webview.canGoBackOrForward(int steps)
Webview.goBackOrForward(int steps)

按下返回键默认是会退出当前Activity,如果希望是WebView内页面后退,需要复写onKeyDown方法

 @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {           //复写onKeyDown方法
        if(keyCode == KeyEvent.KEYCODE_BACK && mWV.canGoBack()) {
            mWV.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
  • 在使用WebView控件时常用的一些方法和类:

当下属方法或者类使用达不到效果,很可能是app没有网络访问权限,需要在Manifest文件中加入: <uses-permission android:name="android.permission.INTERNET" />

private WebView mWV;
mWV = findViewById(R.id.);
mWV.getSettings().setJavaScriptEnabled(true);
//当加载需要JavaScript支持的网页时,需要加上这一句
//---------------------------------------------------------------------//
mWV.setWebViewClient(new MyWebViewClient());
//防止WebView跳转到手机浏览器打开网页,而使用webview打开
class MyWebViewClient extends WebViewClient{
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
            view.loadUrl(request.getUrl().toString());
            return true;
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            Log.d("WebView","onPageStarted"); //用于在logcat中输出tag和一段字符串,可以不写,下同
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            Log.d("WebView","onPageFinished");
        }
    }
    //---------------------------------------------------------------------//
     mWV.setWebChromeClient(new MyWebChromeClient()); 
     //监听网页信息并利用这些信息对app进行操作
     class MyWebChromeClient extends WebChromeClient{
        public MyWebChromeClient() {
            super();
        }

        @Override
        public void onProgressChanged(WebView view, int newProgress) {
            super.onProgressChanged(view, newProgress);
        }

        @Override
        public void onReceivedTitle(WebView view, String title) {
            super.onReceivedTitle(view, title);
            setTitle(title);
        }
    }

Toast

消息提示组件

  • 常用样式:
Toast.makeText(getApplicationContext(),"defaulttoast",Toast.LENGTH_LONG).show();
  • 自定义显示位置:
Toast toast=Toast.makeText(getApplicationContext(),"",Toast.LENGTH_LONG);
//Toast的makeText方法会返回一个toast类的对象
toast.setText("hello");
toast.setGravity(Gravity.CENTER,0,0);
//设置Toast居中显示
toast.show();
  • 自定义显示内容(图片、文本)
Toast customToast = new Toast(getApplicationContext());
LayoutInflater  inflatr = LayoutInflater.from(ToastActivity.this);
Viewview = inflater.inflate(R.layout.layout_toast,null);

//自定义一个layout布局文件,此布局文件就是自定义内容模版
TextViewtextView = view.findViewById(R.id.tv);
ImageViewimageView = view.findViewById(R.id.iv);
textView.setText("test");

//为自定义模版中的Text组件设置内容
imageView.setImageResource(R.drawable.ic_launcher_foreground);
//设置图像
customToast.setView(view);
//将模版应用到Toast对象上

customToast.setDuration(Toast.LENGTH_LONG);
//设置显示时间
customToast.show();
  • 简单封装(这样可以防止多次toast排队显示,也可以被其他Activity直接引用)
public class ToastUtil{
public static ToastmToast;
public static void showMsg(Contextcontext,StringMsg){
if(mToast == null){
mToast = Toast.makeText(context,Msg,Toast.LENGTH_LONG);
}else{
mToast.setText(Msg);
}
mToast.show();
}
}

封装后的调用格式:

ToastUtil.showMsg(getApplicationContext(),"封装的Toast");

ProgressBar

  • 没有监听器

  • 支持自定义样式

    例如可以如下定义一个style

<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/icon_status_progress" //进度条图片
    android:pivotX="50%"      //旋转中心的x坐标在图片宽度的50%处
    android:pivotY="50%">     ////旋转中心的y坐标在图片高度的50%处
</animated-rotate>

然后在xml文件的一个progress控件中使用下述语句调用该style

android:indeterminateDrawable="@drawable/background_progress"
  • 常用属性
Style:Horizontal (Small. Large. Inverse. Small.Inverse. Large.Inverse)
Max:   //设置进度条最大值
Progress:    //设置进度条当前进度
secondaryProgress:     //设置进度条第二进度,一般用作播放器的缓冲进度
  • 常用方法:
Boolean isIndeterminate ()     //设置进度条的模式,indeterminate模式“圆形旋转”:true,条形模式:false
incrementProgressBy (int)
incrementsecondaryProgressBy (int)  

SeekBar

用户可调节的进度条

  • 监听器:
msb1.setOnSeekBarChangeListener(newSeekBar.OnSeekBarChangeListener(){
@Override
publicvoidonProgressChanged(SeekBarseekBar,intprogress,booleanfromUser){
//fromUser用于区分本次进度改变是否来自于用户
}

@Override
publicvoidonStartTrackingTouch(SeekBarseekBar){

}

@Override
publicvoidonStopTrackingTouch(SeekBarseekBar){

}
});

RatingBar

  • 监听器:
mRb1.setOnRatingBarChangeListener(newRatingBar.OnRatingBarChangeListener(){
@Override
publicvoidonRatingChanged(RatingBarratingBar,floatrating,booleanfromUser){
if(fromUser){
Toast.makeText(TimePickerActivity.this,rating+"评价",Toast.LENGTH_SHORT).show();
}
}
});
  • 属性:
StepSize    //每次移动的最小距离(多少星)
Numstart    //整个进度条星星的个数

AlertDialog

  • 设计一般型AlertDialog,可以设置positivebutton,neutralbutton和negativebutton三种按钮,并可以为每个按钮设置监听器(注意监听器类型为DialogInterface.OnClickListener()),监听器的参数分别代表被点击的dialog对象和该对象中被点击的按钮标号。
AlertDialog.Builder builder = new AlertDialog.Builder(AlertDialogActivity.this);
                    builder.setTitle("Please answer").setMessage("how are you?").setIcon(R.drawable.ic_launcher_foreground)
                            .setPositiveButton("I'm fine!", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            ToastUtil.showMsg(AlertDialogActivity.this,"thank you, and you?");
                        }
                    }).setNeutralButton("not too bad.", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            ToastUtil.showMsg(AlertDialogActivity.this,"tomorrow will be better!");
                        }
                    }).setNegativeButton("not very well.", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            ToastUtil.showMsg(AlertDialogActivity.this,"hope you have a nice day");
                        }
                    }).show();

注意最后要调用.show()方法,不然最后不会显示dialog对话框。

  • 设置单选型dialog
final String[] nation = new String[]{"Han","minority"};
                    AlertDialog.Builder builder3 = new AlertDialog.Builder(AlertDialogActivity.this);
                    builder3.setTitle("choose your nation: ").setSingleChoiceItems(nation, 1, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            ToastUtil.showMsg(AlertDialogActivity.this,nation[which]);
                            dialog.dismiss();                                                      //点击以后关闭dialog
                        }
                    }).setCancelable(false).show();                                                 //点击空白处不可关闭dialog

注意需要将string数组设置为final类型,否则无法在内部类中调用

  • 设置多选型dialog,在多选型dialog中需要使用一个boolean型数组来设置多选按钮的初始状态。
final String[] action = new String[]{"sing","dance","rap"};
                    boolean[] seclected = new boolean[]{false,false,false};
                    AlertDialog.Builder builder4 = new AlertDialog.Builder(AlertDialogActivity.this);
                    builder4.setMultiChoiceItems(action, seclected, new DialogInterface.OnMultiChoiceClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which, boolean isChecked) {
                            ToastUtil.showMsg(AlertDialogActivity.this,action[which] + ":" + isChecked);
                        }
                    }).setPositiveButton("confirm", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    }).setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    }).show();
  • 自定义dialog 使用LayoutInflater.from(AlertDialogActivity.this).inflate(R.layout.layout_dialog,null);语句通过inflater对象使用layout布局生成一个view对象,该view对象作为模版设置给一个AlertDialog的builder对象。同时可以对模版中的各个控件动态修改。
inal AlertDialog.Builder builder5 =  new AlertDialog.Builder(AlertDialogActivity.this);
                    View view = LayoutInflater.from(AlertDialogActivity.this).inflate(R.layout.layout_dialog,null);
                    Button button = view.findViewById(R.id.btn_login);
                    button.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {

                        }
                    });
                    builder5.setTitle("Please login first.").setView(view).show();

技巧

使用handler和Runnable实现进度条进度的动态增加

mProgressBar2 = findViewById(R.id.pb_2);
        mbtnStart = findViewById(R.id.btn_start);

        mbtnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                handler.sendEmptyMessage(0);
                Toast.makeText(ProgressBarActivity.this,"click",Toast.LENGTH_SHORT).show();
            }
        });
    }

    Handler handler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if(mProgressBar2.getProgress() < 100){
                mProgressBar2.postDelayed(runnable,500);
            }else{
                ToastUtil.showMsg(ProgressBarActivity.this,"progress complete");
            }
        }
    };

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            mProgressBar2.setProgress(mProgressBar2.getProgress() + 5);
            handler.sendEmptyMessage(0);
        }
    };

定义函数时可以将巧妙的设置返回值类型,实现连续调用:

例如:

public CustomDialog setTitle(String title) {
        Title = title;
        return this;
    }

这样定义CustomDialog的set类函数,就可以对一个对象连续调用其set方法,快速赋值。

使用switch语句和自定义clickListener管理众多button:

例如:

mBtnToast = findViewById(R.id.btn_toast);
        mAlertDialog = findViewById(R.id.btn_alertdialog);
        mProgressBar = findViewById(R.id.btn_progressbar);
        mCustomDialog = findViewById(R.id.btn_custondialog);
         
         
         private void setListeners(){
        OnClick onClick = new OnClick(); mBtnToast.setOnClickListener(onClick);
        mAlertDialog.setOnClickListener(onClick);
        mProgressBar.setOnClickListener(onClick);
        mCustomDialog.setOnClickListener(onClick);
    }
     private class OnClick implements View.OnClickListener{

        @Override
        public void onClick(View v) {
            Intent intent = null;
            switch (v.getId()){
             case R.id.btn_toast:
                    //转到Toast
                    intent = new Intent(UIActivity.this,ToastActivity.class);
                    break;
                case R.id.btn_alertdialog:
                    //转到AlertDialog
                    intent = new Intent(UIActivity.this,AlertDialogActivity.class);
                    break;
                case R.id.btn_progressbar:
                    //
                    intent = new Intent(UIActivity.this, ProgressBarActivity.class);
                    break;
                case R.id.btn_custondialog:
                    //
                    intent = new Intent(UIActivity.this,CustomDialogActivity.class);
                    break;
            }
            startActivity(intent);

使用View控件设置分割线:

例如:

 <View
            android:layout_width="0.5dp"
            android:layout_height="match_parent"
            android:background="@color/colorBlack"/>

自定义Dialog(CustomDialog)

可以到我的GitHub仓库查看源代码

  • 第一步设计CustommDialog的布局文件
<?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"
    android:gravity="center_horizontal"
    android:padding="10dp"
    android:background="@drawable/layout_custom_dialog">

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Title"
        android:textSize="25sp"
        android:textStyle="bold"
        android:layout_marginTop="10dp"/>
    
    <TextView
        android:id="@+id/tv_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="confirm to delete?"
        android:textSize="20sp"
        android:layout_marginTop="10dp"/>
    
    <View
        android:layout_marginTop="10dp"
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:background="@color/colorBlack"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/btn_confirm"
            android:layout_width="1dp"
            android:layout_height="wrap_content"
            android:text="confirm"
            android:layout_weight="1"/>
        <View
            android:layout_width="0.5dp"
            android:layout_height="match_parent"
            android:background="@color/colorBlack"/>
        <Button
            android:id="@+id/btn_cancel"
            android:layout_width="1dp"
            android:layout_height="wrap_content"
            android:text="cancel"
            android:layout_weight="1"/>
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:background="@color/colorBlack"/>

</LinearLayout>
  • 第二步定义一个CustomDialog类,并在该类的onCreat方法中调用上述布局文件实现CustomDailog。
package com.example.myfirstapplication.widget;

import android.app.Dialog;
import android.content.Context;
import android.graphics.Point;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.example.myfirstapplication.R;
import com.example.myfirstapplication.Util.ToastUtil;

public class CustomDialog extends Dialog implements View.OnClickListener{ 
//继承Dialog类,同时实现onclicklistener方法,
让自定义dailog既可以有dialog的属性和方法,还可以快速实现点击。

    private TextView mTvTitle,mTvMessage;
    private Button mBtnConfirm,mBtnCancel;

    private IOnCancelListener cancelListener;
    private IOnConfirmListener confirmListener;

    private String Title,Message,Cancel,Confirm;
    
    //复写Dialog构造函数
    public CustomDialog(@NonNull Context context) {
        super(context);
    }

    public CustomDialog(@NonNull Context context, int themeResId) {
        super(context, themeResId);
    }

    protected CustomDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) {
        super(context, cancelable, cancelListener);
    }


    //定义CustomDialog的属性设置函数,和AlertDialog类中的对应函数功能相同
    public CustomDialog setTitle(String title) {
        Title = title;
        return this;
    }

    public CustomDialog setMessage(String message) {
        Message = message;
        return this;
    }

    public CustomDialog setCancel(String cancel,IOnCancelListener listener) {
        Cancel = cancel;
        this.cancelListener = listener;
        return this;
    }

    public CustomDialog setConfirm(String confirm,IOnConfirmListener listener) {
        Confirm = confirm;
        this.confirmListener = listener;
        return this;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_custom_dialog);
        //获取当前屏幕宽度
        WindowManager manager = getWindow().getWindowManager();
        Display display = manager.getDefaultDisplay();
        WindowManager.LayoutParams params = getWindow().getAttributes();

        //设置控件宽度为屏幕宽度的80%
        Point size = new Point();
        display.getSize(size);
        params.width = (int)(size.x * 0.8);
        getWindow().setAttributes(params);

        mTvMessage = findViewById(R.id.tv_message);
        mTvTitle = findViewById(R.id.tv_title);
        mBtnCancel = findViewById(R.id.btn_cancel);
        mBtnConfirm = findViewById(R.id.btn_confirm);
        
        // 初始化CustomDialog的各个属性
        if(!TextUtils.isEmpty(Title)){
            mTvTitle.setText(Title);
        }
        if(!TextUtils.isEmpty(Message)){
            mTvMessage.setText(Message);
        }
        if(!TextUtils.isEmpty(Cancel)){
            mBtnCancel.setText(Cancel);
        }
        if(!TextUtils.isEmpty(Confirm)){
            mBtnConfirm.setText(Confirm);
        }
        mBtnCancel.setOnClickListener(this);
        mBtnConfirm.setOnClickListener(this);
    }

    // 复写onClickListner借口的onClikc方法
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_cancel:
                if(cancelListener != null){
                    cancelListener.OnCancel(this);
                    dismiss();
                }
                break;
            case R.id.btn_confirm:
                if(confirmListener != null){
                    confirmListener.OnConfirm(this);
                    dismiss();
                }
                break;
        }
    }
    
    //自定义接口
    public  interface IOnCancelListener{
        void OnCancel(Dialog dialog);
    }
    public interface IOnConfirmListener{
        void OnConfirm(Dialog dialog);
    }
}
  • 第三步,定义一个Activity,在该activity实例化CustomDialog类,复写CustomDialog类中的接口,自定义两个按钮的功能,调用set方法自定义Dialog的各种信息
package com.example.myfirstapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.app.Dialog;
import android.os.Bundle;
import android.view.Display;
import android.view.View;
import android.widget.Button;

import com.example.myfirstapplication.Util.ToastUtil;
import com.example.myfirstapplication.widget.CustomDialog;

public class CustomDialogActivity extends AppCompatActivity {

    private Button mBtnCustomDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_custom_dialog);
        mBtnCustomDialog = findViewById(R.id.btn_CustomDialog);
        mBtnCustomDialog.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                CustomDialog customDialog = new CustomDialog(CustomDialogActivity.this);
                customDialog.setTitle("提示").setMessage("确认删除此项?").setCancel("取消", new CustomDialog.IOnCancelListener() {
                    @Override
                    public void OnCancel(Dialog dialog) {
                        ToastUtil.showMsg(CustomDialogActivity.this,"cancel...");
                    }
                }).setConfirm("确认", new CustomDialog.IOnConfirmListener() {
                    @Override
                    public void OnConfirm(Dialog dialog) {
                        ToastUtil.showMsg(CustomDialogActivity.this,"confirm...");
                    }
                }).show();
            }
        });
    }
}

实现效果: