Android 自定义按钮状态

需求描述:

最近做个项目,有一个按钮,有下载,安装,点击,安装中,下载中和使用这六个不同的状态,每个状态对应的按钮颜色也是不一样的,加上按下去的变色,大概有12种状态。

解决方案:

  • 6种状态对应不一样的background,设置为不同的状态的时候,换上对应的背景。
  • 自定义按钮状态

选择方案:

其实第二种和第一种的本质区别就是把所有的状态的文件写到一个xml里,但是更优雅,果断使用第二种

方案实现:

  • 定义自己的状态
  • 重写控件的onCreateDrawableState(int extraSpace) 告诉系统你有多少种状态

就这两个步骤,非常简单

定义自己的状态
   <declare-styleable name="ColorStateButton">
        <attr name="state_download" format="boolean"/>
        <attr name="state_downloading" format="boolean"/>
        <attr name="state_install" format="boolean"/>
        <attr name="state_installing" format="boolean"/>
        <attr name="state_open" format="boolean"/>
    </declare-styleable>

其实我想试试可不可以直接用数字类型的,当时时间比较紧急,就没试了,有兴趣的可以试试

重写onCreateDrawableState
 @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        if (mColorStatus != null && mColorStatus.getMergeState() != null && isEnabled()) {
            final int[] drawableStatus = super.onCreateDrawableState(extraSpace + mColorStatus.getMergeState().length);//告诉系统你要添加拓展的状态数量
            //告诉系统你要合并的状态
            mergeDrawableStates(drawableStatus, mColorStatus.getMergeState());
//            printList(drawableStatus);
            return drawableStatus;
        }¡
        return super.onCreateDrawableState(extraSpace);
    }

详细代码:

按钮的background
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto">
    <!-- 需要下载状态-->
    <item
        android:drawable="@drawable/ic_color_button_download_normal"
        android:state_pressed="false"
        app:state_download="true"/>
    <item
        android:drawable="@drawable/ic_color_button_download_pressed"
        android:state_pressed="true"
        app:state_download="true"/>

    <!--需要安装状态-->
    <item
        android:drawable="@drawable/ic_color_button_install"
        android:state_pressed="false"
        app:state_install="true"/>
    <item
        android:drawable="@drawable/ic_color_button_install_pressed"
        android:state_pressed="true"
        app:state_install="true"/>
    <!--按钮不可用-->
    <item
        android:drawable="@drawable/ic_color_button_disable"
        android:state_enabled="false"/>

    <item
        android:drawable="@drawable/ic_color_button_normal_pressed"
        android:state_pressed="true"/>
    <!--正常状态-->
    <item
        android:drawable="@drawable/ic_color_button_normal"/>
</selector>
按钮的源码
package com.bingwish.bibao.ui.fragment;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.support.annotation.StringRes;
import android.util.AttributeSet;
import android.widget.Button;
import com.bingwish.bibao.R;
import com.hangox.xlog.XLog;
/**
* Created With Android Studio
* User hangox
* Date 16/1/11
* Time 下午8:58
* 下载显示按钮
*/
public class ColorStateButton extends Button {
public static final int[] STATUS_DOWNLOAD = {R.attr.state_download};
public static final int[] STATUS_INSTALL = {R.attr.state_install};
private ColorStatus mColorStatus = ColorStatus.DOWNLOAD;
public ColorStateButton(Context context) {
super(context);
init(context);
}
public ColorStateButton(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public ColorStateButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ColorStateButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
private void init(Context context) {
setColorState(ColorStatus.DOWNLOAD);
}
/***
* 设置颜色类型
*
* @param colorState
*/
public void setColorState(ColorStatus colorState) {
setText(colorState.getButtonTextRes());
switch (colorState) {
case DOWNLOADING:
case INSTALLING:
setEnabled(false);
return;
}
setEnabled(true);
mColorStatus = colorState;
refreshDrawableState();
invalidate();
}
@Override
protected int[] onCreateDrawableState(int extraSpace) {
if (mColorStatus != null && mColorStatus.getMergeState() != null && isEnabled()) {
final int[] drawableStatus = super.onCreateDrawableState(extraSpace + mColorStatus.getMergeState().length);
mergeDrawableStates(drawableStatus, mColorStatus.getMergeState());
//            printList(drawableStatus);
return drawableStatus;
}
return super.onCreateDrawableState(extraSpace);
}
private void printList(int[] ints) {
StringBuilder builder = new StringBuilder();
for (int state : ints) {
builder.append(state).append("#");
}
XLog.i(builder.toString());
}
public enum ColorStatus {
DOWNLOAD(STATUS_DOWNLOAD, R.string.state_download),
CLICK(STATUS_INSTALL, R.string.state_click),
OPEN(null, R.string.state_open),
DOWNLOADING(null, R.string.state_downloading),
INSTALL(STATUS_INSTALL, R.string.state_install),
INSTALLING(null, R.string.state_installing);
int[] mergeState;
@StringRes
int mButtonTextRes;
ColorStatus(int[] statusDownload, @StringRes int buttonTextRes) {
mergeState = statusDownload;
mButtonTextRes = buttonTextRes;
}
public int getButtonTextRes() {
return mButtonTextRes;
}
public int[] getMergeState() {
return mergeState;
}
}
}

Sock代理转换为http 代理

为了应对日益强大的防火墙,大部分人开始专用ShadowSock 作为代理,但是ShadowSock并不支持http 代理,而很多软件非常依赖于http 代理,比如Android SDK ,终端等,所以我们需要Privoxy

以下以Mac系统为例演示安装过程

安装
brew install proxivy

如果你看到这个了

表示你已经安装成功了

配置

配置其实很简单,上面的截图已经告诉你配置文件在哪里,就是/usr/local/etc/privoxy/的config 文件
敲入

vi /usr/local/etc/privoxy/config

在最下面加入

# 监听端口为8118,如果需要其他设备访问,则需要将ip改为路由器的IP 192.168.1.1 或 0.0.0.0 或者直接 :8118
listen-address  0.0.0.0:8118 #如果要使用默认配置,可以不需要这行
forward-socks5 / 127.0.0.1:1080 .
#forward-socks5 表示监听sock5 ,127.0.0.1:1080是本地shadowsock 地址, "." 表示监听所有的URL

配置完成后如图

启动

还记得安装成功后的截图不?

这是直接运行,但是关机后就没了

privoxy /usr/local/etc/privoxy/config

下面是加入系统启动项

ln -sfv /usr/local/opt/privoxy/*.plist ~/Library/LaunchAgents
launchctl load ~/Library/LaunchAgents/homebrew.mxcl.privoxy.plist

如果你选择了其中一个敲入,并没有任何提示,那就是表示成功了

验证
  • 首先验证这个进程是否已经启动了
ps aux  | grep privoxy

截图如下:

  • 验证provixy 是否在监听8118这个端口
netstat -an | grep 8118

结果如下:

这样就是表示正在监听8118端口了

Linux 笔记

内核查看

uname -a

上传或者下载文件

#下载
scp -r -P {SSH端口号} {用户名}@{主机IP地址}:{主机文件目录}   {本地文件目录}
#上传
scp -r -P {SSH端口号}  {本地文件目录} {用户名}@{主机IP地址}:{主机文件目录}

查看当前的IP地址

ip addr show

开启某个服务开机启动

sudo chkconfig [服务名] on
sudo chkconfig docker on

Centos7 添加服务器端口

firewall-cmd --zone=public --add-port=80/tcp --permanent

Firewall 移除port

firewall-cmd --zone=public  --remove-port=19999/tcp --permanent

关闭SELinux

修改/etc/selinux/config 文件
将SELINUX=enforcing改为SELINUX=disabled

添加环境变量

不要直接修改/etc/profile 文件,把需要执行的代码加入到xx.sh 文件中,移动到/etc/profile.d/中就好了