安卓项目实战之小功能

设置activity为全透明或者半透明或者弹窗形式

http://blog.csdn.net/zhaozhiwen6140/article/details/52034495

http://blog.csdn.net/ithinklw/article/details/52002662(使用过的方式)(注意要继承activity,清单文件为activity指定theme等)

webview显示图片视频的适配问题

//  适配工具方法
    public static String getNewContent(String htmltext,int height){

      Document doc= Jsoup.parse(htmltext);
       Elements elements1=doc.getElementsByTag("img");
         for (Element element : elements1) {
                 element.attr("width","100%").attr("height","auto");
              }
        Elements elements2=doc.getElementsByTag("iframe");
        for (Element element : elements2) {
            element.attr("width","100%").attr("height",height+"");
        }
              return doc.toString();
           }
------------------------------------------------------------------------------
需要:jsoup的jar包
以上方法的第二个参数只为视频设置,因为iframe标签无auto属性,必须按照宽度来动态指定。

在代码中调用时如下:

        // 获取屏幕的宽高
        DisplayMetrics dm = new DisplayMetrics();
	getWindowManager().getDefaultDisplay().getMetrics(dm); // 获取手机屏幕的大小
        int w_screen = dm.widthPixels;
        int h_screen = dm.heightPixels;
        // 宽高比为16:9 ,-10为两边的留白区域
        webView.loadData(TimeUtils.getNewContent(data.getContent(), ((DisplayUtil.px2dp(this,w_screen)-10)*9)/16), "text/html; charset=UTF-8", null);

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

解决webview显示图片时,宽度100%填充,按照宽高比设置大图防止出现左右滑动后,发现对于小图宽度同样会被拉伸到100%填充,而图片的宽高数据又是包含在html文本中,
现在需求:大图100%填充显示,小图原样显示,解决方案:

后台在上传图片时,大图不指定尺寸,小图设置尺寸,安卓端处理是更改所有图片的宽度填充,高度auto自适配,但是发现小图却没变大小,究其原因是后台编辑器在上传
图片时如果指定了宽高那么img标签会存在width属性,同时<style>里面也设置了图片的宽度,而两者同时存在时style的优先级高于外层width,安卓端更改的是外层的width,
因内层的style指定的width不变,所以图片还是原大小不会被拉伸,当后台不指定宽高上传时,两者都不会存在,安卓端自动为其添加width属性,所以宽度会填充。

WebView展示图文混排,以及出现文字长度超过屏宽造成的WebView可以左右滑动问题


 WebView展示图文混排,以及出现文字长度超过屏宽造成的WebView可以左右滑动问题 

简单实现 

后台返回数是文字含有图片的图文混排格式,当然图片的就是个url,之前只是文字的话很简单用TextView就能解决,即setText(Html.fromHtml(“请求内容”));图文混排的话我这里用的WebView控件展示的:content为请求返回的内容

WebView webView= (WebView) view.findViewById(R.id.content4);

webView.loadDataWithBaseURL("", content, "text/html", "UTF-8", "");

这样的话就可以完成图文混排的展示了,但后来又发现问题图文混排中图片太宽造成屏幕左右滑动才能看全,这个问题最后让后台调整下图片,前端不做处理,用WebView这种方法咱也没地方处理;但又发现文字过宽不自动换行,可能就是前端展示WebView控件可能不支持js等造成的,再添加如下代码支持js:

WebSettings webSettings= webView.getSettings();
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
webSettings.setJavaScriptEnabled(true);//支持js

---------------------------------------------------------------------------------------------------------

在WebView中展示文章的时候,像让文字左右两端对齐,这样比较好看一些。

只需要在相关标签的CSS样式加上

text-align: justify;

即可,适用于普通web和ios,android等移动平台

比如:
Css代码  
    .text {  
        TEXT-INDENT: 2em;  
        line-height: 150%;  
        text-align: justify;  
    }  

webview和js互调时必须添加混淆

androidstudio中将.pro混淆文件的有关于webview和js交互时需要添加的混淆注释解开,然后替换为自己的全路径

// class后面为自己项目的类的全路径:包名.类名,该类指的是@javascriptInterface注解的方法所在的类
-keepclassmembers class com.example.admin.tingxueproject.utils.JavascriptInterface {
   public *;
}
// 解决在4.2及以上系统可能会丢掉@javascriptInterface注解的混淆
-keepattributes *Annotation*
-keepattributes *JavascriptInterface*

0,将.db数据库文件嵌入app并读取

1..db数据库文件保存在项目的assets资产目录下,如data.db
2.创建指向该数据库的db对象,有了db对象就可以对该数据库的表进行增删改查了     
        
        // 初始化,只需要调用一次
        AssetsDatabaseManager.initManager(getApplication());
        // 获取管理对象,因为数据库需要通过管理对象才能够获取
        AssetsDatabaseManager mg = AssetsDatabaseManager.getManager();
        // 通过管理对象获取数据库
        db = mg.getDatabase("data.db");

3.根据db查询数据库的示例,字段模糊匹配,每次取20条记录,pageCount的值为20
  cursor = db.query("card", str, "cata like ? and cata2 like ? and rarity = ?", new String[]{"%"+select01+"%","%"+select02+"%",select03}, null, null, null,0+","+pageCount);
  list = new ArrayList<>();
        while(cursor.moveToNext()){
            String cata3 = cursor.getString(cursor.getColumnIndex("cata3"));
            String name = cursor.getString(cursor.getColumnIndex("name"));
            String pic_s = cursor.getString(cursor.getColumnIndex("pic_s"));
            String pic_b = cursor.getString(cursor.getColumnIndex("pic_b"));
            Card card = new Card(cata3,name,pic_s,pic_b);
            list.add(card);
        }

4.请求下一页的20条数据:
  
  // 第一页:0,20
  // 第二页:20,20
  // 第三页:40,20 
  current += pageCount;
  cursor = db.query("card", str, "cata like ? and cata2 like ? and rarity = ?", new String[]{"%"+select01+"%","%"+select02+"%",select03}, null, null, null,currentStart+","+pageCount); 

1.搜索结果关键字高亮显示

1.工具类

package com.example.admin.tingxueproject.utils;

import android.content.Context;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @function 字符串变色工具类
 */
public class StringFormatUtil {

    private SpannableStringBuilder spBuilder;
    private String wholeStr, highlightStr;
    private Context mContext;
    private int color;

    /**
     * @param context      上下文
     * @param wholeStr     全部文字
     * @param highlightStr 改变颜色的文字
     * @param color        颜色
     */
    public StringFormatUtil(Context context, String wholeStr, String highlightStr, int color) {
        this.mContext = context;
        this.wholeStr = wholeStr;
        this.highlightStr = highlightStr;
        this.color = color;
    }

    /**
     * 填充颜色
     *
     * @return StringFormatUtil
     */
    public StringFormatUtil fillColor() {


        if (!TextUtils.isEmpty(wholeStr) && !TextUtils.isEmpty(highlightStr)) {

            spBuilder = new SpannableStringBuilder(wholeStr);

            //匹配规则
            Pattern p = Pattern.compile(highlightStr);
            //匹配字段
            Matcher m = p.matcher(spBuilder);
            //上色
            color = mContext.getResources().getColor(color);

            //开始循环查找里面是否包含关键字
            while (m.find()) {
                int start = m.start();
                int end = m.end();
                spBuilder.setSpan(new ForegroundColorSpan(color), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }

            return this;
        }
        return null;
    }


    /**
     * 获取到已经更改好的结果(这个时候已经实现了高亮,在获取这个result的时候不要toString()要不然会把色调去除的)
     *
     * @return result
     */
    public SpannableStringBuilder getResult() {
        if (spBuilder != null) {
            return spBuilder;
        }
        return null;
    }

}

2.在Adapter中使用如下:

// 搜索结果关键字高亮显示
// context  总的文本   关键字   关键字的颜色
StringFormatUtil mFormatUtil = new StringFormatUtil(ZXSousuoActivity.this, search.getTitle(), string, 
                                                    R.color.colorAccent).fillColor();
holder.tvTitle.setText(mFormatUtil.getResult());

2.APK二次打包以及优化

二次打包
应用场景:apk经过加固(具体怎么操作不清楚,比较高端),把我们的签名给破坏了,需要用命令进行二次打包

手动签名:(JDK8版本下进行手动签名的完整命令)
jarsigner  -keystore yiyou.jks(签名文件) -storepass tingxue666(密钥)  -signedjar 22.apk(已签名apk) 11.apk(未签名apk) yiyou(别名) 
-digestalg SHA1 -sigalg MD5withRSA -tsa http://timestamp.digicert.com

使用JDK8版本进行手动签名时必须要加上如下两个参数:-digestalg SHA1 和 -sigalg MD5withRSA,否则签名完apk安装时会提示错误:Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]
如果不设置tsa参数,会有如下警告:
警告:
未提供 -tsa 或 -tsacert, 此 jar 没有时间戳。如果没有时间戳, 则在签名者证书的到期日期 (2070-05-29) 或以后的任何撤销日期之后, 用户可能无法验证此 jar。
经测试:将Java环境变量切换到jdk6后,不设置digestalg、sigalg、tsa3个参数, 一切都OK
手动打包时需要注意JDK版本,JDK有版本区分,如果使用的keystore是用JDK6生成的,用JDK8重新签名的话打不开应用直接闪退,所以需要准备对应版本的JDK。
进入命令行(cmd),并cd到jdk的bin目录下(没切到bin目录下会默认去JAVAHOME下找),然后输入上面的完整签名命令即可,如下图:
在这里插入图片描述
注意图中仅参考使用方式,具体的命令书写格式以上面的jdk8完整签名命令为正确,另外建议将未签名apk和签名文件拷贝放到和jarsigner工具同级的目录下,这样绝对路径写法就可以省去了。

zipalign优化

zipalign优化的最根本目的是帮助操作系统更高效率的根据请求索引资源,将resource-handling code统一将Data structure alignment(数据结构对齐标准:DSA)限定为4-byte boundaries。

优化处理方法一:使用命令行
1、在Android SDK的tools文件夹下,找到zipalign.exe文件。
2、把你要优化的apk复制到你解压出来的tools文件夹下。
开始->运行->CMD调出命令行窗口
命令行下输入:

zipalign -v 4 22.apk(需优化) 33.apk(优化后)

其中这里-v代表详细输出,4代表对齐为4个字节。
如下图:
在这里插入图片描述
优化处理方法二:在build.gradle配置

release { 
//Zipalign优化 
zipAlignEnabled true 
}
签名:
jarsigner  -keystore yiyou.jks(签名文件) -storepass tingxue666(密钥)  -signedjar 22.apk(已签名apk) 11.apk(未签名apk) yiyou(别名) -digestalg SHA1 -sigalg MD5withRSA -tsa http://timestamp.digicert.com

优化:
zipalign -v 4 22.apk(需优化) 33.apk(优化后)

3.TextView两端对齐

package com.example.admin.tingxueproject.weight;

import android.content.Context;
import android.graphics.Canvas;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.widget.TextView;

public class JustifyTextView extends TextView {


    /** TextView的总宽度*/
    private int mViewWidth;
    /** 行高*/
    private int mLineY;

    public JustifyTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public JustifyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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

    @Override
    protected void onDraw(Canvas canvas) {
        TextPaint paint = getPaint();
        paint.setColor(getCurrentTextColor());
        paint.drawableState = getDrawableState();
        mViewWidth = getMeasuredWidth();//拿到textview的实际宽度
        String text = getText().toString();
        mLineY = 0;
        mLineY += getTextSize();
        Layout layout = getLayout();
        for (int i = 0; i < layout.getLineCount(); i++) {//每行循环
            int lineStart = layout.getLineStart(i);
            int lineEnd = layout.getLineEnd(i);
            String line = text.substring(lineStart, lineEnd);//获取到TextView每行中的内容
            float width = StaticLayout.getDesiredWidth(text, lineStart,lineEnd, getPaint());
            if (needScale(line)) {
                if (i == layout.getLineCount() - 1) {//最后一行不需要重绘
                    canvas.drawText(line, 0, mLineY, paint);
                } else {
                    drawScaleText(canvas, lineStart, line, width);
                }
            } else {
                canvas.drawText(line, 0, mLineY, paint);
            }
            mLineY += getLineHeight();//写完一行以后,高度增加一行的高度
            System.out.println("lineHeight---" + getLineHeight());
        }
    }

    /**
     * 重绘此行
     *
     * @param canvas  画布
     * @param lineStart  行头
     * @param line  该行所有的文字
     * @param lineWidth 该行每个文字的宽度的总和
     */
    private void drawScaleText(Canvas canvas, int lineStart, String line,
                               float lineWidth) {
        float x = 0;
        if (isFirstLineOfParagraph(lineStart, line)) {
            String blanks = "  ";
            canvas.drawText(blanks, x, mLineY, getPaint());// 以 (x, mLineY) 为起点,画出blanks
            float bw = StaticLayout.getDesiredWidth(blanks, getPaint());// 画出一个空格需要的宽度
            x += bw;
            line = line.substring(3);
        }
        // 比如说一共有5个字,中间隔了4个空儿,
        //	那就用整个TextView的宽度 - 这5个字的宽度,
        //然后除以4,填补到这4个空儿中
        float d = (mViewWidth - lineWidth) / (line.length() - 1);

        for (int i = 0; i < line.length(); i++) {
            String c = String.valueOf(line.charAt(i));
            float cw = StaticLayout.getDesiredWidth(c, getPaint());
            canvas.drawText(c, x, mLineY, getPaint());
            x += cw + d;
        }
    }
    /**
     * 判断是不是段落的第一行。
     * 一个汉字相当于一个字符,此处判断是否为第一行的依据是:
     * 字符长度大于3且前两个字符为空格
     * @param lineStart
     * @param line
     * @return
     */
    private boolean isFirstLineOfParagraph(int lineStart, String line) {
        return line.length() > 3 && line.charAt(0) == ' '
                && line.charAt(1) == ' ';
    }




    /**
     * 判断需不需要缩放
     * 该行最后一个字符不是换行符的时候返回true,
     * 该行最后一个字符是换行符的时候返回false
     * @param line
     * @return
     */
    private boolean needScale(String line) {
        if (line.length() == 0) {
            return false;
        } else {
            return line.charAt(line.length() - 1) != '\n';//该行最后一个字符不是换行符的时候返回true,是换行符的时候返回false
        }
    }
}

4.仿支付余额滚动效果

1.自定义的TextView类:

package com.example.admin.mytest666666;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.TextView;

import java.text.DecimalFormat;

/**
 * 数字滚动的textView
 */
public class NumberRunningTextView extends TextView {

    private static final int MONEY_TYPE = 0;
    private static final int NUM_TYPE = 1;

    private int textType;//内容的类型,默认是金钱类型
    private boolean useCommaFormat;//是否使用每三位数字一个逗号的格式,让数字显得比较好看,默认使用
    private boolean runWhenChange;//是否当内容有改变才使用动画,默认是
    private int duration;//动画的周期,默认为800ms
    private int minNum;//显示数字最少要达到这个数字才滚动 默认为1
    private float minMoney;//显示金额最少要达到这个数字才滚动 默认为0.3

    private DecimalFormat formatter = new DecimalFormat("0.00");// 格式化金额,保留两位小数
    private String preStr;


    public NumberRunningTextView(Context context) {
        this(context, null);
    }

    public NumberRunningTextView(Context context, AttributeSet attrs) {
        this(context, attrs, android.R.attr.textViewStyle);
    }

    public NumberRunningTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.NumberRunningTextView);
        duration = ta.getInt(R.styleable.NumberRunningTextView_duration, 1000);
        textType = ta.getInt(R.styleable.NumberRunningTextView_textType, MONEY_TYPE);
        useCommaFormat = ta.getBoolean(R.styleable.NumberRunningTextView_useCommaFormat, true);
        runWhenChange = ta.getBoolean(R.styleable.NumberRunningTextView_runWhenChange,true);
        minNum = ta.getInt(R.styleable.NumberRunningTextView_minNum, 3);
        minMoney = ta.getFloat(R.styleable.NumberRunningTextView_minMoney,0.1f);

        ta.recycle();
    }


    /**
     * 设置需要滚动的金钱(必须为正数)或整数(必须为正数)的字符串
     *
     * @param str
     */
    public void setContent(String str) {
        //如果是当内容改变的时候才执行滚动动画,判断内容是否有变化
        if (runWhenChange){
            if (TextUtils.isEmpty(preStr)){
                //如果上一次的str为空
                preStr = str;
                useAnimByType(str);
                return;
            }

            //如果上一次的str不为空,判断两次内容是否一致
            if (preStr.equals(str)){
                //如果两次内容一致,则不做处理
                return;
            }

            preStr = str;//如果两次内容不一致,记录最新的str
        }

        useAnimByType(str);
    }

    private void useAnimByType(String str) {
        if (textType == MONEY_TYPE) {
            playMoneyAnim(str);
        } else if (textType == NUM_TYPE){
            playNumAnim(str);
        }
    }


    /**
     * 播放金钱数字动画的方法
     *
     * @param moneyStr
     */
    public void playMoneyAnim(String moneyStr) {
        String money = moneyStr.replace(",", "").replace("-", "");//如果传入的数字已经是使用逗号格式化过的,或者含有符号,去除逗号和负号
        try {
            float finalFloat = Float.parseFloat(money);
            if (finalFloat < minMoney) {
                //如果传入的为0,则直接使用setText()
                setText(moneyStr);
                return;
            }
            ValueAnimator floatAnimator =  ValueAnimator.ofFloat(0, finalFloat);
            floatAnimator.setDuration(duration);
            floatAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float currentNum = (float) animation.getAnimatedValue();
                    String str = formatter.format(Double.parseDouble(String.valueOf(currentNum)));//格式化成两位小数
                    // 更新显示的内容
                    if (useCommaFormat) {
                        //使用每三位数字一个逗号的格式
                        String formatStr = StringUtils.addComma(str);//三位一个逗号格式的字符串
                        setText(formatStr);
                    } else {
                        setText(str);
                    }
                }
            });
            floatAnimator.start();
        } catch (NumberFormatException e) {
            e.printStackTrace();
            this.setText(moneyStr);//如果转换Double失败则直接用setText
        }
    }

    /**
     * 播放数字动画的方法
     *
     * @param numStr
     */
    public void playNumAnim(String numStr) {
        String num = numStr.replace(",", "").replace("-", "");//如果传入的数字已经是使用逗号格式化过的,或者含有符号,去除逗号和负号
        try {
            int finalNum = Integer.parseInt(num);
            if (finalNum < minNum) {
                //由于是整数,每次是递增1,所以如果传入的数字比帧数小,则直接使用setText()
                this.setText(numStr);
                return;
            }
            ValueAnimator intAnimator = new ValueAnimator().ofInt(0, finalNum);
            intAnimator.setDuration(duration);
            intAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    int currentNum = (int) animation.getAnimatedValue();
                    setText(String.valueOf(currentNum));
                }
            });
            intAnimator.start();
        } catch (NumberFormatException e) {
            e.printStackTrace();
            setText(numStr);//如果转换Double失败则直接用setText
        }
    }
}

2.自定义属性attr.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="NumberRunningTextView">
        <attr name="duration" format="integer"></attr>
        <attr name="minNum" format="integer"></attr>
        <attr name="minMoney" format="float"></attr>
        <!--内容的格式-->
        <attr name="textType">
            <enum name="money" value="0"></enum>
            <enum name="num" value="1"></enum>
        </attr>
        <!--是否使用每三位数字一个逗号-->
        <attr name="useCommaFormat" format="boolean"></attr>
        <!--是否当内容改变的时候使用动画,不改变则不使用动画-->
        <attr name="runWhenChange" format="boolean"></attr>

    </declare-styleable>

</resources>

3.工具类StringUtils.java代码:

package com.example.admin.mytest666666;

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class StringUtils {

    /**
     * 格式化字符串,每三位用逗号隔开
     *
     * @param str
     * @return
     */
    public static String addComma(String str) {
        str = new StringBuilder(str).reverse().toString();     //先将字符串颠倒顺序
        if (str.equals("0")) {
            return str;
        }
        String str2 = "";
        for (int i = 0; i < str.length(); i++) {
            if (i * 3 + 3 > str.length()) {
                str2 += str.substring(i * 3, str.length());
                break;
            }
            str2 += str.substring(i * 3, i * 3 + 3) + ",";
        }
        if (str2.endsWith(",")) {
            str2 = str2.substring(0, str2.length() - 1);
        }
        //最后再将顺序反转过来
        String temp = new StringBuilder(str2).reverse().toString();
        //将最后的,去掉
        return temp.substring(0, temp.lastIndexOf(",")) + temp.substring(temp.lastIndexOf(",") + 1, temp.length());
    }


    public static String formatDoublePointTwo(double money) {
        //保持小数点后两位
        DecimalFormat formater = new DecimalFormat();
        formater.setMaximumFractionDigits(2);
        formater.setGroupingSize(0);
        formater.setRoundingMode(RoundingMode.FLOOR);
        return formater.format(money);
    }

    public static String formatTimeYMD(String time) {
        try {
            Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(time);
            return new SimpleDateFormat("yyyy-MM-dd").format(date);
        } catch (ParseException e) {
            e.printStackTrace();
            return "日期获取失败";
        }
    }

}

4.1.在布局文件layout中定义如下:

<com.chaychan.viewlib.NumberRunningTextView
            android:id="@+id/tv_num"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="200"
            android:textColor="#fff"
            android:textSize="30sp"
            android:textStyle="bold"
            app:textType="num"
/>

1.textType是用于指定内容的格式,总共有money(金钱格式,带小数)和num(整数格式),默认是金钱的格式,不配置textType的话,默认就是使用金钱格式。
2.默认金额显示的整数部分每三位添加一个逗号,如果不想要这种格式的数字,可以在布局文件中,NumberRunningTextView的配置中,将useCommaFormat设置为false,这样最终的数字就不会是带有逗号了。

4.2.在activity中进行赋值:

tv_num = (NumberRunningTextView) findViewById(R.id.tv_num);
tv_money = (NumberRunningTextView) findViewById(R.id.tv_money);
tv_num.setContent("200");
tv_money.setContent("1354.00");

1.当一开始进入界面的时候,初始化数据完毕,NumberRunningTextView设置数据完毕,会自动执行数字滚动的动画,如果进行刷新操作,从服务器获取新的数据,重新设置数据,NumberRunningTextView会自动判断传入的内容是否有变化,如果没有变化,则不会再次滚动,而当金额发生变化后,就会再次滚动,如果想要在刷新的时候,无论内容是否有变化都要执行滚动动画的话,可以在布局文件中,NumberRunningTextView的配置中,将runWhenChange设置为false即可,此时,无论内容是否有变化,都会执行滚动动画。
2.NumberRunningTextView默认是30帧,如果需要修改帧数,可以在布局文件中,NumberRunningTextView的配置中,将frameNum设置为自己想要的帧数。

5.自定义跟随TextView一起居中的drawable

package com.example.admin.tingxueproject.weight;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.TextView;

/**
 * drawableLeft与文本一起居中显示
 */
public class DrawableCenterTextView extends TextView {

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

    public DrawableCenterTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public DrawableCenterTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Drawable[] drawables = getCompoundDrawables();
        if (drawables != null) {
            Drawable drawableLeft = drawables[0];
            if (drawableLeft != null) {
                float textWidth = getPaint().measureText(getText().toString());
                int drawablePadding = getCompoundDrawablePadding();
                int drawableWidth = 0;
                drawableWidth = drawableLeft.getIntrinsicWidth();
                float bodyWidth = textWidth + drawableWidth + drawablePadding;
                canvas.translate((getWidth() - bodyWidth) / 2, 0);
            }
        }
        super.onDraw(canvas);
    }
}

用法和一般的TextView用法相同
自定义控件使用DrawableLeft/Right图片和文字同时居中:https://blog.csdn.net/eileenching/article/details/48393531

6.Glide加载图片的两种方式,动态解决图片适配问题

两种方式如下:

// 获取到原图对应的
//            Glide.with(mActivity).load(GlobalUrl.BASE_URL + image1 ).into(holder.iv1); // 方式1

                // 方式2
                Glide.with(mActivity).load(GlobalUrl.BASE_URL + image1).asBitmap()
                    .placeholder(R.mipmap.default2)
                    .into(new SimpleTarget<Bitmap>(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) {
                @Override
                public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                    int imageWidth = resource.getWidth(); // 获取到图片的宽度
                    int imageHeight = resource.getHeight(); // 获取到图片的高度
                    Log.d("test","原始图片的宽度为:"+imageWidth);
                    Log.d("test","原始图片的高度为:"+imageHeight);
                    // 判断宽和高的大小关系,以长的一边为基准
                    if(imageWidth == imageHeight){
                        Log.d("test","宽度等于高度");
                        // 如果宽高相等
                        RelativeLayout.LayoutParams para = (RelativeLayout.LayoutParams) holder.rl.getLayoutParams();
                        // 动态设置imageview的宽高,然后再加载图片
                        // 获取到屏幕的宽度
                        DisplayMetrics dm = new DisplayMetrics();
                        mActivity.getWindowManager().getDefaultDisplay().getMetrics(dm); // 获取手机屏幕的大小
                        para.height = para.width = (int)(dm.widthPixels/3*1.7);
                    }else if(imageWidth > imageHeight){
                        // 如果宽高相等
                        RelativeLayout.LayoutParams para = (RelativeLayout.LayoutParams) holder.rl.getLayoutParams();
                        // 动态设置imageview的宽高,然后再加载图片
                        // 获取到屏幕的宽度
                        DisplayMetrics dm = new DisplayMetrics();
                        mActivity.getWindowManager().getDefaultDisplay().getMetrics(dm); // 获取手机屏幕的大小
                        para.width = (int)(dm.widthPixels/3*1.7);
                        para.height =  para.width*imageHeight/imageWidth;

                    }else if(imageWidth < imageHeight){
                        // 如果宽高相等
                        RelativeLayout.LayoutParams para = (RelativeLayout.LayoutParams) holder.rl.getLayoutParams();
                        // 动态设置imageview的宽高,然后再加载图片
                        // 获取到屏幕的宽度
                        DisplayMetrics dm = new DisplayMetrics();
                        mActivity.getWindowManager().getDefaultDisplay().getMetrics(dm); // 获取手机屏幕的大小
                        para.height = (int)(dm.widthPixels/3*1.7);
                        para.width = para.height*imageWidth/imageHeight;
                    }
                    // 设置图片
                    holder.iv1.setImageBitmap(resource);
                }
            });

7.Glide加载长图适配

http://blog.csdn.net/libra_louis/article/details/58604149

如:其中imageview(iv1)的宽高均为填充父容器,而他的父容器即为相对布局rl,rl的宽高指定为105dp。(防止滑动时尺寸的变化)

Glide.with(mActivity).load(GlobalUrl.BASE_URL + image1).asBitmap()
                    .into(new SimpleTarget<Bitmap>(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) {
                        @Override
                        public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                            // 获取到屏幕的宽度
                            DisplayMetrics dm = new DisplayMetrics();
                            mActivity.getWindowManager().getDefaultDisplay().getMetrics(dm); // 获取手机屏幕的大小
                            int imageWidth = resource.getWidth(); // 获取到图片的宽度
                            int imageHeight = resource.getHeight(); // 获取到图片的高度
//                    Log.d("test","原始图片的宽度为:"+imageWidth);
//                    Log.d("test","原始图片的高度为:"+imageHeight);
                            // 判断宽和高的大小关系,以长的一边为基准
                            if(imageWidth == imageHeight){
                                // 如果宽高相等
                                RelativeLayout.LayoutParams para = (RelativeLayout.LayoutParams) holder.rl.getLayoutParams();
                                // 动态设置imageview的宽高,然后再加载图片
                                para.height = para.width = (int)(dm.widthPixels/3*1.7);
                                holder.rl.setLayoutParams(para);
                                holder.iv1.setImageBitmap(resource);
                            }else if(imageWidth > imageHeight){
                                // 如果宽高相等
                                RelativeLayout.LayoutParams para = (RelativeLayout.LayoutParams) holder.rl.getLayoutParams();
                                // 动态设置imageview的宽高,然后再加载图片
                                para.width = (int)(dm.widthPixels/3*1.7);
                                para.height =  para.width*imageHeight/imageWidth;
                                holder.rl.setLayoutParams(para);
                                holder.iv1.setImageBitmap(resource);
                            }else if(imageWidth < imageHeight){
                                // 如果宽小于高,判断是否为长图
//                                if(imageHeight > 4096) {
                                if(imageHeight > dm.heightPixels ) {
                                    RelativeLayout.LayoutParams para = (RelativeLayout.LayoutParams) holder.rl.getLayoutParams();
                                    para.width = DisplayUtil.dp2px(mActivity,105);
                                    para.height =  DisplayUtil.dp2px(mActivity,105);
                                    holder.rl.setLayoutParams(para);
                                    holder.iv1.setLayoutParams(para);
                                    // 开始加载图片
                                    Glide.with(mActivity)
                                            .load(GlobalUrl.BASE_URL + image)
                                            .dontAnimate()
                                            .into(holder.iv1);
                                }else{
                                    RelativeLayout.LayoutParams para = (RelativeLayout.LayoutParams) holder.rl.getLayoutParams();
                                    para.height = (int)(dm.widthPixels/3*1.7);
                                    para.width = para.height*imageWidth/imageHeight;
                                    holder.rl.setLayoutParams(para);
                                    holder.iv1.setImageBitmap(resource);
                                }
                            }
                        }
                    });

8.webview和js互调时必须添加混淆

androidstudio中将.pro混淆文件的有关于webview和js交互时需要添加的混淆注释解开,然后替换为自己的全路径

// class后面为自己项目的类的全路径:包名.类名,该类指的是@javascriptInterface注解的方法所在的类
-keepclassmembers class com.example.admin.tingxueproject.utils.JavascriptInterface {
   public *;
}
// 解决在4.2及以上系统可能会丢掉@javascriptInterface注解的混淆
-keepattributes *Annotation*
-keepattributes *JavascriptInterface*

9.webview显示图片视频的适配问题

//  适配工具方法
    public static String getNewContent(String htmltext,int height){

      Document doc= Jsoup.parse(htmltext);
       Elements elements1=doc.getElementsByTag("img");
         for (Element element : elements1) {
                 element.attr("width","100%").attr("height","auto");
              }
        Elements elements2=doc.getElementsByTag("iframe");
        for (Element element : elements2) {
            element.attr("width","100%").attr("height",height+"");
        }
              return doc.toString();
           }
------------------------------------------------------------------------------
需要:jsoup的jar包
以上方法的第二个参数只为视频设置,因为iframe标签无auto属性,必须按照宽度来动态指定。

在代码中调用时如下:

        // 获取屏幕的宽高
        DisplayMetrics dm = new DisplayMetrics();
	getWindowManager().getDefaultDisplay().getMetrics(dm); // 获取手机屏幕的大小
        int w_screen = dm.widthPixels;
        int h_screen = dm.heightPixels;
        // 宽高比为16:9 ,-10为两边的留白区域
        webView.loadData(TimeUtils.getNewContent(data.getContent(), ((DisplayUtil.px2dp(this,w_screen)-10)*9)/16), "text/html; charset=UTF-8", null);

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

解决webview显示图片时,宽度100%填充,按照宽高比设置大图防止出现左右滑动后,发现对于小图宽度同样会被拉伸到100%填充,而图片的宽高数据又是包含在html文本中,
现在需求:大图100%填充显示,小图原样显示,解决方案:

后台在上传图片时,大图不指定尺寸,小图设置尺寸,安卓端处理是更改所有图片的宽度填充,高度auto自适配,但是发现小图却没变大小,究其原因是后台编辑器在上传
图片时如果指定了宽高那么img标签会存在width属性,同时<style>里面也设置了图片的宽度,而两者同时存在时style的优先级高于外层width,安卓端更改的是外层的width,
因内层的style指定的width不变,所以图片还是原大小不会被拉伸,当后台不指定宽高上传时,两者都不会存在,安卓端自动为其添加width属性,所以宽度会填充。

9.WebView展示图文混排,以及出现文字长度超过屏宽造成的WebView可以左右滑动问题


 WebView展示图文混排,以及出现文字长度超过屏宽造成的WebView可以左右滑动问题 

简单实现 

后台返回数是文字含有图片的图文混排格式,当然图片的就是个url,之前只是文字的话很简单用TextView就能解决,即setText(Html.fromHtml(“请求内容”));图文混排的话我这里用的WebView控件展示的:content为请求返回的内容

WebView webView= (WebView) view.findViewById(R.id.content4);

webView.loadDataWithBaseURL("", content, "text/html", "UTF-8", "");

这样的话就可以完成图文混排的展示了,但后来又发现问题图文混排中图片太宽造成屏幕左右滑动才能看全,这个问题最后让后台调整下图片,前端不做处理,用WebView这种方法咱也没地方处理;但又发现文字过宽不自动换行,可能就是前端展示WebView控件可能不支持js等造成的,再添加如下代码支持js:

WebSettings webSettings= webView.getSettings();
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
webSettings.setJavaScriptEnabled(true);//支持js

---------------------------------------------------------------------------------------------------------

在WebView中展示文章的时候,像让文字左右两端对齐,这样比较好看一些。

只需要在相关标签的CSS样式加上

text-align: justify;

即可,适用于普通web和ios,android等移动平台

 

比如:
Css代码  
    .text {  
        TEXT-INDENT: 2em;  
        line-height: 150%;  
        text-align: justify;  
    }  

10.将glide下载的缓存图片保存在本地

在这里插入代码片项目需求:使用glide加载显示网络图片,然后在图片上长按出现保存到本地选项,点击可以保存到本地。
解决方案:因为是网络图片,所以保存到本地是否会有下载的过程??
          Glide加载显示图片已经将图片下载并且缓存到了本地,我们只需将该缓存重新保存在手机系统相册即可,那么如何将glide的缓存保存到本地呢?
          实现的方法如下:(需要写入SD卡的权限)
          
    // 思路:从glide中获取到指定url的bitmap对象,然后将其转换成二进制再写入本地,获取bitmap必须放在子线程中来完成,
    @NeedsPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
    void saveImage(final String s1) {
        //将ImageView中的图片转换成Bitmap
        /*iv.buildDrawingCache();
        Bitmap bitmap = iv.getDrawingCache();*/
        new Thread(new Runnable() {
            @Override
            public void run() {
                Bitmap bitmap = null;
                try {
                    bitmap = Glide.with(ImageActivity.this)
                            .load(image)
                            .asBitmap()
                            .into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
                            .get();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
                if(bitmap != null){
                    //将Bitmap 转换成二进制,写入本地
                    ByteArrayOutputStream stream = new ByteArrayOutputStream();
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
                    byte[] byteArray = stream.toByteArray();
                    File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/yiyou");
                    Log.d("test","dir的路径地址为:"+dir.getPath());
                    if (!dir.isFile()) {
                        dir.mkdir();
                    }
                /*// 获取当前时间戳字符串,精确到毫秒
                SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmm"); //精确到毫秒
                String suffix = fmt.format(new Date());*/
                    String s = s1;
                    File file = new File(dir, s);
                    Message msg = new Message();
                    msg.what = 0x22;
                    msg.obj = file.getPath();
                    mHandler.sendMessage(msg);
                    try {
                        FileOutputStream fos = new FileOutputStream(file);
                        fos.write(byteArray, 0, byteArray.length);
                        fos.flush();
                        //用广播通知相册进行更新相册
                        Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                        Uri uri = Uri.fromFile(file);
                        intent.setData(uri);
                        sendBroadcast(intent);
//                    Toast.makeText(ImageActivity.this, "图片保存成功,保存路径为"+, Toast.LENGTH_SHORT).show();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智玲君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值