Android 基础

Jan 26, 2016


Android 基础知识点:


android:layout_gravity和android:gravity属性的区别 :

  • gravity的中文意思就是”重心”,就是表示view横向和纵向的停靠位置;

  • android:gravity:是对view控件本身来说的,是用来设置view本身的内容应该显示在view的什么位置,默认值是左侧。

  • android:layout_gravity:是相对于包含改元素的父元素来说的,设置该元素在父元素的什么位置;

  • 比如TextView: android:layout_gravity表示TextView在界面上的位置,android:gravity表示TextView文本在TextView的什么位置,默认值是左侧.


设置颜色

    Android 代码中使用Color工具类 方法parseColor解析
    view.setBackgroundColor(Color.parseColor("#365663"));

添加分割线的方法

  • 自己在drawable下新建xml文件,然后在textView引用

      实线
      <?xml version="1.0" encoding="utf-8"?>
      <shape xmlns:android="http://schemas.android.com/apk/res/android"
          android:shape="line" >
            
          <stroke 
              android:color="#d4d4d4" />
            
      </shape>
        
      虚线
      <?xml version="1.0" encoding="utf-8"?>  
      <shape xmlns:android="http://schemas.android.com/apk/res/android"  
          android:shape="line" >  
          <stroke  
              android:dashGap="3dp"  
              android:dashWidth="6dp"  
              android:width="1dp"  
              android:color="#63a219" />  
          <!-- 虚线的高度 -->  
          <size android:height="1dp" />  
      </shape>  
        
      <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/line" />
    
  • 使用view

      <View 
         android:id="@+id/tab_line"
         android:layout_width="match_parent"
         android:layout_height="1dp"
         android:background="#d4d4d4"
         android:layout_alignParentBottom="true"/>
    
  • 添加竖线

      <ImageView
          android:layout_width="1dp"
          android:layout_height="match_parent"
          android:layout_marginTop="1dp"
          android:background="#ebebeb"
          android:layout_gravity="center_horizontal" />
    

listView相关

  • 要想让ListView显示底部的分割线,需要同时满足以下的选项: 1)mFooterDividersEnabled 必须为true,其默认值是true的 2)ListView的高度必须为match_parent。

  • listview的应用中很常见的一种便是item的布局不是简单的一种,对于有多种布局的情况,一般需要重写适配器adapter

      思路为:
      1. 首先为不同的item类型编写布局layout文件和class类文件
      2. 选好用来传递数据给适配器的工具,常见的有HashMap<String, Object> map、ArrayList<Message> moreItemList;如:
          使用message来传递信息:            
          moreItemList = new ArrayList<Message>();
          MoreItem free_collect = new MoreItem("免费收录", R.drawable.free_collect, R.drawable.tag_more);
          Message collect = new Message();
          collect.obj = free_collect;     //obj用来传递数据
          collect.what = img_text;    //what作为标记位
          moreItemList.add(collect);
            
          取信息:
          Message msg = moreItemList.get(position);
          holderText.text.setText(msg.obj.toString());
          holderImageText.image.setImageResource(((MoreItem)msg.obj).getImageId());
            
      3. 初始化数据
      4. MoreItemAdapter adapter = new MoreItemAdapter(MoreActivity.this, moreItemList);
          moreListView.setAdapter(adapter);
    

intent 传递图片

    #发送图片
    Intent intent = new Intent(this.mContext, AccountDetailActivity.class);
    holder.account_image.setDrawingCacheEnabled(true);
    intent.putExtra("account_img", holder.account_image.getDrawingCache());
    this.mContext.startActivity(intent);
    
    #接收图片
    Bitmap bitmap = (Bitmap) getIntent().getParcelableExtra("account_img");
    Matrix matrix = new Matrix();//放大图片
    matrix.postScale(1.2f, 1.2f);
    Bitmap bm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    accountImg.setImageBitmap(bm);

颜色

    android 定义颜色color时6位或8位值的区别
  6位(#000000)就是RGB值
  8位(#1e000000)头两位是透明度,后6位是RGB值,00是完全透明,ff是完全不透明,比较适中的透明度值是 1e

点击事件的设置

    LinearLayout category;
    category.setClickable(true);//使能点击,false则不能点击
    category.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(mContext, ChildCatsActivity.class);
            mContext.startActivity(intent);
        }
    });

点击改变imageView的图片资源ID

    like.setOnClickListener(new OnClickListener() {
		
		@Override
		public void onClick(View v) {
			Integer integer = (Integer) like.getTag();
			integer = integer == null ? 0 : integer;
			switch(integer) {
			case R.drawable.like_normal:
				like.setImageResource(R.drawable.like_select);
				like.setTag(R.drawable.like_select);
				break;
			case R.drawable.like_select:
				like.setImageResource(R.drawable.like_normal);
				like.setTag(R.drawable.like_normal);
				break;
			default:
				like.setImageResource(R.drawable.like_normal);
				like.setTag(R.drawable.like_normal);
				break;
			}
		}
	});

点击或者按压改变颜色,包括ImageView、TextView、Button等

    步骤一:在res/drawable目录下新建xml文件
    
    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android" >
        
        //设置颜色
        <item android:state_pressed="true" android:color="#00bc44"/>    //按下时候的颜色
        <item android:state_pressed="false" android:color="#717171"/>
         
        //设置图片
        <item android:state_selected="true" android:drawable="@drawable/more_select" />     //被选中时的图片

        <item android:state_selected="false" android:drawable="@drawable/more_normal" />

    </selector>
    
    步骤二:在对应的ImageView、TextView、Button中设置属性,ImageView/Button的background属性,textView的color属性
    <TextView 
        android:id="@+id/subscribe_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dp"
        android:text="订阅"
        android:textSize="18sp"
        android:textColor="@drawable/subscribetext_selector"/>

返回上一个活动:直接把当前的活动finish()

    tagBack.setOnClickListener(new OnClickListener() {
		@Override
		public void onClick(View v) {
			AccountDetailActivity.this.finish();
		}
	});

复制信息到系统剪贴板

    // 从API11开始android推荐使用android.content.ClipboardManager
    // 为了兼容低版本我们这里使用旧版的android.text.ClipboardManager,虽然提示deprecated,但不影响使用。
    ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
    // 将文本内容放到系统剪贴板里。
    cm.setText(tvMsg.getText());
    Toast.makeText(this, "复制成功,可以发给朋友们了。", Toast.LENGTH_LONG).show();

打开其他应用,如微信等

    Intent intent = new Intent();

    ComponentName cmp = new ComponentName("com.sina.weibo","com.sina.weibo.EditActivity");
    intent.setAction(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_LAUNCHER);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setComponent(cmp);
    startActivityForResult(intent, 0);
    
    几个常用的Package命令:

    新浪微博(编辑界面):com.sina.weibo     com.sina.weibo.EditActivity

    腾讯微博(编辑界面):com.tencent.WBlog    com.tencent.WBlog.activity.MicroblogInput

    微信:                com.tencent.mm      com.tencent.mm.ui.LauncherUI
    QQ:                   com.tencent.mobileqq com.tencent.mobileqq.activity.HomeActivity

ScrollView的简单应用

    <ScrollView 
        android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_height="match_parent"
        android:scrollbars="none"   //滚动条隐藏
        xmlns:tools="http://schemas.android.com/tools"></ScrollView>

使用styles.xml编写布局

    项目中有时候会有很多重复的布局,这时候可以编写values/styles.xml,来避免重复写控件的属性:
    如:
    <style name="usercenter_text_bottom">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:textColor">#a6a6a6</item>
        <item name="android:textSize">14sp</item>
    </style>
    
    然后在布局对应的控件中引用:
    <TextView
        android:id="@+id/tv_user_message"
        android:text="10条未读消息"
        style="@style/usercenter_text_bottom"/>

获取手机的imei码

    在manifest.xml文件中要添加 <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    TelephonyManager tm = (TelephonyManager) this.getSystemService(TELEPHONY_SERVICE);  
    String imei = tm.getDeviceId();//String     

通过资源名称获取资源ID

    ImageView iv = new ImageView(getContext());
    iv.setBackgroundResource(getResources().getIdentifier(getContext().getPackageName() + ":" + name, null, null));
    其中name可以是存储在json中的字符串,如:drawable/user_image;
    若json中存储的是user_image,则只要改":"为":drawable/"
    即第一个参数为完整的资源路径

EditText

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:hint="请输入新的密码"
        android:background="@null"  //消除下划线等背景
        android:lines="1"
        android:maxLines="1"        //限制行数
        android:inputType="textPassword"    //限制输入的类型
        android:maxLength="10"              //限制最大输入字符个数为10 
        android:imeOptions="actionNext"     //设置输入法回车键的功能,如:actionNext,下一项;actionDone:完成;actionSearch搜索
        android:layout_weight="1"
        android:textColor="#404040"
        android:textColorHint="#b4b4b4"     //设置提示的字体颜色
        android:textCursorDrawable="@null"/>    //设置光标的颜色,@null即表示与字体颜色一样
        
    密码不可见:editText.setTransformationMethod(PasswordTransformationMethod.getInstance());
    密码可见: editText.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
    
    //一开始进入新的Activity就要弹出键盘的话需要延时一会,等待activity加载完毕才能显示出键盘
    Timer timer = new Timer();
    timer.schedule(new TimerTask() {
        @Override
        public void run() {

        Context context = view.getContext();
        InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        view.requestFocus();
        imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
        }
    }, 998);
  • 监听内容变化:addTextChangedListener

      searchEditText.addTextChangedListener(new TextWatcher() {
          @Override
          public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
              //输入内容改变前
          }
    
          @Override
          public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
              //输入内容改变时
          }
    
          @Override
          public void afterTextChanged(Editable editable) {//输入内容改变后
              //editText内容为空改变视图
              if ("".equals(searchEditText.getText().toString().trim())) {
                  defaultLinearLayout.setVisibility(View.VISIBLE);
                  searchDetailContentLinearLayout.setVisibility(View.GONE);
                  initLatelySearch();
              }
          }
      });
    
  • 监听软键盘回车键事件:setOnEditorActionListener

      searchEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
          @Override
          public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
              //搜索,对应在xml文件中设置属性android:imeOptions="actionSearch"
              if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                  //搜索事件
                  searchKeyText = searchEditText.getText().toString().trim();
                  initData();
    
                  return true;
              }
              return false;
          }
      });
    

用framelayout实现图片上加提示数字

    <FrameLayout
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_marginRight="10dp">

        <ImageView
            android:id="@+id/iv_itemAlbum_img"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_marginRight="5dp"
            android:src="@mipmap/placeholder_square"/>

        <TextView
            android:id="@+id/tv_album_item_count"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_gravity="right|bottom"   //标记位于图片的右下角
            android:gravity="center"
            android:text="1"
            android:textColor="#ffffff"
            android:background="@drawable/shape_usercenter_item_album_count"/>

    </FrameLayout>

判断网络连接状态

    //判断网络连接状态
    private boolean isNetworkConnected(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(context.CONNECTIVITY_SERVICE);
        NetworkInfo ni = cm.getActiveNetworkInfo();
        return ni != null && ni.isConnectedOrConnecting();
    }
    
    //监听网络状态
    //编写监听广播
    public class NetworkReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i("NetworkReceiver", "NetworkReceiver");
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = cm.getActiveNetworkInfo();
            if (cm != null && networkInfo != null && networkInfo.isAvailable()) {
                reloadData();
            }
        }
    }
    //静态注册
    <receiver android:name=".base.PullRequestMoreActivity$NetworkReceiver">
        <intent-filter>
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
        </intent-filter>
    </receiver>
    //或是动态注册
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        intentFilter = new IntentFilter();
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        NetworkReceiver = new NetworkReceiver();
        registerReceiver(NetworkReceiver, intentFilter);
    }

时间格式转化

    import java.text.SimpleDateFormat;  
    import java.util.Date; 

    // 转化时间格式,例如:cc_time=1291778220
    private String getStrTime(String cc_time) {
        String re_StrTime = null;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒");
        long lcc_time = Long.valueOf(cc_time);
        re_StrTime = sdf.format(new Date(lcc_time * 1000L));

        return re_StrTime;
    }

时间选择对话框,应用场景:选择生日等

    private static final int DATE_DIALOG = 0;
    private Calendar c = null;

    @Override
    protected Dialog onCreateDialog(int id) {

        Dialog dialog = null;
        switch (id) {
            case DATE_DIALOG:
                c = Calendar.getInstance();
                dialog = new DatePickerDialog(UserInformationActivity.this, new DatePickerDialog.OnDateSetListener() {
                    @Override
                    public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                        birthday.setText(year + "年" + (monthOfYear + 1) + "月" + dayOfMonth + "日");
                    }
                },
                c.get(Calendar.YEAR),c.get(Calendar.MONTH),c.get(Calendar.DAY_OF_MONTH));

                break;
        }
        return dialog;
    }
    
    直接调用showDialog(DATE_DIALOG);

绑定手机

    Pattern phonePattern = Pattern.compile("^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$");
    Matcher phoneMatcher = phonePattern.matcher(phoneString);
    if (!phoneMatcher.matches()) {
        FLDDialogUtil.showErrorDialog(this, "亲, 请输入正确的手机号码");
    }
    
    //验证码重新发送倒计时
    new CountDownTimer(countDown*1000, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            tvVerifyCode.setText(millisUntilFinished/1000 + "秒后重新发送");
        }

        @Override
        public void onFinish() {
            tvVerifyCode.setText("获取验证码");
            tvVerifyCode.setEnabled(true);
            countDownLooping = false;
        }

    }.start();

双击返回键退出程序

    private static boolean isExit = false;
    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {

        if(keyCode==KeyEvent.KEYCODE_BACK){

            if(!isExit){
                isExit = true;
                Toast.makeText(this, "再按一次后退键退出程序!", Toast.LENGTH_SHORT).show();
                new CountDownTimer(2200,2200){

                    @Override
                    public void onTick(long millisUntilFinished) {
                    }

                    @Override
                    public void onFinish() {
                        isExit = false;
                    }
                }.start();
            }else{
                finish();
            }

            return false;


        }

        return super.onKeyUp(keyCode, event);
    }

让软键盘消失

    InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);   
    imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);

不需要放到版本控制中

    Androidstudio是用gradle来构建项目的,有很多环境方面的文件都不需要增加到SVN版本库。
    以下为列出不需要增加到版本库的文件:
    .idea 文件夹,此文件夹是用来保存开发工具的设置信息。
    .gradle 文件夹,此文件夹是用来保存gradle的依赖信息。
    所有的 build 文件夹,build文件夹是用来保存编译后的文件目录。
    所有的 .iml 文件,是用来保存开发工具信息。
    local.properties 文件,是用来保存项目依赖信息。

向上取整Math.ceil()返回的是大于或等于函数参数,并且与之最接近的整数。


viewpager

  • viewpager.getCurrentItem()可以得到当前的标签是第几个

发布自己的开源项目到jcenter和Maven Central,这样其他开发者可以很简单的引用项目

  • 如何使用Android Studio把自己的Android library分享到jCenter和Maven Central

  • 上传android library 到bintray.

  • 步骤:

      1.申请好[bintray官网 ](https://bintray.com/)的账号,建好Package
      2.准备好要上传的项目
      3.利用发布工具[novoda](https://github.com/novoda/bintray-release)配置项目
        
      配置点如下:
      1. project的builde gradle下加:classpath 'com.novoda:bintray-release:0.3.4'
      2. APP的builde gradle下加apply plugin: 'com.novoda.bintray-release' 这句话 需要放在com.android.library 下面
      3. publish {
          userOrg = 'snowdream1314'
          groupId = 'com.snowdream1314'   //唯一包名
          artifactId = 'enhancedpulltorefreshlistview'    //之前最初在bintary的maven中创建的那个package的名字
          publishVersion = '1.0.0'    //版本
          desc = 'An Android sample integrates EnhancedListView with PullToRefresh'   //项目描述
          website = 'https://github.com/snowdream1314/EnhancedPullToRefreshListView'
      }
        
      最后在android studio 终端Terminal运行:
      4. gradlew clean build bintrayUpload -PbintrayUser=BINTRAY_USERNAME -PbintrayKey=BINTRAY_KEY -PdryRun=false
         其中BINTRAY_USERNAME为你在bintary注册的名字,BINTRAY_KEY为bintary账号下的APIKey
    
  • 错误: 主要是网络连接错误之类的。直接多试几次就OK了。


修改项目的包名

  • 主要参考Android Studio Rename Package

  • 步骤:

      1. In your Project pane, click on the little gear icon ( Gears icon )
      2. Uncheck / De-select the Compact Empty Middle Packages option
      (这样就能修改中间的名字, 比如com.snowdream.enhancedpulltorefreshlistview改成com.snowdream1314.enhancedpulltorefreshlistview)
      3. Refactor -> Rename就行了
      4. 重新编译一下
    

View事件监听ViewTreeObserver.OnGlobalLayoutListener

  • 一共有5个接口:

  • 当在一个视图树中的焦点状态发生改变时,所要调用的回调函数的接口类:

      interface ViewTreeObserver.OnGlobalFocusChangeListener
    
  • 当在一个视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变时,所要调用的回调函数的接口类:

      interface ViewTreeObserver.OnGlobalLayoutListener
    
  • 当一个视图树将要绘制时,所要调用的回调函数的接口类:

      interface ViewTreeObserver.OnPreDrawListener
    
  • 当一个视图树中的一些组件发生滚动时,所要调用的回调函数的接口类:

      interface ViewTreeObserver.OnScrollChangedListener
    
  • 当一个视图树的触摸模式发生改变时,所要调用的回调函数的接口类:

      interface ViewTreeObserver.OnTouchModeChangeListener
    
  • 简单应用:

      ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();//初始化
      //设置监听回调
      if (viewTreeObserver.isAlive()) {
          viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
              @Override
              public void onGlobalLayout() {
                  //获取View高度,设置高度等
              }
                
          });
      }
    

WebView相关

    布局:
    <WebView
        android:id="@+id/wv_webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </WebView>
    
    //代码设置
    webView = (WebView) findViewById(R.id.wv_webview);
    WebSettings webSettings = webView.getSettings();
    webSettings.setJavaScriptEnabled(true);     //可以JS交互
    webView.setWebChromeClient(new WebChromeClient() {  //设置client,必须是WebChromeClient(), WebViewClient好像不能处理JS?

        public void onProgressChanged(WebView view,int newProgress) {
            Log.i("onProgressChanged", String.valueOf(newProgress));
            if (newProgress == 100) {       //加载完毕
                submit.setVisibility(View.VISIBLE);
            }
        }

    });  
    webView.loadUrl(getIntent().getStringExtra("url"));
    
    //java调用JS
    private View.OnClickListener clickListener = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        webView.loadUrl("javascript:submitForm()");     //submitForm()为嵌入网页的JS方法
    }
};

    //监听web的点击事件可以监听WebViewClient的shouldOverrideUrlLoading(WebView view, String url)回调,其中的url即是点击事件请求的Uri,可以根据uri的scheme做相应的处理。
    //uri结构:
    格式:scheme://host:port/path
    举个实际的例子:
    content://com.example.project:200/folder/subfolder/etc
    \---------/  \---------------------------/ \---/ \--------------------------/
    scheme                 host               port        path
                    \--------------------------------/
                              authority   
                              
    对应intent-filter中的data标签:
    <data android:host="string"
          android:mimeType="string"
          android:path="string"
          android:pathPattern="string"
          android:pathPrefix="string"
          android:port="string"
          android:scheme="string" />

设置状态栏的颜色

    修改res\values目录下的styles文件:
    <style name="AppTheme" parent="Theme.AppCompat.Light">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>    //状态栏的颜色
        <item name="colorAccent">@color/colorAccent</item>
        <!--<item name="android:windowIsTranslucent">true</item>-->
    </style>

颜色示意图


Android利用SpannableStringBuilder设置TextView中部分文字的颜色

    SpannableString titleSpannableString = new SpannableString(titleString+" "+subTitleString);
    titleSpannableString.setSpan(new ForegroundColorSpan(ColorUtil.HextoColor("#FFF02E1F")), titleString.length(), titleString.length()+subTitleString.length()+1,  Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
    titleTextView.setText(titleSpannableString);
    
     * titleSpannableString.setSpan
     * (new ForegroundColorSpan(Color.RED), 1, 3, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);     
     * 第一个参数:颜色
     * 第二个参数:开始位置
     * 第三个参数:终止位置
     * 第三个参数:SPAN_EXCLUSIVE_INCLUSIVE.用来对第二个和第三个参数进一步限制和说明
     * 此处表示包含1,但是不包含3.

android 用设置饱和度为0的方法让图片变灰色,设置1可恢复原图

    /*
    * change imageview to gray for disable tag
    * @param imageview
    *
    * by xxq
    * */
    private static void Image2Gray(ImageView imageView) {
        Drawable drawable = imageView.getDrawable();
        ColorMatrix cm = new ColorMatrix();
        cm.setSaturation(0);    //值为1可恢复原图
        ColorMatrixColorFilter cf = new ColorMatrixColorFilter(cm);
        drawable.setColorFilter(cf);
        imageView.setImageDrawable(drawable);
    }
    
    //也可以用同样的方法给对应的imageView设置灰色
    private static void Image2Gray(ImageView imageView) {
        ColorMatrix cm = new ColorMatrix();
        cm.setSaturation(0);    //值为1可恢复原图
        ColorMatrixColorFilter cf = new ColorMatrixColorFilter(cm);
        imageView.setColorFilter(cf);
    }

android 改变图片的颜色

    /*
    * change image color
    * @params context, id
    *
    * @return
    *
    * by xxq*/
    public static Bitmap changeImageColor(Context context, int id) {
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), id);
//		int mBitmapWidth = bitmap.getWidth();
//		int mBitmapHeight = bitmap.getHeight();

        Bitmap mAlphaBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas mCanvas = new Canvas(mAlphaBitmap);//画布
        Paint mPaint = new Paint();//画笔
        mPaint.setColor(Color.parseColor("#FFFFFF"));   //画笔颜色
        Bitmap alphaBitmap = bitmap.extractAlpha();
        mCanvas.drawBitmap(alphaBitmap, 0, 0, mPaint);
//        for(int i = 0; i < mBitmapHeight; i++) {
//			for (int j = 0; j < mBitmapWidth; j++) {
////				int color = bitmap.getPixel(j, i);//可以获取每个点的颜色值,从而得到每个点的RGB值
////				int r = Color.red(color);
////				int g = Color.green(color);
////				int b = Color.blue(color);
//
//                mAlphaBitmap.setPixel(j, i, Color.argb(255, 255, 255, 255));
//			}
//		}
        return mAlphaBitmap;
    }
    
    相当于按照原图重新画了一遍,生成新的bitmap

textView 特殊属性(没有调整文字间距的API)

    android:maxEms="4"
    [Android 开发者,你真的会用textview(maxEms和maxLength)的属性吗?](http://blog.csdn.net/beiminglei/article/details/9317997)
    [android TextView setEms 方法名字](http://blog.csdn.net/JavaLive09/article/details/38661773)
    
    android:ellipsize="end"     //内容过长在末尾增加省略号
    android:includeFontPadding="false" //取消预留的padding,TextView默认留下了上下的padding,是为了显示上标和下标。
    android:lineSpacingExtra    //设置行间距,如”3dp”
    android:lineSpacingMultiplier   //设置行间距的倍数,如”1.2″
    android:textScaleX      //设置文字水平方向的伸缩
  • 特殊样式,下划线,中间划线等等

      textView.getPaint().setFlags(Paint. UNDERLINE_TEXT_FLAG ); //下划线
    
      textView.getPaint().setAntiAlias(true);//抗锯齿
    
      textview.getPaint().setFlags(Paint. STRIKE_THRU_TEXT_FLAG); //中划线
    
      setFlags(Paint. STRIKE_THRU_TEXT_FLAG|Paint.ANTI_ALIAS_FLAG);  // 设置中划线并加清晰 
    
      textView.getPaint().setFlags(0);  // 取消设置的的划线
    
  • 动态设置shape

      TextView tag = new TextView(fragmentActivity);
        
      GradientDrawable myGrad = new GradientDrawable();
      myGrad.setCornerRadius(3);      //圆角
      myGrad.setStroke(1,Color.parseColor("#" + itemTag.getTag_color()));     //边框颜色和宽度
      tag.setBackgroundDrawable(myGrad);
        
      [Android代码设置Shape,corners,Gradient](http://blog.csdn.net/houshunwei/article/details/17392409)
    
  • 水平滚动显示的TextView

      设置属性:
      android:ellipsize="marquee"
      android:marqueeRepeatLimit="marquee_forever"     
    
      要让textview获得焦点才能滚动显示,重写TextView
      public class AnnouncementTextView extends TextView{
    
          public AnnouncementTextView(Context context) {
              super(context);
          }
          public AnnouncementTextView(Context context, AttributeSet attrs) {
              super(context, attrs);
          }
          public AnnouncementTextView(Context context, AttributeSet attrs,
                                      int defStyle) {
              super(context, attrs, defStyle);
          }
          @Override
          public boolean isFocused() {//一直获得焦点
              return true;
          }
      }
    
    
      [TextView实现滚动显示的效果](http://blog.csdn.net/l0605020112/article/details/37569455)
    

状态栏相关

  • 获得状态栏高度

      /**
       * 获得状态栏的高度
       *
       * @param context
       * @return
       */
      public static int getStatusHeight(Context context) {
    
          int statusHeight = -1;
          try {
              Class clazz = Class.forName("com.android.internal.R$dimen");
              Object object = clazz.newInstance();
              int height = Integer.parseInt(clazz.getField("status_bar_height")
                      .get(object).toString());
              statusHeight = context.getResources().getDimensionPixelSize(height);
          } catch (Exception e) {
              e.printStackTrace();
          }
          return statusHeight;
      }
    
  • 状态栏透明

      if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
          //透明状态栏
          getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
          //透明导航栏
          getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
      }
        
      对应的layout根布局设置属性
      android:fitsSystemWindows="true"//布局扩展至手机屏幕
      android:clipToPadding="true"
    
  • 状态栏隐藏

      public class MainActivity extends AppCompatActivity {
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              View decorView = getWindow().getDecorView();
              int option = View.SYSTEM_UI_FLAG_FULLSCREEN;
              decorView.setSystemUiVisibility(option);
              ActionBar actionBar = getSupportActionBar();
              actionBar.hide();
          }
      }
        
      [Android状态栏微技巧,带你真正理解沉浸式模式](http://blog.csdn.net/guolin_blog/article/details/51763825#comments)
    
  • 判断横竖屏

      if (getActivity().getResources().getConfiguration().orientation != Configuration.ORIENTATION_PORTRAIT) {
          VGetLog.e("change screen orientation");
          getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
          return true;
      }
    

项目中用到的开源插件


参考文章:


结语:

坚持每天进步一点点…