主頁 > 移動端開發 > Android開發復用代碼

Android開發復用代碼

2022-01-04 10:10:26 移動端開發

目錄

      • 1.設定狀態欄透明
      • 2.Dialog樣式一(是/否)
        • 2.1 Dialog樣式二(新手引導)
        • 2.2 Diaglog點擊其他地方不銷毀
      • 3.從下方彈出頁面
      • 4.封裝的PrefStore
        • 4.1 封裝的PrefStore使用
      • 5.封裝的PicassoUtils
      • 6.封裝的OkHttpUtils
        • 6.1 封裝的OkHttpUtils發送 Post請求
      • 7.簡單配接器
      • 8.抖音的簡單實作
      • 9.封裝的GsonUtils
        • 9.1 GsonUtils使用
      • 10.加載時間
      • 11.獲取螢屏高度/寬度
      • 12.android簡單適配
        • 12.1 懸浮窗權限兼容類
        • 12.2 華為懸浮窗權限兼容實作
        • 12.3 魅族懸浮窗權限兼容實作
        • 12.4 MIUI 懸浮窗權限兼容實作
        • 12.5 360 懸浮窗權限兼容實作
        • 12.6 Rom 工具類
      • 13.擊碎爆破粒子
        • 13.1 擊碎爆破粒子使用
      • 14.WindowUtils工具類
      • 15.常用框架-PhotoView縮放圖片
      • 16.常用框架-加載gif
      • 17.判斷App是第一次啟動
      • 18.sqlite資料庫
        • 18.1 簡單增刪改查
      • 19.流式布局原理
      • 20.監聽螢屏滑動簡單原理
      • 21.Listview任意行生成截圖分享
        • 21.1 分享
      • 22.獲取當前本地apk的版本/版本號名稱
      • 23.ImageView高度根據圖片比例自適應
      • 24.ToastUtil封裝類
        • 24.1 ToastUtil封裝類使用
      • 25.Android四大組件-廣播入門
        • 25.1 BroadcastReceiver-廣播判斷網路狀態
        • 25.2 動態注冊廣播
      • 26.EditText的監聽-TextWatcher三個回呼
      • 27.Activity+viewPage+Fragment+RadioButton實作左右滑動切換頁面
      • 28.估值器-貝塞爾曲線-控制元件封裝-抖音點贊特效

1.設定狀態欄透明

    if (Build.VERSION.SDK_INT >= 21){
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            getWindow().setStatusBarColor(Color.TRANSPARENT);
            int ui = decorView.getSystemUiVisibility();
            ui |=View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; //設定狀態欄中字體的顏色為白色
            decorView.setSystemUiVisibility(ui);
        }
if (Build.VERSION.SDK_INT >= 21){
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            getWindow().setStatusBarColor(Color.BLACK);
            int ui = decorView.getSystemUiVisibility();
            ui |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; //設定狀態欄中字體的顏色為黑色
            decorView.setSystemUiVisibility(ui);
        }

2.Dialog樣式一(是/否)

private void showNormalDialog(final String xid){
        final AlertDialog.Builder normalDialog =
                new AlertDialog.Builder(alldata.this);
        normalDialog.setTitle("洗掉");
        normalDialog.setMessage("確認是否洗掉?");
        normalDialog.setPositiveButton("確定",
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        del(xid);
                    }
                });
        normalDialog.setNegativeButton("關閉",
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(alldata.this, "關閉", Toast.LENGTH_SHORT).show();
                    }
                });
        // 顯示
        normalDialog.show();
    }

2.1 Dialog樣式二(新手引導)

private void newYingdao() {
        LayoutInflater inflater = LayoutInflater.from(courseInfo.this);
        View view = inflater.inflate(R.layout.tips1, null);
        AlertDialog.Builder builder=new AlertDialog.Builder(courseInfo.this,R.style.TransparentDialog);
        builder.setView(view);
        final AlertDialog dialog=builder.create();
        final Button b=view.findViewById(R.id.button4);
        final LinearLayout tips=view.findViewById(R.id.tips);
        tips.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialog.dismiss();
            }
        });
        b.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialog.dismiss();
            }
        });
        dialog.show();

    }
<style name="TransparentDialog" parent="Theme.AppCompat.Dialog">
        <item name="android:windowBackground">@color/transparent</item>
    </style>

2.2 Diaglog點擊其他地方不銷毀

 //創建dialog
                final AlertDialog dialog=builder.create();
                //dialog點擊其他地方不關閉
                dialog.setCancelable(false);

3.從下方彈出頁面

 private void dialogs2() {
        LayoutInflater inflater = LayoutInflater.from(getApplication());
        View view = inflater.inflate(R.layout.home_ulist, null);
        AlertDialog.Builder builder=new AlertDialog.Builder(home.this);
        builder.setView(view);
        final AlertDialog dialog=builder.create();
        Window window = dialog.getWindow();
        final TextView bianji=view.findViewById(R.id.bianji);
        users(bianji);
        window.setGravity(Gravity.BOTTOM);  //此處可以設定dialog顯示的位置
        window.setWindowAnimations(R.style.SelectUpload2);  //添加影片
        dialog.show();
        WindowManager.LayoutParams params =
                dialog.getWindow().getAttributes();
        WindowManager wm = (WindowManager)home.this.getSystemService(Context.WINDOW_SERVICE);
        params.width = WindowManager.LayoutParams.MATCH_PARENT;
        dialog.getWindow().setBackgroundDrawableResource(R.color.white);
        dialog.getWindow().setAttributes(params);
    }
<style name="SelectUpload2">

        <item name="android:windowEnterAnimation">@anim/dialog_enter</item>  //進入時的影片
        <item name="android:windowExitAnimation">@anim/dialog_exit</item>    //退出時的動

    </style>

4.封裝的PrefStore

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;

public class PrefStore {

    private static final String STORE_NAME = "Settings";
    private static Context mContext = null;
    private static PrefStore instance = null;

    public static PrefStore getInstance(Context context) {
        if (instance == null) {
            instance = new PrefStore(context);
        }
        return instance;
    }

    public PrefStore(Context context) {
        mContext = context.getApplicationContext();
    }

    public boolean savePref(String key, String value) {

        if (mContext != null) {
            SharedPreferences pref = mContext.getSharedPreferences(STORE_NAME,
                    Context.MODE_PRIVATE);
            Editor editor = pref.edit();
            editor.putString(key, value);
            editor.commit();
            return true;
        } else {
            return false;
        }

    }

    public String getPref(String key, String defValue) {

        if (mContext != null) {
            SharedPreferences pref = mContext.getSharedPreferences(STORE_NAME,
                    Context.MODE_PRIVATE);
            return pref.getString(key, defValue);
        } else {
            return null;
        }

    }

    public boolean removePref(String key) {
        if (mContext != null) {
            SharedPreferences pref = mContext.getSharedPreferences(STORE_NAME,
                    Context.MODE_PRIVATE);
            Editor editor = pref.edit();
            editor.remove(key);
            editor.commit();
            return true;
        } else {
            return false;
        }
    }

    public boolean clearPref() {
        if (mContext != null) {
            SharedPreferences pref = mContext.getSharedPreferences(STORE_NAME,
                    Context.MODE_MULTI_PROCESS);
            Editor editor = pref.edit();
            editor.clear();
            editor.commit();
            return true;
        } else {
            return false;
        }
    }

}

4.1 封裝的PrefStore使用

PrefStore pref = PrefStore.getInstance(Login.this);
pref.savePref("Phone", USERS.getPhone());
pref.getPref("Uid","1")

5.封裝的PicassoUtils

PicassoUtils.loadImageViewCrop2(ChangeHeadImage.this,localhost_path+ result, imageView);

6.封裝的OkHttpUtils

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.Map;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * OkHttp的封裝工具類
 */
public class OkHttpUtils {
    //TAG
    private static final String TAG = OkHttpUtils.class.getSimpleName();
    //宣告客戶端
    private OkHttpClient client;
    //防止多個執行緒同時訪問所造成的安全隱患
    private volatile static OkHttpUtils okHttpUtils;
    //定義提交型別Json
    private static final MediaType JSON = MediaType.parse("application/json;charset=utf-8");
    //定義提交型別String
    private static final MediaType STRING = MediaType.parse("text/x-markdown;charset=utf-8");
    //子執行緒
    private Handler handler;
    //構造方法
    private OkHttpUtils() {
        //初始化
        client = new OkHttpClient();
        handler = new Handler(Looper.getMainLooper());
    }
    //單例模式
    public static OkHttpUtils getInstance() {
//        OkHttpUtils okUtils = null;
//        if (okHttpUtils == null) {
//            //執行緒同步
//            synchronized (OkHttpUtils.class) {
//                if (okUtils == null) {
//                    okUtils = new OkHttpUtils();
//                    okHttpUtils = okUtils;
//                }
//            }
//        }
        OkHttpUtils okUtils = new OkHttpUtils();
        return okUtils;
    }
    /**
     * 請求的回傳結果是json字串
     * @param jsonValue
     * @param callBack
     */
    private void onsuccessJsonStringMethod(final String jsonValue, final FuncJsonString callBack) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (callBack != null) {
                    try {
                        //決議json
                        callBack.onResponse(jsonValue);
                    } catch (Exception e) {

                    }
                }
            }
        });
    }
    /**
     * 求的回傳結果是json物件
     * @param jsonValue
     * @param callBack
     */
    private void onsuccessJsonObjectMethod(final String jsonValue, final FuncJsonObject callBack) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (callBack != null) {
                    try {
                        callBack.onResponse(new JSONObject(jsonValue));
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }
    /**
     * 求的回傳結果是json陣列
     * @param data
     * @param callBack
     */
    private void onsuccessJsonByteMethod(final byte[] data, final FuncJsonObjectByte callBack) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (callBack != null) {
                    callBack.onResponse(data);
                }
            }
        });
    }
    /**
     * 同步請求,不是很常用,因為會阻塞執行緒
     * @param url
     * @return
     */
    public String syncGetByURL(String url) {
        //構建一個Request請求
        Request request = new Request.Builder().url(url).build();
        Response response = null;
        try {
            //同步請求資料
            response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                return response.body().string();
            }
        } catch (Exception e) {

        }
        return null;
    }

    /**
     * 請求指定的url,回傳的結果是json字串
     *
     * @param url
     * @param callback
     */
    public void syncJsonStringByURL(String url, final FuncJsonString callback) {
        final Request request = new Request.Builder().url(url).build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.i(TAG, "決議失敗");
            }

            //決議成功
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response != null && response.isSuccessful()) {
                    onsuccessJsonStringMethod(response.body().string(), callback);
                }
            }
        });
    }


    /**
     * 請求指定的url,回傳的結果是json物件
     *
     * @param url
     * @param callback
     */
    public void syscJsonObjectByURL(String url, final FuncJsonObject callback) {
        final Request request = new Request.Builder().url(url).build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.i(TAG, "決議失敗");



            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response != null && response.isSuccessful()) {
                    onsuccessJsonObjectMethod(response.body().string(), callback);
                }
            }
        });
    }
    /**
     * 請求指定的url,回傳的結果是byte位元組陣列
     *
     * @param url
     * @param callback
     */
    public void syscGetByteByURL(String url, final FuncJsonObjectByte callback) {
        final Request request = new Request.Builder().url(url).build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.i(TAG, "決議失敗");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response != null && response.isSuccessful()) {
                    onsuccessJsonByteMethod(response.body().bytes(), callback);
                }
            }
        });
    }

    /**
     * 請求指定的url,回傳的結果是Bitmap
     * @param url
     * @param callback
     */
    public void syscDownloadImageByURL(String url, final FuncJsonObjectBitmap callback) {
        final Request request = new Request.Builder().url(url).build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.i(TAG, "決議失敗");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response != null && response.isSuccessful()) {
                    byte[] data = response.body().bytes();
                    Bitmap bitmap = new PicassoUtils.CropImageView().transform(BitmapFactory.decodeByteArray(data, 0, data.length));
                    callback.onResponse(bitmap);
                }
            }
        });
    }
    /**
     * 向服務器提交表單
     * @param url      提交地址
     * @param params   提交資料
     * @param callback 提交回呼
     */
    public void sendDatafForClicent(String url, Map<String, String> params, final FuncJsonObject callback) {
        //表單物件,包含input開始的操作
        FormBody.Builder from = new FormBody.Builder();
        //鍵值對不為空,他的值也不為空
        if (params != null && !params.isEmpty()) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                //裝載表單值
                from.add(entry.getKey(), entry.getValue());
            }
        }
        RequestBody body = from.build();
        //post提交
        Request request = new Request.Builder().url(url).post(body).build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.i(TAG, "決議失敗");
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response != null && response.isSuccessful()) {
                    onsuccessJsonObjectMethod(response.body().string(), callback);
                }
            }
        });
    }

    //todo post請求帶引數
    public void sendDatafForClicent2(String url, Map<String, String> params, final FuncJsonString callback) {
        //表單物件,包含input開始的操作
        FormBody.Builder from = new FormBody.Builder();
        //鍵值對不為空,他的值也不為空
        if (params != null && !params.isEmpty()) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                //裝載表單值
                from.add(entry.getKey(), entry.getValue());
            }
        }
        RequestBody body = from.build();
        //post提交
        Request request = new Request.Builder().url(url).post(body).build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.i(TAG, "決議失敗");
            }
            //決議成功
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response != null && response.isSuccessful()) {
                    onsuccessJsonStringMethod(response.body().string(), callback);
                }
            }
        });
    }
    //todo post請求帶引數
    public void sendDatafForClicent3(String url, Map<String, String> params, final FuncJsonString callback) {
        //表單物件,包含input開始的操作
        FormBody.Builder from = new FormBody.Builder();
        //鍵值對不為空,他的值也不為空
        if (params != null && !params.isEmpty()) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                //裝載表單值
                from.add(entry.getKey(), entry.getValue());
            }
        }
        RequestBody body = from.build();
        //post提交
        Request request = new Request.Builder().url(url).post(body).build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.i(TAG, "決議失敗");
            }
            //決議成功
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response != null && response.isSuccessful()) {
                    onsuccessJsonStringMethod(response.body().string(), callback);
                }
            }
        });
    }
    //todo 無引數Post請求
    public void sendPostNoParams(String url, final FuncJsonString callback) {
        //表單物件,包含input開始的操作
        FormBody.Builder from = new FormBody.Builder();
        RequestBody body = from.build();
        //post提交
        Request request = new Request.Builder().url(url).post(body).build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.i(TAG, "決議失敗");
            }
            //決議成功
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response != null && response.isSuccessful()) {
                    onsuccessJsonStringMethod(response.body().string(), callback);
                }
            }
        });
    }
    /**
     * 回傳字串json的介面
     */
    public interface FuncJsonString {
        //處理我們回傳的結果
        void onResponse(String result);
    }
    /**
     * 回傳json物件的介面
     */
    public interface FuncJsonObject {
        //處理我們回傳的結果
        void onResponse(JSONObject jsonObject);
    }
    /**
     * 回傳json物件的介面
     */
    interface FuncJsonObjectByte {
        //處理我們回傳的結果
        void onResponse(byte[] result);
    }
    /**
     * 回傳json物件的介面
     */
    interface FuncJsonObjectBitmap {
        //處理我們回傳的結果
        void onResponse(Bitmap bitmap);
    }
}


6.1 封裝的OkHttpUtils發送 Post請求

	//todo post請求
    private void Post(){
        blogInfos.clear();
        Map<String,String> hs=new HashMap<>();
        hs.put("uname", String.valueOf("admin-all"));
        OkHttpUtils okHttp = OkHttpUtils.getInstance();
        okHttp.sendDatafForClicent2(getAllXiangList,hs, new OkHttpUtils.FuncJsonString() {
            @Override
            public void onResponse(String result) {
                JsonParser parser = new JsonParser();
                JsonArray jsonArray = parser.parse(result).getAsJsonArray();
                Gson gson = new Gson();
                PrefStore pref = PrefStore.getInstance(mydata.this);
                for (JsonElement Title : jsonArray) {
                    Xiangzi g= gson.fromJson(Title, Xiangzi.class);
                    if(g.getUserid()==Integer.valueOf(pref.getPref("Uid","1"))){
                        blogInfos.add(g);
                    }

                }
                initListView();
            }
        });

    }

7.簡單配接器

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.example.sushe.R;
import com.example.sushe.model.Xiangzi;
import com.example.sushe.url.url;
import com.example.sushe.utils.OkHttpUtils;
import com.example.sushe.utils.PrefStore;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class ListAdapter extends BaseAdapter {
    private List<Xiangzi> mList;
    private Context mContext;
    public ListAdapter(Context mContext, List<Xiangzi> mList) {
        this.mContext=mContext;
        this.mList=mList;
    }

    @Override
    public int getCount() {
        return mList!=null?mList.size():0;
    }

    @Override
    public Object getItem(int position) {
        return mList!=null?mList.get(position):null;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.bloglist_item, parent, false);
            holder = new ViewHolder(convertView);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        final ViewHolder finalHolder = holder;
       

        return convertView;
    }
    

    private class ViewHolder{
        LinearLayout root;
        public ViewHolder(View view) {
            if(view==null)
                return;
            root= view.findViewById(R.id.root);
            
        }
    }
}

8.抖音的簡單實作

implementation 'com.shuyu:GSYVideoPlayer:5.0.2'
import android.annotation.TargetApi;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.example.sushe.R;
import com.shuyu.gsyvideoplayer.GSYVideoManager;
import com.shuyu.gsyvideoplayer.utils.OrientationUtils;
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer;

import java.util.ArrayList;

import static com.example.sushe.url.url.localhost_path;


public class MainActivity extends AppCompatActivity {
    private static final String TAG = "--------------->";
    private RecyclerView mRecyclerView;
    private MyAdapter mAdapter;
    MyLayoutManager myLayoutManager;
    private OrientationUtils orientationUtils;
    private ArrayList<String> ls = new ArrayList<String>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dys);
//        if (Build.VERSION.SDK_INT >= 21){
//            View decorView = getWindow().getDecorView();
//            decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
//            getWindow().setStatusBarColor(Color.TRANSPARENT);
//            int ui = decorView.getSystemUiVisibility();
//            ui |=View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; //設定狀態欄中字體的顏色為黑色
//            decorView.setSystemUiVisibility(ui);
//        }

        ls.add(localhost_path+"/vedio/mm1.mp4");
        ls.add(localhost_path+"/vedio/mm5.mp4");
        ls.add(localhost_path+"/vedio/mm3.mp4");
        ls.add(localhost_path+"/vedio/mm1.mp4");
        ls.add(localhost_path+"/vedio/mm5.mp4");
        ls.add(localhost_path+"/vedio/mm3.mp4");
        initView();
        initListener();
    }
    private void initView() {
        mRecyclerView = findViewById(R.id.recycler);
        myLayoutManager = new MyLayoutManager(this, OrientationHelper.VERTICAL,false);

        mAdapter = new MyAdapter();
        mRecyclerView.setLayoutManager(myLayoutManager);
        mRecyclerView.setAdapter(mAdapter);
    }

    private void initListener(){
        myLayoutManager.setOnViewPagerListener(new OnViewPagerListener() {
            @Override
            public void onInitComplete() {

            }

            @Override
            public void onPageRelease(boolean isNext, int position) {
                Log.e(TAG,"釋放位置:"+position +" 下一頁:"+isNext);
                Toast.makeText(MainActivity.this,"23", Toast.LENGTH_SHORT).show();
                releaseVideo(position);
            }

            @Override
            public void onPageSelected(int position, boolean isNext) {
                Log.e(TAG,"釋放位置:"+position +" 下一頁:"+isNext);
                Toast.makeText(MainActivity.this,"23", Toast.LENGTH_SHORT).show();
                playVideo(position);
            }
        });
    }

    class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
             public MyAdapter(){
        }
        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view_pager,parent,false);

            return new ViewHolder(view);
        }

        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            holder.t.setVisibility(View.GONE);
//            Toast.makeText(MainActivity.this,"23",Toast.LENGTH_SHORT).show();
            //增加封面
            ImageView imageView = new ImageView(MainActivity.this);
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
           // imageView.setImageResource(R.drawable.p10);
            holder.videoPlayer.setThumbImageView(imageView);
            //增加title
            holder.videoPlayer.getTitleTextView().setVisibility(View.VISIBLE);
            //設定回傳鍵
            holder.videoPlayer.getBackButton().setVisibility(View.VISIBLE);
            //設定旋轉
            orientationUtils = new OrientationUtils(MainActivity.this, holder.videoPlayer);
            //設定全屏按鍵功能,這是使用的是選擇螢屏,而不是全屏
            holder.videoPlayer.getFullscreenButton().setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    orientationUtils.resolveByClick();
                }
            });
            //是否可以滑動調整
            holder.videoPlayer.setIsTouchWiget(true);
            //設定回傳按鍵功能
            holder.videoPlayer.getBackButton().setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onBackPressed();
                }
            });
            holder.videoPlayer.startPlayLogic();
        }

        @Override
        public int getItemCount() {
            return 15;
        }

        public class ViewHolder extends RecyclerView.ViewHolder{

            StandardGSYVideoPlayer videoPlayer;
            LinearLayout z1;
            TextView t;

            public ViewHolder(View itemView) {
                super(itemView);
                videoPlayer = itemView.findViewById(R.id.video_view);
                z1=itemView.findViewById(R.id.z1);
                t=itemView.findViewById(R.id.textView16);
            }

        }
    }

    private void releaseVideo(int index){
        View itemView = mRecyclerView.getChildAt(index);
        final StandardGSYVideoPlayer videoPlayer = itemView.findViewById(R.id.video_view);
        videoPlayer.onVideoPause();
    }


    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    private void playVideo(int position) {
        View itemView = mRecyclerView.getChildAt(0);
        final StandardGSYVideoPlayer videoPlayer = itemView.findViewById(R.id.video_view);
        final TextView z1=itemView.findViewById(R.id.textView16);
      //  z1.setText("223");
        videoPlayer.startPlayLogic();

    }




    @Override
    protected void onDestroy() {
        super.onDestroy();
        GSYVideoManager.releaseAllVideos();
        if (orientationUtils != null) {
            orientationUtils.releaseListener();
        }
    }

}
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.PagerSnapHelper;
import android.support.v7.widget.RecyclerView;
import android.view.View;

public class MyLayoutManager extends LinearLayoutManager implements RecyclerView.OnChildAttachStateChangeListener {
    //位移,用來判斷移動方向
    private int mDrift;

    private PagerSnapHelper mPagerSnapHelper;
    private OnViewPagerListener mOnViewPagerListener;

    public MyLayoutManager(Context context) {
        super(context);
    }

    public MyLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
        mPagerSnapHelper = new PagerSnapHelper();
    }

    @Override
    public void onAttachedToWindow(RecyclerView view) {

        view.addOnChildAttachStateChangeListener(this);
        mPagerSnapHelper.attachToRecyclerView(view);
        super.onAttachedToWindow(view);
    }

    /**
     * 當Item添加進來了  呼叫這個方法
     * 播放視頻操作 即將要播放的是上一個視頻 還是下一個視頻
     * @param view
     */
    @Override
    public void onChildViewAttachedToWindow(@NonNull View view) {
        if (mDrift > 0) {
//            向上
            if (mOnViewPagerListener != null) {
                mOnViewPagerListener.onPageSelected(getPosition(view), true);
            }

        } else {
            if (mOnViewPagerListener != null) {
                mOnViewPagerListener.onPageSelected(getPosition(view), false);
            }
        }
    }

    public void setOnViewPagerListener(OnViewPagerListener mOnViewPagerListener) {
        this.mOnViewPagerListener = mOnViewPagerListener;
    }

    /**
     * OnScrollListener.SCROLL_STATE_FLING; //螢屏處于甩動狀態
     * OnScrollListener.SCROLL_STATE_IDLE; //停止滑動狀態
     * OnScrollListener.SCROLL_STATE_TOUCH_SCROLL;// 手指接觸狀態
     *
     * @param state
     */
    @Override
    public void onScrollStateChanged(int state) {
        switch (state) {
            case RecyclerView.SCROLL_STATE_IDLE:
                View view = mPagerSnapHelper.findSnapView(this);
                int position = getPosition(view);
                if (mOnViewPagerListener != null) {
                    mOnViewPagerListener.onPageSelected(position, position == getItemCount() - 1);

                }


                break;
            default:
        }
        super.onScrollStateChanged(state);
    }

    /**
     * 暫停播放操作
     * @param view
     */
    @Override
    public void onChildViewDetachedFromWindow(@NonNull View view) {
       // sflag=1;
        if (mDrift >= 0) {
            if (mOnViewPagerListener != null) {
          //      mOnViewPagerListener.onPageRelease(true, getPosition(view));
            }
        } else {
            if (mOnViewPagerListener != null) {
         //       mOnViewPagerListener.onPageRelease(false, getPosition(view));
            }
        }
    }


    /**
     * 監聽移動方向
     * @param dy
     * @param recycler
     * @param state
     * @return
     */
    @Override
    public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
        this.mDrift = dy;
        return super.scrollVerticallyBy(dy, recycler, state);
    }

    @Override
    public boolean canScrollVertically() {
        return true;
    }
}

public interface OnViewPagerListener {
    /**
     * 初始化完成
     */
    void onInitComplete();

    /**
     * 釋放的監聽
     * @param isNext
     * @param position
     */
    void onPageRelease(boolean isNext, int position);

    /**
     * 選中的監聽以及判斷是否滑動到底部
     * @param position
     * @param isBottom
     */
    void onPageSelected(int position, boolean isBottom);


}

<?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"
    android:id="@+id/root_view"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="vertical">

        <com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
            android:id="@+id/video_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="45dp"
                android:gravity="center"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/textView2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:layout_marginRight="10dp"
                    android:textSize="19dp"
                    android:textStyle="bold"
                    android:text="學習"
                    android:textColor="#FBF8F8" />

                <TextView
                    android:id="@+id/textView50"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:layout_marginLeft="10dp"
                    android:textSize="19dp"
                    android:text="娛樂"
                    android:textStyle="bold"
                    android:textColor="#FBF8F8" />
            </LinearLayout>
        </com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer>


        <LinearLayout
            android:id="@+id/z1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:layout_marginTop="-320dp"
            android:layout_marginRight="15dp"
            android:gravity="right"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="left"
                android:orientation="vertical">

                <ImageView
                    android:id="@+id/imageView7"
                    android:layout_width="45dp"
                    android:layout_height="30dp" />

                <TextView
                    android:id="@+id/textView16"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="3dp"
                    android:layout_marginLeft="-5dp"
                    android:gravity="center"
                    android:text=""
                    android:textColor="#ffffff"
                    android:textSize="13.5dp" />

                <ImageView
                    android:id="@+id/imageView8"
                    android:layout_width="37dp"
                    android:layout_height="37dp"
                    android:layout_marginTop="15dp"
                    android:background="@drawable/pls" />

                <TextView
                    android:id="@+id/textView17"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="3dp"
                    android:layout_marginLeft="-5dp"
                    android:gravity="center"
                    android:text=""
                    android:textColor="#ffffff"
                    android:textSize="13.5dp" />

                <ImageView
                    android:id="@+id/imageView10"
                    android:layout_width="37dp"
                    android:layout_height="37dp"
                    android:layout_marginTop="15dp"
                    android:background="@drawable/zhuanfa" />

                <TextView
                    android:id="@+id/textView42"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="3dp"
                    android:layout_marginLeft="-3dp"
                    android:gravity="center"
                    android:text="0"
                    android:textColor="#ffffff"
                    android:textSize="13.5dp" />
            </LinearLayout>

        </LinearLayout>

        <LinearLayout
            android:id="@+id/fs"
            android:layout_width="270dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="-5dp"
            android:orientation="vertical">

                <LinearLayout
                    android:id="@+id/xiazai"
                    android:layout_width="wrap_content"
                    android:layout_height="20dp"
                    android:orientation="horizontal"
                    android:visibility="gone"
                    >
                    <ImageView
                        android:id="@+id/imageView14"
                        android:layout_width="20dp"
                        android:layout_height="20dp"
                        android:background="@drawable/xiazai" />

                    <TextView
                        android:id="@+id/textView68"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:textColor="#ffffff"
                        android:textStyle="bold"
                        android:text="點擊下載原始碼決議" />

                </LinearLayout>




            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="35dp"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/textView43"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text=""
                    android:textStyle="bold"
                    android:textColor="#ffffff"
                    android:textSize="17.5dp" />

                <TextView
                    android:id="@+id/textView44"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="5dp"
                    android:text=" 2020/12/18/ 22:54:01"
                    android:textColor="#EAE4E4"
                    android:textSize="16dp" />
            </LinearLayout>

            <TextView
                android:id="@+id/textView38"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="青春就是用來綻放的"
                android:textColor="#EFEDED"
                android:textSize="16dp" />
        </LinearLayout>

    </LinearLayout>



    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#000000"
        android:visibility="gone"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/textView41"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="15dp"
            android:layout_marginBottom="15dp"
            android:text="留下你的精彩評論吧"
            android:textSize="17dp"
            android:layout_marginLeft="15dp"
            android:textColor="#ECEBEB" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="right"
            android:layout_marginTop="15dp"
            android:orientation="horizontal">

            <ImageView
                android:id="@+id/imageView9"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_marginRight="15dp"
                android:layout_gravity="right"
                android:layout_marginTop="15dp"
                android:background="@drawable/xiaolian" />
        </LinearLayout>
    </LinearLayout>


</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<com.example.amusic.love.Love_dy xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/los1"
    android:background="#000000"
    android:layout_width="match_parent"
    android:layout_marginTop="-2dp"
    android:layout_height="match_parent">


    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"

        android:layout_height="match_parent">

    </android.support.v7.widget.RecyclerView>

    <VideoView
        android:id="@+id/line_bottom"
        android:layout_width="match_parent"
        android:layout_height="1px"

        android:background="#000000" />


</com.example.amusic.love.Love_dy>

9.封裝的GsonUtils


import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;

import java.util.ArrayList;
import java.util.List;

public class GsonUtils {

    private static Gson gson;

    static {
        gson = new Gson();
    }

    public static <T> T jsonToBean(String gsonString, Class<T> cls) {
        T t = null;
        if (gson != null) {
            t = gson.fromJson(gsonString, cls);
        }
        return t;
    }

    public static String beanToJson(Object object) {
        String gsonString = null;
        if (gson != null) {
            gsonString = gson.toJson(object);
        }
        return gsonString;
    }

    /**
     * 王正瑞
     * @date 2021/12/21 23:12
     * 轉成list 解決泛型問題
     * @param json json
     * @param cls  類
     * @param <T>  T
     * @return T串列
     */
    public static <T> List<T> jsonGsonToList(String json, Class<T> cls) {
        Gson gson = new Gson();
        List<T> list = new ArrayList<>();
        JsonArray array = new JsonParser().parse(json).getAsJsonArray();
        for (final JsonElement elem : array) {
            list.add(gson.fromJson(elem, cls));
        }
        return list;
    }

}

9.1 GsonUtils使用

blog=GsonUtils.jsonGsonToList(result,blog.class);

10.加載時間

//todo 加載時間
    public static String disposeTime() {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.DAY_OF_MONTH, 0);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        String time = sdf.format(c.getTime());
        return time;
    }

11.獲取螢屏高度/寬度

//todo 獲取螢屏高度呼叫此函式
    public static int getAndroiodScreenHeigh(WindowManager wm) {
        DisplayMetrics dm = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(dm);
        int height = dm.heightPixels;       // 螢屏高度(像素)
        return height;
    }
    //todo 獲取螢屏寬度呼叫此函式
    public static int getAndroiodScreenWidth(WindowManager wm) {
        DisplayMetrics dm = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(dm);
        int width = dm.widthPixels;         // 螢屏寬度(像素)
        return width;
    }

12.android簡單適配

private void checkState() {
        boolean hasAccessibility = AccessibilityUtil.isSettingOpen(AutoTouchService.class, MainActivity.this);
        boolean hasWinPermission = FloatWinPermissionCompat.getInstance().check(this);
        if (hasAccessibility) {
            if (hasWinPermission) {
                tvStart.setText(STRING_START);
            } else {
                tvStart.setText(STRING_ALERT);
            }
        } else {
            tvStart.setText(STRING_ACCESS);
        }
    }

12.1 懸浮窗權限兼容類

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Build;
import android.util.Log;

import java.lang.reflect.Method;

/**
 * 懸浮窗權限兼容類
 * 參考了該專案的代碼:https://github.com/zhaozepeng/FloatWindowPermission
 */
public class FloatWinPermissionCompat {

    private static final String TAG = FloatWinPermissionCompat.class.getSimpleName();

    public static FloatWinPermissionCompat getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private static class SingletonHolder {
        private static final FloatWinPermissionCompat INSTANCE = new FloatWinPermissionCompat();
    }

    private CompatImpl compat;

    private FloatWinPermissionCompat() {
        // 6.0 以下的處理
        if (Build.VERSION.SDK_INT < 23) {
            if (RomUtils.isMiui()) {
                compat = new MiuiCompatImpl();
            } else if (RomUtils.isMeizu()) {
                compat = new MeizuCompatImpl();
            } else if (RomUtils.isHuawei()) {
                compat = new HuaweiCompatImpl();
            } else if (RomUtils.isQihoo()) {
                compat = new QihooCompatImpl();
            } else {
                // Android6.0以下未兼容機型默認實作
                compat = new BelowApi23CompatImpl() {
                    @Override
                    public boolean isSupported() {
                        return false;
                    }

                    @Override
                    public boolean apply(Context context) {
                        return false;
                    }
                };
            }
        } else {
            // 魅族單獨適配一下
            if (RomUtils.isMeizu()) {
                compat = new MeizuCompatImpl();
            } else {
                // 6.0 版本之后由于 google 增加了對懸浮窗權限的管理,所以方式就統一了
                compat = new Api23CompatImpl();
            }
        }
    }

    /**
     * 檢查是否已開啟懸浮窗權限
     *
     * @return
     */
    public boolean check(Context context) {
        return compat.check(context);
    }

    /**
     * 是否支持打開懸浮窗授權界面
     *
     * @return
     */
    public boolean isSupported() {
        return compat.isSupported();
    }


    /**
     * 檢測 op 值判斷懸浮窗是否已授權
     *
     * @param context
     * @param op
     * @return
     */
    @TargetApi(Build.VERSION_CODES.KITKAT)
    public static boolean checkOp(Context context, int op) {
        final int version = Build.VERSION.SDK_INT;
        if (version >= 19) {
            AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
            try {
                Class clazz = AppOpsManager.class;
                Method method = clazz.getDeclaredMethod("checkOp", int.class, int.class, String.class);
                return AppOpsManager.MODE_ALLOWED == (int) method.invoke(manager, op, Binder.getCallingUid(), context.getPackageName());
            } catch (Exception e) {
                Log.e(TAG, Log.getStackTraceString(e));
            }
        } else {
            Log.e(TAG, "Below API 19 cannot invoke!");
        }
        return false;
    }


    public interface CompatImpl {
        /**
         * 檢測是否已經權限
         *
         * @param context
         * @return
         */
        boolean check(Context context);

        /**
         * 對于該 ROM 是否已經做了懸浮窗授權的兼容支持
         *
         * @return
         */
        boolean isSupported();

        /**
         * 申請權限
         *
         * @param context
         * @return
         */
        boolean apply(Context context);
    }

    /**
     * 申請懸浮窗權限
     *
     * @return 是否成功打開授權界面
     */
    public boolean apply(Context context) {
        if (!isSupported()) {
            return false;
        }
        forResult = false;
        this.context = context;
        return compat.apply(context);
    }

    public boolean apply(Activity activity) {
        if (activity == null || !isSupported()) {
            return false;
        }
        this.activity = activity;
        this.context = activity.getApplicationContext();
        forResult = true;
        return compat.apply(context);
    }

    public static final int REQUEST_CODE_SYSTEM_WINDOW = 1001;
    private Activity activity;
    private Context context;
    private boolean forResult = false;

    public void startActivity(Intent intent) {
        try {
            if (intent == null || context == null) {
                return;
            }
            if (!forResult) {
                context.startActivity(intent);
            } else {
                if (activity != null) {//為什么打開權限設定頁就執行了onActivityResult?
                    activity.startActivityForResult(intent, REQUEST_CODE_SYSTEM_WINDOW);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

12.2 華為懸浮窗權限兼容實作

import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

/**
 * 華為懸浮窗權限兼容實作
 */
public class HuaweiCompatImpl extends BelowApi23CompatImpl {

    private static final String TAG = "HuaweiCompatImpl";

    @Override
    public boolean isSupported() {
        return true;
    }

    @Override
    public boolean apply(Context context) {
        try {
            Intent intent = new Intent();
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            // ComponentName comp = new ComponentName("com.huawei.systemmanager","com.huawei.permissionmanager.ui.MainActivity");//華為權限管理
            // "com.huawei.permissionmanager.ui.SingleAppActivity");//華為權限管理,跳轉到指定app的權限管理位置需要華為介面權限,未解決
            ComponentName comp = new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.addviewmonitor.AddViewMonitorActivity");//懸浮窗管理頁面
            intent.setComponent(comp);
            if (RomUtils.getEmuiVersion() == 3.1) {
                //emui 3.1 的適配
                startActivity(context, intent);
            } else {
                //emui 3.0 的適配
                comp = new ComponentName("com.huawei.systemmanager", "com.huawei.notificationmanager.ui.NotificationManagmentActivity");//懸浮窗管理頁面
                intent.setComponent(comp);
                startActivity(context, intent);
            }
        } catch (SecurityException e) {
            Intent intent = new Intent();
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            ComponentName comp = new ComponentName("com.huawei.systemmanager",
                    "com.huawei.permissionmanager.ui.MainActivity");//華為權限管理,跳轉到本app的權限管理頁面,這個需要華為介面權限,未解決
            //ComponentName comp = new ComponentName("com.huawei.systemmanager","com.huawei.systemmanager.addviewmonitor.AddViewMonitorActivity");//懸浮窗管理頁面
            intent.setComponent(comp);
            startActivity(context, intent);
            Log.e(TAG, Log.getStackTraceString(e));
        } catch (ActivityNotFoundException e) {
            /**
             * 手機管家版本較低 HUAWEI SC-UL10
             */
            Intent intent = new Intent();
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            ComponentName comp = new ComponentName("com.Android.settings", "com.android.settings.permission.TabItem");//權限管理頁面 android4.4
            //ComponentName comp = new ComponentName("com.android.settings","com.android.settings.permission.single_app_activity");//此處可跳轉到指定app對應的權限管理頁面,但是需要相關權限,未解決
            intent.setComponent(comp);
            startActivity(context, intent);
            Log.e(TAG, Log.getStackTraceString(e));
        } catch (Exception e) {
            //拋出例外時提示資訊
            Log.e(TAG, Log.getStackTraceString(e));
        }
        return false;
    }

    private void startActivity(Context context, Intent intent) {
        context.startActivity(intent);
        //FloatWinPermissionCompat.getInstance().startActivity(intent);
    }

}

12.3 魅族懸浮窗權限兼容實作

import android.content.Context;
import android.content.Intent;
import android.util.Log;

/**
 * 魅族懸浮窗權限兼容實作
 */
public class MeizuCompatImpl extends BelowApi23CompatImpl {

    @Override
    public boolean isSupported() {
        return true;
    }

    /**
     * 去魅族權限申請頁面
     */
    @Override
    public boolean apply(Context context) {
        try {
            Intent intent = new Intent("com.meizu.safe.security.SHOW_APPSEC");
            intent.setClassName("com.meizu.safe", "com.meizu.safe.security.AppSecActivity");
            intent.putExtra("packageName", context.getPackageName());
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(context,intent);
        } catch (Exception e) {
            try {
                Log.d("dq","flyme 6.2.5+,apply permission failed");
                Api23CompatImpl.commonROMPermissionApplyInternal(context);
            } catch (Exception eFinal) {
                eFinal.printStackTrace();
            }
        }
        return true;
    }

    private void startActivity(Context context, Intent intent) {
        context.startActivity(intent);
        //FloatWinPermissionCompat.getInstance().startActivity(intent);
    }

}

12.4 MIUI 懸浮窗權限兼容實作

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.provider.Settings;
import android.util.Log;

/**
 * MIUI 懸浮窗權限兼容實作
 */
public class MiuiCompatImpl extends BelowApi23CompatImpl {

    private static final String TAG = "MiuiCompatImpl";
    private int miuiVersion = -1;

    public MiuiCompatImpl() {
        miuiVersion = RomUtils.getMiuiVersion();
    }

    @Override
    public boolean isSupported() {
        return miuiVersion >= 5 && miuiVersion <= 8;
    }

    @Override
    public boolean apply(Context context) {
        if (miuiVersion == 5) {
            return applyV5(context);
        } else if (miuiVersion == 6) {
            return applyV6(context);
        } else if (miuiVersion == 7) {
            return applyV7(context);
        } else if (miuiVersion == 8) {
            return applyV8(context);
        } else {
            Log.e(TAG, "this is a special MIUI rom version, its version code " + miuiVersion);
        }
        return false;
    }

    /**
     * MIUI8下申請權限
     *
     * @param context
     */
    private boolean applyV8(Context context) {
        Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
        intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
        intent.putExtra("extra_pkgname", context.getPackageName());
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (RomUtils.isIntentAvailable(context, intent)) {
            startActivity(context, intent);
            return true;
        }

        intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
        intent.setPackage("com.miui.securitycenter");
        intent.putExtra("extra_pkgname", context.getPackageName());
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (RomUtils.isIntentAvailable(context, intent)) {
            startActivity(context, intent);
            return true;
        } else {
            // 小米平板2上沒有安全中心,可以打開應用詳情頁開啟權限
            //I/ActivityManager: START u0 {flg=0x14000000 cmp=com.android.settings/.applications.InstalledAppDetailsTop (has extras)}
            return applyV5(context);
        }
    }

    /**
     * MIUI7下申請權限
     *
     * @param context
     */
    private boolean applyV7(Context context) {
        Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
        intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
        intent.putExtra("extra_pkgname", context.getPackageName());
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (RomUtils.isIntentAvailable(context, intent)) {
            startActivity(context, intent);
            return true;
        } else {
            Log.e(TAG, "applyV7 Intent is not available!");
        }
        return false;
    }

    /**
     * MIUI6下申請權限
     *
     * @param context
     */
    private boolean applyV6(Context context) {
        Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
        intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
        intent.putExtra("extra_pkgname", context.getPackageName());
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (RomUtils.isIntentAvailable(context, intent)) {
            startActivity(context, intent);
            return true;
        } else {
            Log.e(TAG, "applyV6 Intent is not available!");
        }
        return false;
    }

    /**
     * MIUI5下申請權限
     *
     * @param context
     */
    private boolean applyV5(Context context) {
        Intent intent;
        String packageName = context.getPackageName();
        intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", packageName, null);
        intent.setData(uri);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (RomUtils.isIntentAvailable(context, intent)) {
            startActivity(context, intent);
            return true;
        } else {
            Log.e(TAG, "applyV5 intent is not available!");
        }
        return false;
        //設定頁面在應用詳情頁面
    }

    private void startActivity(Context context, Intent intent) {
        context.startActivity(intent);
        //FloatWinPermissionCompat.getInstance().startActivity(intent);
    }
}

12.5 360 懸浮窗權限兼容實作

import android.content.Context;
import android.content.Intent;
import android.util.Log;

/**
 * 360 懸浮窗權限兼容實作
 */
public class QihooCompatImpl extends BelowApi23CompatImpl {

    private static final String TAG = "QihooCompatImpl";

    @Override
    public boolean isSupported() {
        return true;
    }

    @Override
    public boolean apply(Context context) {
        Intent intent = new Intent();
        intent.setClassName("com.android.settings", "com.android.settings.Settings$OverlaySettingsActivity");
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (RomUtils.isIntentAvailable(context, intent)) {
            startActivity(context,intent);
            return true;
        } else {
            intent.setClassName("com.qihoo360.mobilesafe", "com.qihoo360.mobilesafe.ui.index.appEnterActivity");
            if (RomUtils.isIntentAvailable(context, intent)) {
                startActivity(context,intent);
                return true;
            } else {
                Log.e(TAG, "can't open permission page with particular name, please use " +
                        "\"adb shell dumpsys activity\" command and tell me the name of the float window permission page");
            }
        }
        return false;
    }

    private void startActivity(Context context, Intent intent) {
        context.startActivity(intent);
        //FloatWinPermissionCompat.getInstance().startActivity(intent);
    }

}

12.6 Rom 工具類

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Rom 工具類
 */
public class RomUtils {

    private static final String TAG = RomUtils.class.getSimpleName();

    /**
     * 獲取 emui 版本號
     *
     * @return
     */
    public static double getEmuiVersion() {
        try {
            String emuiVersion = getSystemProperty("ro.build.version.emui");
            String version = emuiVersion.substring(emuiVersion.indexOf("_") + 1);
            return Double.parseDouble(version);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 4.0;
    }

    /**
     * 獲取小米 rom 版本號,獲取失敗回傳 -1
     *
     * @return miui rom version code, if fail , return -1
     */
    public static int getMiuiVersion() {
        String version = getSystemProperty("ro.miui.ui.version.name");
        if (version != null) {
            try {
                return Integer.parseInt(version.substring(1));
            } catch (Exception e) {
                Log.e(TAG, "getInstance miui version code error, version : " + version);
            }
        }
        return -1;
    }

    /**
     * System.getProperties()不回傳與 getprop 相同的屬性,要獲取 getprop 屬性,請嘗試使用 Runtime.exec() 執行 getprop 并讀取其標準輸出,
     *
     * @param propName
     * @return
     */
    public static String getSystemProperty(String propName) {
        String line;
        BufferedReader input = null;
        try {
            Process p = Runtime.getRuntime().exec("getprop " + propName);
            input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
            line = input.readLine();
            input.close();
        } catch (IOException ex) {
            Log.e(TAG, "Unable to read sysprop " + propName, ex);
            return null;
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    Log.e(TAG, "Exception while closing InputStream", e);
                }
            }
        }
        return line;
    }

    /**
     * 是否OPPO系統
     *
     * @return
     */
    public static boolean isOppo() {
        return !TextUtils.isEmpty(getSystemProperty("ro.build.version.opporom"));
    }

    /**
     * 是否VIVO系統
     *
     * @return
     */
    public static boolean isVivo() {
        return !TextUtils.isEmpty(getSystemProperty("ro.vivo.os.version"));
    }

    /**
     * 是否華為系統
     *
     * @return
     */
    public static boolean isHuawei() {
        return Build.MANUFACTURER.contains("HUAWEI");
    }

    /**
     * 是否小米系統
     *
     * @return
     */
    public static boolean isMiui() {
        return !TextUtils.isEmpty(getSystemProperty("ro.miui.ui.version.name"));
    }

    /**
     * 是否魅族系統
     *
     * @return
     */
    public static boolean isMeizu() {
        String meizuFlymeOSFlag = getSystemProperty("ro.build.display.id");
        return !TextUtils.isEmpty(meizuFlymeOSFlag) && meizuFlymeOSFlag.toLowerCase().contains("flyme");
    }

    /**
     * 是否 360 系統
     *
     * @return
     */
    public static boolean isQihoo() {
        return Build.MANUFACTURER.contains("QiKU");
    }


    /**
     * 判斷 Intent 是否有效
     *
     * @param context
     * @param intent
     * @return
     */
    public static boolean isIntentAvailable(Context context, Intent intent) {
        if (intent == null) {
            return false;
        }
        return context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
    }


}

13.擊碎爆破粒子

public class ExplosionAnimator extends ValueAnimator {
    public static final int DEFAULT_DURATION = 1500;
    private Particle[][] mParticles;
    private Paint mPaint;
    private View mContainer;

    public ExplosionAnimator(View view, Bitmap bitmap, Rect bound) {

        mPaint = new Paint();
        mContainer = view;

        setFloatValues(0.0f, 1.0f);
        setDuration(DEFAULT_DURATION);

        mParticles = generateParticles(bitmap, bound);
    }

    private Particle[][] generateParticles(Bitmap bitmap, Rect bound) {
        int w = bound.width();
        int h = bound.height();

        int partW_Count = w / Particle.PART_WH; //橫向個數
        int partH_Count = h / Particle.PART_WH; //豎向個數

        int bitmap_part_w = bitmap.getWidth() / partW_Count;
        int bitmap_part_h = bitmap.getHeight() / partH_Count;

        Particle[][] particles = new Particle[partH_Count][partW_Count];
        Point point = null;
        for (int row = 0; row < partH_Count; row ++) { //行
            for (int column = 0; column < partW_Count; column ++) { //列
                //取得當前粒子所在位置的顏色
                int color = bitmap.getPixel(column * bitmap_part_w, row * bitmap_part_h);

                point = new Point(column, row); //x是列,y是行

                particles[row][column] = Particle.generateParticle(color, bound, point);
            }
        }

        return particles;
    }

    public void draw(Canvas canvas) {
        if(!isStarted()) { //影片結束時停止
            return;
        }
        for (Particle[] particle : mParticles) {
            for (Particle p : particle) {
                p.advance((Float) getAnimatedValue());
                mPaint.setColor(p.color);
//                mPaint.setAlpha((int) (255 * p.alpha)); //只是這樣設定,透明色會顯示為黑色
                mPaint.setAlpha((int) (Color.alpha(p.color) * p.alpha)); //這樣透明顏色就不是黑色了
                canvas.drawCircle(p.cx, p.cy, p.radius, mPaint);
            }
        }

        mContainer.invalidate();
    }

    @Override
    public void start() {
        super.start();
        mContainer.invalidate();
    }
}
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;

import com.example.amusic.utils.posui.utils.Utils;

import java.util.ArrayList;

public class ExplosionField extends View {
    private static final String TAG = "ExplosionField";
    private static final Canvas mCanvas = new Canvas();
    private ArrayList<ExplosionAnimator> explosionAnimators;
    private OnClickListener onClickListener;

    public ExplosionField(Context context) {
        super(context);
        init();
    }

    public ExplosionField(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    private void init() {
        explosionAnimators = new ArrayList<ExplosionAnimator>();

        attach2Activity((Activity) getContext());
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (ExplosionAnimator animator : explosionAnimators) {
            animator.draw(canvas);
        }
    }

    /**
     * 爆破
     * @param view 使得該view爆破
     */
    public void explode(final View view) {
        Rect rect = new Rect();
        view.getGlobalVisibleRect(rect); //得到view相對于整個螢屏的坐標
        rect.offset(0, -Utils.dp2px(25)); //去掉狀態欄高度

        final ExplosionAnimator animator = new ExplosionAnimator(this, createBitmapFromView(view), rect);
        explosionAnimators.add(animator);

        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                view.animate().alpha(0f).setDuration(150).start();
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                view.animate().alpha(1f).setDuration(150).start();

                //影片結束時從影片集中移除
                explosionAnimators.remove(animation);
                animation = null;
            }
        });
        animator.start();
    }

    private Bitmap createBitmapFromView(View view) {
        /*
         * 為什么屏蔽以下代碼段?
         * 如果ImageView直接得到位圖,那么當它設定背景(backgroud)時,不會讀取到背景顏色
         */
//        if (view instanceof ImageView) {
//            Drawable drawable = ((ImageView)view).getDrawable();
//            if (drawable != null && drawable instanceof BitmapDrawable) {
//                return ((BitmapDrawable) drawable).getBitmap();
//            }
//        }

        //view.clearFocus(); //不同焦點狀態顯示的可能不同——(azz:不同就不同有什么關系?)

        Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);

        if (bitmap != null) {
            synchronized (mCanvas) {
                mCanvas.setBitmap(bitmap);
                view.draw(mCanvas);
                mCanvas.setBitmap(null); //清除參考
            }
        }
        return bitmap;
    }

    /**
     * 給Activity加上全屏覆寫的ExplosionField
     */
    private void attach2Activity(Activity activity) {
        ViewGroup rootView = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT);

        ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        rootView.addView(this, lp);
    }


    /**
     * 希望誰有破碎效果,就給誰加Listener
     * @param view 可以是ViewGroup
     */
    public void addListener(View view) {
        if (view instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) view;
            int count = viewGroup.getChildCount();
            for (int i = 0 ; i < count; i++) {
                addListener(viewGroup.getChildAt(i));
            }
        } else {
            view.setClickable(true);
            view.setOnClickListener(getOnClickListener());
        }
    }


    private OnClickListener getOnClickListener() {
        if (null == onClickListener) {

            onClickListener = new OnClickListener() {
                @Override
                public void onClick(View v) {
                    ExplosionField.this.explode(v);

//                view.setOnClickListener(null); // 用過一次就不需要了
                }
            };
        }

        return onClickListener;
    }
}

import android.graphics.Point;
import android.graphics.Rect;

import java.util.Random;

/**
 * 爆破粒子
 */
public class Particle {

    public static final int PART_WH = 8; //默認小球寬高

    //原本的值(不可變)
//    float originCX;
//    float originCY;
//    float originRadius;

    //實際的值(可變)
    float cx; //center x of circle
    float cy; //center y of circle
    float radius;

    int color;
    float alpha;

    static Random random = new Random();

    Rect mBound;

    public static Particle generateParticle(int color, Rect bound, Point point) {
        int row = point.y; //行是高
        int column = point.x; //列是寬

        Particle particle = new Particle();
        particle.mBound = bound;
        particle.color = color;
        particle.alpha = 1f;

        particle.radius = PART_WH;
        particle.cx = bound.left + PART_WH * column;
        particle.cy = bound.top + PART_WH * row;

        return particle;
    }

    public void advance(float factor) {
        cx = cx + factor * random.nextInt(mBound.width()) * (random.nextFloat() - 0.5f);
        cy = cy + factor * random.nextInt(mBound.height() / 2);

        radius = radius - factor * random.nextInt(2);

        alpha = (1f - factor) * (1 + random.nextFloat());
    }
}

import android.content.res.Resources;

public class Utils {
    /**
     * 密度
     */
    public static final float DENSITY = Resources.getSystem().getDisplayMetrics().density;

    public static int dp2px(int dp) {
        return Math.round(dp * DENSITY);
    }
}

13.1 擊碎爆破粒子使用

            ExplosionField explosionField = new ExplosionField(mContext);
            explosionField.addListener(view.findViewById(R.id.rootd1));

14.WindowUtils工具類

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.PixelFormat;
import android.os.Build;
import android.util.Log;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import static android.content.Context.WINDOW_SERVICE;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;

/**
 * 螢屏工具類
 */
public class WindowUtils {

    /**
     * 判斷是否是透明背景的Activity
     * @param context
     * @return
     */
    public static boolean isTranslucentOrFloating(Context context){
        boolean isTranslucentOrFloating = false;
        try {
            int [] styleableRes = (int[]) Class.forName("com.android.internal.R$styleable").getField("Window").get(null);
            final TypedArray ta = context.obtainStyledAttributes(styleableRes);
            Method m = ActivityInfo.class.getMethod("isTranslucentOrFloating", TypedArray.class);
            m.setAccessible(true);
            isTranslucentOrFloating = (boolean)m.invoke(null, ta);
            m.setAccessible(false);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return isTranslucentOrFloating;
    }

    /**
     * 修復8.0以上透明背景Activity指定方向時候閃退的bug
     * @param activity
     */
    public static void fixOrientation(Activity activity){
        try {
            Field field = Activity.class.getDeclaredField("mActivityInfo");
            field.setAccessible(true);
            ActivityInfo o = (ActivityInfo)field.get(activity);
            o.screenOrientation = -1;
            field.setAccessible(false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 獲取螢屏寬度
     */
    public static int getScreenWidth(Context context){
        return context.getResources().getDisplayMetrics().widthPixels;
    }

    /**
     * 獲取螢屏高度
     */
    public static int getScreenHeight(Context context){
        return context.getResources().getDisplayMetrics().heightPixels;
    }

    /**
     * 獲取虛擬按鍵高度
     * @param context
     * @return
     */
    public static int getNavigationBarHeight(Context context) {
        int result = 0;
        if (hasNavBar(context)) {
            Resources res = context.getResources();
            int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
            if (resourceId > 0) {
                result = res.getDimensionPixelSize(resourceId);
            }
        }
        return result;
    }

    /**
     * 檢查是否存在虛擬按鍵欄
     * @param context
     */
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    public static boolean hasNavBar(Context context) {
        Resources res = context.getResources();
        int resourceId = res.getIdentifier("config_showNavigationBar", "bool", "android");
        if (resourceId != 0) {
            boolean hasNav = res.getBoolean(resourceId);
            // check override flag
            String sNavBarOverride = getNavBarOverride();
            if ("1".equals(sNavBarOverride)) {
                hasNav = false;
            } else if ("0".equals(sNavBarOverride)) {
                hasNav = true;
            }
            return hasNav;
        } else { // fallback
            return !ViewConfiguration.get(context).hasPermanentMenuKey();
        }
    }

    /**
     * 判斷虛擬按鍵欄是否重寫
     *
     * @return
     */
    private static String getNavBarOverride() {
        String sNavBarOverride = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            try {
                Class c = Class.forName("android.os.SystemProperties");
                Method m = c.getDeclaredMethod("get", String.class);
                m.setAccessible(true);
                sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys");
            } catch (Throwable e) {
            }
        }
        return sNavBarOverride;
    }

    /**
     * 全屏 - 隱藏狀態欄和虛擬按鍵
     * @param window
     */
    public static void setHideVirtualKey(Window window) {
        //保持布局狀態
        int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE|
                //布局位于狀態欄下方
                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION|
                //全屏
                View.SYSTEM_UI_FLAG_FULLSCREEN|
                //隱藏導航欄
                View.SYSTEM_UI_FLAG_HIDE_NAVIGATION|
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
        if (Build.VERSION.SDK_INT >= 19){
            uiOptions |= 0x00001000;
        }else{
            uiOptions |= View.SYSTEM_UI_FLAG_LOW_PROFILE;
        }
        window.getDecorView().setSystemUiVisibility(uiOptions);
    }

    /**
     * 改變螢屏亮度
     */
    /**	 * 設定頁面的透明度	 * @param bgAlpha 1表示不透明	 */
    public static void setBackgroundAlpha(Activity activity, float bgAlpha) {
        WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
        lp.alpha = bgAlpha;
        if (bgAlpha == 1) {
            //不移除該Flag的話,在有視頻的頁面上的視頻會出現黑屏的bug
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);

        } else {
            //此行代碼主要是解決在華為手機上半透明效果無效的bug
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
        }
        activity.getWindow().setAttributes(lp);
    }

    /**
     * 獲取狀態欄高度
     */
    public static int getStatusBarHeight(Context context) {
        int statusBarHeight = 0;
        Resources res = context.getResources();
        int resourceId = res.getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            statusBarHeight = res.getDimensionPixelSize(resourceId);
        }
        return statusBarHeight;
    }

    /**
     * 將View全屏
     * @param context
     * @param view
     */
    public static void enterFullScreen(Context context, View view){
        //從原有的View中取出來
        ViewGroup parent = (ViewGroup) view.getParent();
        if (parent != null) {
            parent.removeView(view);
        }

        //找到父布局
        ViewGroup contentView = scanForActivity(context)
                .findViewById(android.R.id.content);

        //添加到父布局中
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
                MATCH_PARENT,MATCH_PARENT);
        contentView.addView(view,params);
    }

    /**
     * 將View退出全屏
     */
    public static void exitFullScreen(Context context, View view){
        //找到父布局
        ViewGroup contentView = scanForActivity(context)
                .findViewById(android.R.id.content);
        contentView.removeView(view);
    }

    private static Activity scanForActivity(Context cont) {
        if (cont == null) {
            Log.d("scanForActivity","cont == null");
            return null;
        } else if (cont instanceof Activity) {
            Log.d("scanForActivity","Activity");
            return (Activity) cont;
        } else if (cont instanceof ContextWrapper) {
            Log.d("scanForActivity","ContextWrapper");
            return scanForActivity(((ContextWrapper) cont).getBaseContext());
        }
        Log.d("scanForActivity","not result");
        return null;
    }

    public static WindowManager.LayoutParams newWmParams(int width, int height) {
        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_SCALED
                | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
        if (Build.VERSION.SDK_INT >= 26) {
            params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
        }
        params.width = width;
        params.height = height;
        params.format = PixelFormat.TRANSLUCENT;
        return params;
    }

    public static WindowManager getWindowManager(Context context) {
        return (WindowManager) context.getSystemService(WINDOW_SERVICE);
    }
}

15.常用框架-PhotoView縮放圖片

implementation 'com.github.chrisbanes:PhotoView:1.2.6'
 //todo 彈出圖片放大縮小
    private void ImaEvent() {
        PhotoView photoView=findViewById(R.id.id_myimg);
        Button xiazai=findViewById(R.id.button13);
        PicassoUtils.loadImageViewCrop2(paihang.this,localhost_path+"/image/lagelangri/paihangpic.png", photoView);

        xiazai.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Uri uri = Uri.parse(localhost_path+"/image/lagelangri/paihangpic.png");
                Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                startActivity(intent);

            }
        });


    }
<uk.co.senab.photoview.PhotoView
        android:id="@+id/id_myimg"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center" />

16.常用框架-加載gif

implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.7'
<pl.droidsonroids.gif.GifImageView
        android:id="@+id/loading_img"
        android:layout_width="match_parent"
        android:layout_height="450dp"
        android:layout_gravity="center_vertical"
        android:layout_marginTop="80dp"
        android:src="@drawable/wel" />

17.判斷App是第一次啟動

SharedPreferences setting;
setting = getSharedPreferences(SHARE_APP_TAG, 0);
 private void first() {
        //todo 判斷是第一次啟動
        Boolean user_first = setting.getBoolean("FIRST21",true);
        if(user_first){//第一次
            setting.edit().putBoolean("FIRST21", false).commit();
            setting.edit().putString("userName", "null").commit();
            setting.edit().putString("passWord", "null").commit();
            setting.edit().putString("devicecode", getPassword()).commit();
            DEVICECODE=setting.getString("devicecode", "");
            Intent intent=new Intent(welcome.this,Login.class);
            startActivity(intent);
        }else{
            //todo 不是第一次啟動 自動登錄
            uphone=setting.getString("userName", "");
            upassword=setting.getString("passWord", "");
            DEVICECODE=setting.getString("devicecode", "");
            //todo 登陸請求
            newRunner();
            }
    }

18.sqlite資料庫

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

public class MyDatabase extends SQLiteOpenHelper {
    //todo 記錄播放歷史(上次觀看記錄)
    public static final String LEARN_HISTORY = "create table Learn(id integer primary key autoincrement,kcid char(20),listid char(20))" ;
    public static final String LOGINUSER = "create table LoginUser(u_id integer,userName char(100),passWord char(20),name char(20),headImage char(100),sex char(20),major char(20),grade char(20),identity char(20),phone char(20),mibao char(20))" ;
    private Context mContext;

    public MyDatabase(Context context, String name, CursorFactory factory,
                      int version) {
        super(context, name, factory, version);
        // TODO Auto-generated constructor stub
        mContext = context ;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // TODO Auto-generated method stub
        db.execSQL(LEARN_HISTORY);
        db.execSQL(LOGINUSER);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // TODO Auto-generated method stub

    }

}

18.1 簡單增刪改查

private MyDatabase myDatebaseHelper;
myDatebaseHelper = new MyDatabase(this, SQLITE_NAME, null, 1);
 //todo 檢驗用戶是否登陸過
    public boolean IScheck(String phone) {
        SQLiteDatabase db = myDatebaseHelper.getWritableDatabase();
        String Query = "Select * from LoginUser where phone =?";
        Cursor cursor = db.rawQuery(Query, new String[]{phone});
        if (cursor.getCount() > 0) {
            cursor.close();
            return true;
        }
        cursor.close();
        return false;
    }
    //todo 洗掉
    public void del(){
        SQLiteDatabase db = myDatebaseHelper.getWritableDatabase();
        db.delete("LoginUser","phone=?",new String[]{USERS.getPhone()});
        db.close();
        addUser();
    }
    //todo  修改
    private void less() {
        SQLiteDatabase db = myDatebaseHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put("u_id",USERS.getU_id());
        values.put("userName",USERS.getUserName());
        values.put("passWord", USERS.getPassWord());
        values.put("name", USERS.getName());
        values.put("headImage", USERS.getHeadImage());
        values.put("sex", USERS.getSex());
        values.put("major", USERS.getMajor());
        values.put("grade", USERS.getGrade());
        values.put("identity", USERS.getIdentity());
        values.put("phone", USERS.getPhone());
        values.put("mibao", String.valueOf(USERS.getMibao()));
        db.update("LoginUser",values, "phone=?",new String[]{USERS.getPhone()});
        db.close();
    }
    //todo 添加用戶
    private void addUser() {
        SQLiteDatabase db = myDatebaseHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put("u_id",USERS.getU_id());
        values.put("userName",USERS.getUserName());
        values.put("passWord", USERS.getPassWord());
        values.put("name", USERS.getName());
        values.put("headImage", USERS.getHeadImage());
        values.put("sex", USERS.getSex());
        values.put("major", USERS.getMajor());
        values.put("grade", USERS.getGrade());
        values.put("identity", USERS.getIdentity());
        values.put("phone", USERS.getPhone());
        values.put("mibao", String.valueOf(USERS.getMibao()));
        db.insert("LoginUser",null, values);
        db.close();
    }

19.流式布局原理

private void addInit() {
        int w,h;
        WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        w = getAndroiodScreenWidth(wm);
        for(int i=0;i<ls.size();i++){
            final ImageView imageView = new ImageView(this);
            final FrameLayout f=new FrameLayout(this);
            final TextView t=new TextView(this);
            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(w/5-20,w/5-20);
            t.setGravity(Gravity.CENTER);
            imageView.setAlpha(0.8f);
            t.setTextColor(this.getColor(R.color.ffffff));
            t.setText("未獲得");
            for(int j=0;j<ls2.size();j++){
                if(ls.get(i).getHeadImage().equals(ls2.get(j).getHeadImage())){
                   // Toast.makeText(ChangeHeadImage.this,"---"+ls.get(i).getHeadImage()+"---"+ls2.get(i).getHeadImage(),Toast.LENGTH_SHORT).show();
                    imageView.setAlpha(1f);
                    t.setVisibility(View.GONE);
                }
            }
            PicassoUtils.loadImageViewCrop2(ChangeHeadImage.this,localhost_path+ ls.get(i).getHeadImage(), imageView);
            f.addView(imageView);
            f.addView(t);
            gridLayout.addView(f,params);
            //todo 點擊已獲得的頭像 修改頭像
            final int finalI = i;
            imageView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(imageView.getAlpha()==1f){
                        headImages=ls.get(finalI).getHeadImage();
                        HEADIMA=1;
                        updateUserIma();

                    }else {
                        Toast.makeText(ChangeHeadImage.this,"未獲得",Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
    }

20.監聽螢屏滑動簡單原理

 @Override
    public boolean onTouchEvent(MotionEvent event) {
        //繼承了Activity的onTouchEvent方法,直接監聽點擊事件
        if(event.getAction() == MotionEvent.ACTION_DOWN) {
            //當手指按下的時候
            x1 = event.getX();
            y1 = event.getY();
        }
        if(event.getAction() == MotionEvent.ACTION_UP) {
            //當手指離開的時候
            x2 = event.getX();
            y2 = event.getY();
            if(y1 - y2 > 50) {
                Toast.makeText(MainActivity.this, "向上滑", Toast.LENGTH_SHORT).show();
            } else if(y2 - y1 > 50) {
                Toast.makeText(MainActivity.this, "向下滑", Toast.LENGTH_SHORT).show();
            } else if(x1 - x2 > 50) {
                Toast.makeText(MainActivity.this, "向左滑", Toast.LENGTH_SHORT).show();
            } else if(x2 - x1 > 50) {
                Toast.makeText(MainActivity.this, "向右滑", Toast.LENGTH_SHORT).show();
            }
        }
        return super.onTouchEvent(event);
    }

21.Listview任意行生成截圖分享

 public  static Bitmap createBitmap(ListView listView, Context context){
        int titleHeight,width, height, rootHeight=0;
        Bitmap bitmap;
        Canvas canvas;
        int yPos = 0;
        int listItemNum;
        List<View> childViews = null;
        width = 1200;//寬度等于螢屏寬
        ListAdapter listAdapter = listView.getAdapter();
        listItemNum = listAdapter.getCount();
        childViews = new ArrayList<View>(listItemNum);
        View itemView;
        //計算整體高度:
        if(JTALL==0){
            for(int pos=0; pos < jt.size(); ++pos){
                itemView = listAdapter.getView(jt.get(pos), null, listView);
                //measure程序
                itemView.measure(View.MeasureSpec.makeMeasureSpec(width, View. MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
                childViews.add(itemView);
                rootHeight += itemView.getMeasuredHeight();
            }
        }else{
            for(int pos=0; pos < listItemNum; ++pos){
                itemView = listAdapter.getView(pos, null, listView);
                //measure程序
                itemView.measure(View.MeasureSpec.makeMeasureSpec(width, View. MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
                childViews.add(itemView);
                rootHeight += itemView.getMeasuredHeight();
            }
            JTALL=0;
        }



        // 創建對應大小的bitmap
        bitmap = Bitmap.createBitmap(width, rootHeight,
                Bitmap.Config.ARGB_8888);
        canvas = new Canvas(bitmap);

        Bitmap itemBitmap;
        int childHeight;
        //把每個ItemView生成圖片,并畫到背景畫布上
        for(int pos=0; pos < childViews.size(); ++pos){
            itemView = childViews.get(pos);
            childHeight = itemView.getMeasuredHeight();
            itemBitmap = viewToBitmap(itemView,width,childHeight);
            if(itemBitmap!=null){
                canvas.drawBitmap(itemBitmap, 0, yPos, null);
            }
            yPos = childHeight +yPos;
        }
        canvas.save();
        canvas.restore();

        return bitmap;
    }
    private static Bitmap viewToBitmap(View view, int viewWidth, int viewHeight){
        view.layout(0, 0, viewWidth, viewHeight);
        view.buildDrawingCache();
        Bitmap bitmap = view.getDrawingCache();
        return bitmap;
    }

21.1 分享

Uri uri = Uri.parse(MediaStore.Images.Media.insertImage(getContentResolver(), ima, null,null));
private void share(Uri uri){
        Intent shareIntent = new Intent(Intent.ACTION_SEND);
        shareIntent.putExtra(Intent.EXTRA_TEXT, "hello world");
        shareIntent.setType("text/plain");
        shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
        shareIntent.setType("image/*");
        startActivity(Intent.createChooser(shareIntent, "activityTitle"));

    }

22.獲取當前本地apk的版本/版本號名稱

import android.content.Context;
import android.content.pm.PackageManager;

public class APKVersionCodeUtils {
    /**
     * 獲取當前本地apk的版本
     *
     * @param mContext
     * @return
     */
    public static int getVersionCode(Context mContext) {
        int versionCode = 0;
        try {
            //獲取軟體版本號,對應AndroidManifest.xml下android:versionCode
            versionCode = mContext.getPackageManager().
                    getPackageInfo(mContext.getPackageName(), 0).versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return versionCode;
    }

    /**
     * 獲取版本號名稱
     *
     * @param context 背景關系
     * @return
     */
    public static String getVerName(Context context) {
        String verName = "";
        try {
            verName = context.getPackageManager().
                    getPackageInfo(context.getPackageName(), 0).versionName;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return verName;
    }
}

23.ImageView高度根據圖片比例自適應

<ImageView
    android:id="@+id/iv_test"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:scaleType="fitXY"
    />

24.ToastUtil封裝類

import android.annotation.SuppressLint;
import android.content.Context;
import android.widget.Toast;

public class ToastUtil {

    @SuppressLint("StaticFieldLeak")
    private static Context mContext;

    public static void init(Context context) {
        mContext = context.getApplicationContext();
    }

    public static void show(String content) {
        Toast.makeText(mContext, content, Toast.LENGTH_SHORT).show();
    }
}

24.1 ToastUtil封裝類使用

ToastUtil.show("23232---3232");

25.Android四大組件-廣播入門

25.1 BroadcastReceiver-廣播判斷網路狀態

public class MyNetworkReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        boolean isconnect = false; //判斷是否連接網路
        //獲取網路連接服務
        ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(context.CONNECTIVITY_SERVICE);
        //判斷wifi是否連接
        NetworkInfo.State state = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState();
        if (state == NetworkInfo.State.CONNECTED){
            isconnect = true;
            Toast.makeText(context , "wifi連接", Toast.LENGTH_LONG).show();
        }
        //判斷GPRS是否連接
        NetworkInfo.State gstate = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState();
        if (gstate == NetworkInfo.State.CONNECTED){
            isconnect = true;
            Toast.makeText(context , "當前正在使用資料流量", Toast.LENGTH_LONG).show();
        }
        //沒網路連接
        if (!isconnect){
            Toast.makeText(context , "無網路連接", Toast.LENGTH_LONG).show();
        }

    }
}

25.2 動態注冊廣播

 //動態注冊廣播
        myNetworkReceiver = new MyNetworkReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        registerReceiver(myNetworkReceiver, intentFilter);

26.EditText的監聽-TextWatcher三個回呼

    EditText et = (EditText) findViewById(R.id.et);
    TextWatcher watcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            Log.d(TAG, "beforeTextChanged: s = " + s + ", start = " + start +
                    ", count = " + count + ", after = " + after);
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            Log.d(TAG, "onTextChanged: s = " + s + ", start = " + start +
                    ", before = " + before + ", count = " + count);
        }

        @Override
        public void afterTextChanged(Editable s) {
            Log.d(TAG, "afterTextChanged: " + s);
        }
    };
    et.addTextChangedListener(watcher);

27.Activity+viewPage+Fragment+RadioButton實作左右滑動切換頁面

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/home15"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@drawable/bjt"
    tools:context=".fragment.MainActivity">


    <android.support.v4.view.ViewPager
        android:id="@+id/main_ViewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
    </android.support.v4.view.ViewPager>

    <LinearLayout
        android:id="@+id/root1"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:layout_gravity="center"
        android:gravity="center"
        android:visibility="gone"
        android:background="#ffffff"
        android:orientation="vertical">

        <pl.droidsonroids.gif.GifImageView
            android:layout_width="130dp"
            android:layout_height="160dp"
            android:background="@drawable/dtz1" />
    </LinearLayout>
    <RadioGroup
        android:id="@+id/main_tab_RadioGroup"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="#000000"
        android:alpha="0.9"
        android:orientation="horizontal"
        android:padding="3dp">

        <RadioButton
            android:id="@+id/radio_home"
            android:layout_width="10dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:width="100dp"
            android:height="100dp"
            android:background="@null"
            android:button="@null"
            android:gravity="center"
            android:textStyle="bold"
            android:text="首頁"
            android:textColor="#ffffff" />

        <RadioButton
            android:id="@+id/radio_square"
            android:layout_width="10dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:width="100dp"
            android:height="100dp"
            android:background="@null"
            android:button="@null"
            android:gravity="center"
            android:text="短視頻"
            android:textStyle="bold"
            android:textColor="#ffffff" />

        <RadioButton
            android:id="@+id/radio_information"
            android:layout_width="10dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:width="100dp"
            android:height="100dp"
            android:background="@null"
            android:button="@null"
            android:gravity="center"
            android:text="學習中心"
            android:textColor="#ffffff"
            android:textStyle="bold" />


        <RadioButton
            android:id="@+id/radio_me"
            android:layout_width="10dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:width="100dp"
            android:height="100dp"
            android:background="@null"
            android:button="@null"
            android:gravity="center"
            android:text="我的"
            android:textStyle="bold"
            android:textColor="#ffffff" />
    </RadioGroup>

</LinearLayout>

public class TwoFragment extends Fragment {

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.activity_login, container, false);
        return view;
    }
}
public class MainActivity extends FragmentActivity implements OnCheckedChangeListener {
    //todo 監聽網路變化

    //ViewPager
    private ViewPager main_viewPager;
    //RadioGroup
    private RadioGroup main_tab_RadioGroup;
    //RadioButton
    private RadioButton radio_home, radio_shopcar,
            radio_sort, radio_me, radio_search;
    private ArrayList<Fragment> fragmentList;
    int current = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0)
        {
            finish();
            return;
        }
        //todo  android:background="#F5F6FA"
        setContentView(R.layout.activity_login2);
        // 界面初始函式,用來獲取定義的各控制元件對應的ID
//        //TODO 設定狀態欄透明
        if (Build.VERSION.SDK_INT >= 21){
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            getWindow().setStatusBarColor(Color.TRANSPARENT);
            int ui = decorView.getSystemUiVisibility();
            ui |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; //設定狀態欄中字體的顏色為黑色
            decorView.setSystemUiVisibility(ui);
        }

        InitView();
        //todo
        InitViewPager();


    }






    public void InitView() {
        main_tab_RadioGroup = (RadioGroup) findViewById(R.id.main_tab_RadioGroup);
        radio_home = (RadioButton) findViewById(R.id.radio_home);
        radio_shopcar = (RadioButton) findViewById(R.id.radio_square);
        radio_sort = (RadioButton) findViewById(R.id.radio_information);
        radio_me = (RadioButton) findViewById(R.id.radio_me);
        main_tab_RadioGroup.setOnCheckedChangeListener(this);

    }

    public void InitViewPager() {
        main_viewPager = (ViewPager) findViewById(R.id.main_ViewPager);
        fragmentList = new ArrayList<Fragment>();

        //todo 短視頻學習
        Fragment learnFragment = new TwoFragment();
        Fragment squareFragment = new SquareFragment();
        Fragment informationFragment = new InformationFragment();
        Fragment meFragment = new MeFragment();
        fragmentList.add(squareFragment);
        fragmentList.add(learnFragment);
        //todo 學習中心
        fragmentList.add(informationFragment);
        fragmentList.add(meFragment);
        main_viewPager.setAdapter(new MyAdapter(getSupportFragmentManager(), fragmentList));
        main_viewPager.setCurrentItem(0);
        main_viewPager.addOnPageChangeListener(new MyListner());


    }

    public class MyAdapter extends FragmentPagerAdapter {
        ArrayList<Fragment> list;
        public MyAdapter(FragmentManager fm, ArrayList<Fragment> list) {
            super(fm);
            this.list = list;
        }

        @Override
        public Fragment getItem(int arg0) {
            return list.get(arg0);
        }
        @Override
        public int getCount() {
            return list.size();
        }
    }

    public class MyListner implements ViewPager.OnPageChangeListener {

        @Override
        public void onPageScrollStateChanged(int arg0) {

        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {

        }

        @Override
        public void onPageSelected(int arg0) {
            int current = main_viewPager.getCurrentItem();
            switch (current) {
                case 0:
                    main_tab_RadioGroup.check(R.id.radio_home);
                    break;
                case 1:
                    main_tab_RadioGroup.check(R.id.radio_square);
                    break;
                case 2:
                    main_tab_RadioGroup.check(R.id.radio_information);
                    break;
                case 3:
                    main_tab_RadioGroup.check(R.id.radio_me);
                    break;
            }
        }
    }

    @Override
    public void onCheckedChanged(RadioGroup radioGroup, int checkId) {

        switch (checkId) {
            case R.id.radio_home:
                current = 0;
                break;
            case R.id.radio_square:
                current = 1;
                break;
            case R.id.radio_information:
                current = 2;
                break;
            case R.id.radio_me:
                current = 3;
                break;
        }
        if (main_viewPager.getCurrentItem() != current) {
            main_viewPager.setCurrentItem(current);
        }
    }





    protected void onStart() {
        super.onStart();

    }
}

28.估值器-貝塞爾曲線-控制元件封裝-抖音點贊特效

import android.animation.TypeEvaluator;
import android.graphics.PointF;

/**
 * 估值器
 * */
public class BasEvaluator implements TypeEvaluator<PointF> {
 
	private PointF p1;
	private PointF p2;
 
	public BasEvaluator(PointF p1, PointF p2) {
		super();
		this.p1 = p1;
		this.p2 = p2;
	}
 
	@Override
	public PointF evaluate(float fraction, PointF p0, PointF p3) {
		// TODO Auto-generated method stub
		PointF pointf = new PointF();
		
		// 貝塞爾曲線公式  p0*(1-t)^3 + 3p1*t*(1-t)^2 + 3p2*t^2*(1-t) + p3^3
		pointf.x = p0.x * (1-fraction) *(1-fraction ) * (1-fraction)
				   +3*p1.x * fraction *(1-fraction )*(1-fraction )
				   +3*p2.x *fraction  *fraction  *(1-fraction )
				   +p3.x*fraction *fraction *fraction ; 
		pointf.y = p0.y * (1-fraction ) *(1-fraction ) * (1-fraction )
				+3*p1.y * fraction *(1-fraction )*(1-fraction )
				+3*p2.y *fraction  *fraction  *(1-fraction )
				+p3.y*fraction *fraction *fraction ; 
		return pointf;
	}
}
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.example.amusic.R;

import java.util.Random;

public class Love_dy extends RelativeLayout {
    private int a2=8;
    private Context context;
    private LayoutParams params;
    private Drawable[] icons = new Drawable[a2];
    private Interpolator[] interpolators = new Interpolator[4];
    private int mWidth;
    private int mHeight;
    private int[] ImaResources={R.drawable.caomei,R.drawable.qiezi,R.drawable.heart_red,R.drawable.xigua,R.drawable.tuzi,R.drawable.tuzi,
            R.drawable.hua,R.drawable.qiezi};
    public Love_dy(Context context, AttributeSet attrs) {
        super(context, attrs);

        this.context = context;
        initView();

    }


    private void initView() {
        for(int i=0;i<a2;i++){
            icons[i] = getResources().getDrawable(ImaResources[i]);
        }
        // 插值器
        interpolators[0] = new AccelerateDecelerateInterpolator(); // 在影片開始與結束的地方速率改變比較慢,在中間的時候加速
        interpolators[1] = new AccelerateInterpolator();  // 在影片開始的地方速率改變比較慢,然后開始加速
        interpolators[2] = new DecelerateInterpolator(); // 在影片開始的地方快然后慢
        interpolators[3] = new LinearInterpolator();  // 以常量速率改變

    }

    public void addLoveView(float x, float y) {
        if (x < 100) {
            x = 101;
        }
        if (y < 100) {
            y = 101;
        }
        mWidth = (int) (x);
        mHeight = (int) (y);
        final ImageView iv = new ImageView(context);

        params = new LayoutParams(200, 200);
        iv.setLayoutParams(params);

        iv.setImageDrawable(icons[new Random().nextInt(a2)]);

        addView(iv);

        // 開啟影片,并且用完銷毀
        AnimatorSet set = getAnimatorSet(iv);
        set.start();
        set.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                // TODO Auto-generated method stub
                super.onAnimationEnd(animation);
                removeView(iv);
            }
        });
    }

    /**
     * 獲取影片集合
     *
     * @param iv
     */
    private AnimatorSet getAnimatorSet(ImageView iv) {

        // 1.alpha影片
        ObjectAnimator alpha = ObjectAnimator.ofFloat(iv, "alpha", 0.3f, 1f);

        // 2.縮放影片
        ObjectAnimator scaleX = ObjectAnimator.ofFloat(iv, "scaleX", 0.2f, 1f);
        ObjectAnimator scaleY = ObjectAnimator.ofFloat(iv, "scaleY", 0.2f, 1f);

        // 影片集合
        AnimatorSet set = new AnimatorSet();
        set.playTogether(alpha, scaleX, scaleY);
        set.setDuration(2000);

        // 貝塞爾曲線影片
        ValueAnimator bzier = getBzierAnimator(iv);

        AnimatorSet set2 = new AnimatorSet();
        set2.playTogether(set, bzier);
        set2.setTarget(iv);
        return set2;
    }

    /**
     * 貝塞爾影片
     */
    private ValueAnimator getBzierAnimator(final ImageView iv) {
        // TODO Auto-generated method stub
        PointF[] PointFs = getPointFs(iv); // 4個點的坐標
        BasEvaluator evaluator = new BasEvaluator(PointFs[1], PointFs[2]);
        ValueAnimator valueAnim = ValueAnimator.ofObject(evaluator, PointFs[0], PointFs[3]);
        valueAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // TODO Auto-generated method stub
                PointF p = (PointF) animation.getAnimatedValue();
                iv.setX(p.x);
                iv.setY(p.y);
                iv.setAlpha(1 - animation.getAnimatedFraction()); // 透明度

            }
        });
        valueAnim.setTarget(iv);
        valueAnim.setDuration(2000);
        valueAnim.setInterpolator(interpolators[new Random().nextInt(4)]);
        return valueAnim;
    }

    private PointF[] getPointFs(ImageView iv) {
        // TODO Auto-generated method stub
        PointF[] PointFs = new PointF[4];
        PointFs[0] = new PointF(); // p0
        PointFs[0].x = ((int) mWidth);
        PointFs[0].y = mHeight;

        PointFs[1] = new PointF(); // p1
        PointFs[1].x = new Random().nextInt(mWidth);
        PointFs[1].y = new Random().nextInt(mHeight / 2) + mHeight / 2 + params.height;

        PointFs[2] = new PointF(); // p2
        PointFs[2].x = new Random().nextInt(mWidth);
        PointFs[2].y = new Random().nextInt(mHeight / 2);

        PointFs[3] = new PointF(); // p3
        PointFs[3].x = new Random().nextInt(mWidth);
        PointFs[3].y = 0;
        return PointFs;
    }
}
import android.content.Context;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.widget.Toast;

public class MyGestureListener extends SimpleOnGestureListener {
  
    private Context mContext;
      
    MyGestureListener(Context context) {
        mContext = context;  
    }  
      
    @Override
    public boolean onDown(MotionEvent e) {
        Toast.makeText(mContext, "DOWN " + e.getAction(), Toast.LENGTH_SHORT).show();
        return false;  
    }  
  
    @Override
    public void onShowPress(MotionEvent e) {
        Toast.makeText(mContext, "SHOW " + e.getAction(), Toast.LENGTH_SHORT).show();
    }  
  
    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        Toast.makeText(mContext, "SINGLE UP " + e.getAction(), Toast.LENGTH_SHORT).show();
        return false;  
    }  
  
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2,
                            float distanceX, float distanceY) {
        Toast.makeText(mContext, "SCROLL " + e2.getAction(), Toast.LENGTH_SHORT).show();
        return false;  
    }  
  
    @Override
    public void onLongPress(MotionEvent e) {
        Toast.makeText(mContext, "LONG " + e.getAction(), Toast.LENGTH_SHORT).show();
    }  
  
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                           float velocityY) {
        Toast.makeText(mContext, "FLING " + e2.getAction(), Toast.LENGTH_SHORT).show();
        return false;  
    }  
  
    @Override
    public boolean onDoubleTap(MotionEvent e) {
        Toast.makeText(mContext, "DOUBLE " + e.getAction(), Toast.LENGTH_SHORT).show();
        return false;  
    }  
  
    @Override
    public boolean onDoubleTapEvent(MotionEvent e) {
        Toast.makeText(mContext, "DOUBLE EVENT " + e.getAction(), Toast.LENGTH_SHORT).show();
        return false;  
    }  
  
    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        Toast.makeText(mContext, "SINGLE CONF " + e.getAction(), Toast.LENGTH_SHORT).show();
        return false;  
    }  
}  

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/402780.html

標籤:其他

上一篇:《Android開發藝術探索》第9章-四大組件的作業程序讀書筆記

下一篇:Flutter 專案實戰 編輯框(TextField) 自定義 七

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more