android小技巧

1. 布局技巧

父布局居中

    android:layout_centerInParent="true"
    android:layout_gravity="center"

多余字不显示

    android:singleLine="true"

字体太大时避免显示不全

    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="?attr/actionBarSize"

子控件可以设置为全局固定。可用于实现布局滚动,折叠效果且要求固定Toolbar时

    app:layout_collapseMode="pin"

toolbar偏移量为0

   app:contentInsetStart="0dp"

横竖屏切换及editTextview键盘出现时视图不再上移

        <activity
            android:name=".LoadingActivity"
            android:configChanges="orientation|keyboardHidden"
            android:windowSoftInputMode="adjustPan|stateHidden"
            >

2. 可复用toolbar

nav_toolbar.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.AppBarLayout
xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/grayc"
android:theme="@style/AppTheme.AppBarOverlay"
    >

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:layout_marginTop="20dp"
    android:background="@color/white"

    app:popupTheme="@style/AppTheme.PopupOverlay">

    <!--<ImageView-->
        <!--android:id="@+id/im_about_back"-->
        <!--android:layout_width="40dp"-->
        <!--android:layout_height="40dp"-->
        <!--android:layout_gravity="left"-->
        <!--android:padding="10dp"-->
        <!--android:src="@mipmap/ic_back_green" />-->

    <TextView
        android:id="@+id/toolbar_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/black"
        android:layout_centerInParent="true"
        android:layout_gravity="center"
        app:layout_collapseMode="pin"
        app:contentInsetStart="0dp"
        android:textSize="17sp" />
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>

layout中引用

  <include layout="@layout/nav_toolbar" />

java调用
initToolbar();

     private void initToolbar() {
//        initToolbar();
       Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        TextView tv=(TextView)findViewById(R.id.toolbar_tv);
        toolbar.setTitle("");
        tv.setText("关于我们");
        toolbar.setNavigationIcon(R.mipmap.ic_back_green);//后退按钮
        setSupportActionBar(toolbar);

        //后退监听
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
//                Toast.makeText(AboutActivity.this,"后退", Toast.LENGTH_SHORT).show();
            }
        });
    }

3.沉浸式状态栏

    //浸入式状态栏
    @TargetApi(19)
    private void initWindow() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        }
    }

4.通用BaseActivity

package com.sjs.dz.rzxt3;

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Window;
import android.widget.TextView;
import android.widget.Toast;

import com.sjs.dz.rzxt3.R;
import com.sjs.dz.rzxt3.base.SysApplication;

/**
 * Created by 李江涛 on 2017/6/29.
 * 说明:
 */

public abstract class BaseActivity extends AppCompatActivity implements View.OnClickListener{
    private long lastClick = 0;
    public Toolbar toolbar;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        SysApplication.getInstance().addActivity(this);
        setContentView(getLayoutId());
        initView();
        loadData();
        setListener();
    }

    @Override
    public void onClick(View v) {
        if (fastClick())
            widgetClick(v);
    }


    @Override
    public void finish() {
        SysApplication.getInstance().removeActivity(this);
        super.finish();
    }

    /**
     * 设置ContentView
     * @return R.layout.xxx
     */
    protected abstract int getLayoutId();

    /**
     * 初始化View
     */
    protected abstract void initView();
    /**
     * add Listener
     */
    protected abstract void setListener();

    /**
     * 下载数据
     */
    protected abstract void loadData();
    /**
     * 将数据更新到View
     */
    protected abstract void initDateToView();
    /**
     * view点击
     * @param v
     */
    public abstract void widgetClick(View v);

    /**
     * 防止快速点击
     * @return
     */
    private boolean fastClick() {
        if (System.currentTimeMillis() - lastClick <= 1000) {
            return false;
        }
        lastClick = System.currentTimeMillis();
        return true;
    }

    /**
     * 通用ToolBar 当存在是调用 布局文件 必须包含 single_toolbar.xml
     * @param title 标题内容
     * @param isBack 是否存在反回功能
     */
    protected void setToolBar(String title,boolean isBack) {
        toolbar = $findViewById(R.id.toolbar);
        toolbar.setVisibility(View.VISIBLE);
        TextView tv_title = $findViewById(R.id.tv_title);
        tv_title.setText(title);
        toolbar.setTitle("");
        setSupportActionBar(toolbar);
        if (isBack) {
            toolbar.setNavigationIcon(R.mipmap.ic_back_green);
            toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    finish();
                }
            });
        }
    }

    /**
     * findViewById
     * @param resId
     * @param <T>
     * @return
     */
    public <T extends View> T $findViewById(int resId) {
        return (T) findViewById(resId);
    }

    /**
     *  Toast
     * @param msg 消息
     */
    protected void $toast(CharSequence msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

    /**
     * startActivity
     * @param cls 需要启动的Activity
     */
    protected void $startActivity(Class<?> cls) {
        $startActivity(cls, null);
    }

    /**
     * startActivity 存在Bundle
     * @param cls 需要启动的Activity
     * @param bundle Bundle数据
     */
    protected void $startActivity(Class<?> cls, Bundle bundle) {
        Intent intent = new Intent(this, cls);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivity(intent);
    }

    /**
     * startActivityForResult
     * @param cls 需要启动的Activity
     * @param requestCode 请求码
     */
    protected void $startActivityForResult(Class<?> cls, int requestCode) {
        $startActivityForResult(cls, null, requestCode);
    }

    /**
     * startActivityForResult 存在Bundle
     * @param cls 需要启动的Activity
     * @param bundle Bundle数据
     * @param requestCode 请求码
     */
    protected void $startActivityForResult(Class<?> cls, Bundle bundle, int requestCode) {
        Intent intent = new Intent(this, cls);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivityForResult(intent, requestCode);
    }

    /**
     * 获取 传入 Bundle
     * @return
     */
    protected Bundle $getIntentExtra() {
        Intent intent = getIntent();
        Bundle bundle = null;
        if (null != intent)
            bundle = intent.getExtras();
        return bundle;
    }

}

ParentActivity

package com.sjs.dz.rzxt3;

import android.view.View;

/**
 * Created by 李江涛 on 2017/6/29.
 * 说明:
 */

public class ParentActivity extends BaseActivity {
    @Override
    protected int getLayoutId() {
        return 0;
    }

    @Override
    protected void initView() {

    }


    @Override
    protected void setListener() {

    }

    @Override
    protected void loadData() {

    }

    @Override
    protected void initDateToView() {

    }

    @Override
    public void widgetClick(View v) {

    }
}

MainActivity

package com.sjs.dz.rzxt3;

import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.design.widget.NavigationView;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.MenuItem;
import android.view.View;

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

import com.sjs.dz.rzxt3.R;
import com.sjs.dz.rzxt3.ParentActivity;
import com.sjs.dz.rzxt3.BaseFragment;
import com.sjs.dz.rzxt3.listener.BottomNavigationChangeListener;

public class MainActivity extends ParentActivity {
    private ViewPager viewPager;
    private MenuItem menuItem;
    private BottomNavigationView bottomNavigationView;
    private NavigationView navgaView;


    @Override
    protected int getLayoutId() {
        return R.layout.activity_main;
    }


    @Override
    protected void initView() {
        viewPager = $findViewById(R.id.viewpager);
        bottomNavigationView = $findViewById(R.id.bottom_navigation);
        navgaView = (NavigationView) findViewById(R.id.naviView_three);
    }

    @Override
    protected void setListener() {
        BottomNavigationChangeListener listener = new BottomNavigationChangeListener(this, bottomNavigationView, viewPager);
        List<Fragment> list = new ArrayList<>();
        for (int i=0;i<4;i++) {
            Fragment fragment = BaseFragment.newInstance("di" + i);
            list.add(fragment);
        }
        listener.setFragments(list);
        navgaView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.nav_me:
                        $startActivity(FirstActivity.class);
                        break;
                }
                return true;
            }
        });
    }

    @Override
    protected void loadData() {

    }

    @Override
    public void widgetClick(View v) {

    }


}

SysApplication

package com.sjs.dz.rzxt3.base;


import android.app.Activity;
import android.app.Application;
import android.content.Context;

import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.cache.memory.impl.WeakMemoryCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
import com.nostra13.universalimageloader.utils.StorageUtils;

import java.io.File;
import java.util.ArrayList;

import com.sjs.dz.rzxt3.utils.CrashHandler;

public class SysApplication extends Application {
    private static SysApplication instance;
    public DisplayImageOptions options;
    private ArrayList<Activity> activityList = new ArrayList<Activity>();

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        CrashHandler crashHandler=new CrashHandler();
        crashHandler.init(instance);
        //在使用SDK各组件之前初始化context信息,传入ApplicationContext
        //SDKInitializer.initialize(instance);
        setImageOptions();
    }
    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        //MultiDex.install(this);
    }
    public synchronized static SysApplication getInstance() {
        return instance;
    }

    private void setImageOptions() {
        File cacheDir = StorageUtils.getOwnCacheDirectory(this, "imageloader/Cache"); //缓存文件的存放地址
        ImageLoaderConfiguration config = new ImageLoaderConfiguration
                .Builder(this)
                  .memoryCacheExtraOptions(480, 800) // max width, max height
                .threadPoolSize(3)//线程池内加载的数量
                .threadPriority(Thread.NORM_PRIORITY - 2)  //降低线程的优先级保证主UI线程不受太大影响
                .denyCacheImageMultipleSizesInMemory()
                .memoryCache(new WeakMemoryCache()) //建议内存设在5-10M,可以有比较好的表现  new WeakMemoryCache()
               // .memoryCache(new LruMemoryCache(2 * 1024 * 1024)) //建议内存设在5-10M,可以有比较好的表现  new WeakMemoryCache()
                //.memoryCacheSize(2 * 1024 * 1024)
                .discCacheSize(50 * 1024 * 1024)
                .discCacheFileNameGenerator(new Md5FileNameGenerator())
                .tasksProcessingOrder(QueueProcessingType.LIFO)
                .discCacheFileCount(100) //缓存的文件数量
                .diskCache(new UnlimitedDiskCache(cacheDir))
                .defaultDisplayImageOptions(DisplayImageOptions.createSimple())
                .imageDownloader(new BaseImageDownloader(this, 5 * 1000, 30 * 1000)) // connectTimeout (5 s), readTimeout (30 s)
                .writeDebugLogs() // Remove for release app
                .build();
        ImageLoader.getInstance().init(config);
    }

    public void addActivity(Activity activity) {
        activityList.add(activity);
    }
    public void removeActivity(Activity activity) {
        activityList.remove(activity);
    }
    /**
     *     遍历所有Activity并finish
     */
    public void exit() {
        try {
            for (Activity activity : activityList) {
                activity.finish();
            }
            System.exit(0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     *     杀进程
     */
    @Override
    public void onLowMemory() {
        super.onLowMemory();
        System.gc();
    }
}

CrashHandler.java

package com.sjs.dz.rzxt3.utils;

/**
 * Created by win on 2017/6/30.
 */


import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

/**
 * UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序,并记录发送错误报告.
 *
 * Created by yuyuhang on 15/12/7.
 */
public class CrashHandler implements UncaughtExceptionHandler {

    //系统默认的UncaughtException处理类
    private Thread.UncaughtExceptionHandler mDefaultHandler;
    //CrashHandler实例
    private static CrashHandler INSTANCE;
    //程序的Context对象
    private Context mContext;
    //用来存储设备信息和异常信息
    private Map<String, String> infos = new HashMap<String, String>();

    public CrashHandler() {
    }

    /**
     * 获取CrashHandler实例 ,单例模式
     */
    public static CrashHandler getInstance() {
        if (INSTANCE == null)
            INSTANCE = new CrashHandler();
        return INSTANCE;
    }

    /**
     * 初始化
     *
     * @param context
     */
    public void init(Context context) {
        mContext = context;
        //获取系统默认的UncaughtException处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        //设置该CrashHandler为程序的默认处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     * 当UncaughtException发生时会转入该函数来处理
     */
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if (!handleException(ex) && mDefaultHandler != null) {
            //如果用户没有处理则让系统默认的异常处理器来处理
            mDefaultHandler.uncaughtException(thread, ex);
        } else {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                LogUtils.e(e.toString());
            }
            //退出程序
            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(1);
        }
    }

    /**
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
     *
     * @param ex
     * @return true:如果处理了该异常信息;否则返回false.
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }
        //收集设备参数信息
        collectDeviceInfo(mContext);
        //保存日志文件
        saveCrashInfo2File(ex);
        return true;
    }

    /**
     * 收集设备参数信息
     *
     * @param ctx
     */
    public void collectDeviceInfo(Context ctx) {
        try {
            PackageManager pm = ctx.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
            if (pi != null) {
                String versionName = pi.versionName == null ? "null" : pi.versionName;
                String versionCode = pi.versionCode + "";
                infos.put("versionName", versionName);
                infos.put("versionCode", versionCode);
            }
        } catch (NameNotFoundException e) {
            LogUtils.e("CrashHandleran.NameNotFoundException---> error occured when collect package info", e);
        }
        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                infos.put(field.getName(), field.get(null).toString());
            } catch (Exception e) {
                LogUtils.e("CrashHandler.NameNotFoundException---> an error occured when collect crash info", e);
            }
        }
    }

    /**
     * 保存错误信息到文件中
     *
     * @param ex
     * @return 返回文件名称, 便于将文件传送到服务器
     */
    private String saveCrashInfo2File(Throwable ex) {

        StringBuffer sb = new StringBuffer();
        sb.append("---------------------sta--------------------------");
        for (Map.Entry<String, String> entry : infos.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key + "=" + value + "\n");
        }

        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        String result = writer.toString();
        sb.append(result);
        sb.append("--------------------end---------------------------");
        LogUtils.e(sb.toString());
        return null;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值