Android 在WebView中通过javascript获取网页源码,并在TextView或者在EditText中显示问题

Android 在WebView中通过javascript获取网页源码,并在TextView或者在EditText中显示问题,第1张

webview js之间的交互,项目中马上用到。

JS调用java代码效果图

java代码调用javasrcipt代码效果图

indexhtml代码:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 401//EN" ">

<xml version="10" encoding="utf-8"><LinearLayout xmlns:android=">

public class MainActivity extends AppCompatActivity {private WebView mWebView;    @Override    protected void onCreate(Bundle savedInstanceState) {        superonCreate(savedInstanceState);        setContentView(Rlayoutactivity_main);         mWebView = (WebView) findViewById(Ridtest_webview);        //设置WebView支持JavaScript        mWebViewgetSettings()setJavaScriptEnabled(true);        mWebViewloadUrl("file:///android_asset/indexhtml");        mWebViewaddJavascriptInterface(new JsInterface(this), "AndroidWebView");        //添加客户端支持        mWebViewsetWebChromeClient(new WebChromeClient());        findViewById(Ridtest_btn)setOnClickListener(new ViewOnClickListener() {            @Override            public void onClick(View v) {

sendInfoToJs();            }

});    }    private class JsInterface {        private Context mContext;        public JsInterface(Context context) {            thismContext = context;        }        //在js中调用windowAndroidWebViewshowInfoFromJs(name),便会触发此方法。        @JavascriptInterface        public void showInfoFromJs(String share) {

ToastmakeText(mContext, share, ToastLENGTH_SHORT)show();        }

}    //在java中调用js代码    public void sendInfoToJs() {

String msg = ((EditText)findViewById(Ridtest_edt))getText()toString();        //调用js中的函数:showInfoFromJava(msg)        mWebViewloadUrl("javascript:showInfoFromJava('" + msg + "')");    }

总结下,java代码中要设置webview对javascript的支持,addJavascriptInterface(new JsInterface(this), "AndroidWebView");//这句代码中的第二个参数是在js访问方法的地址。

windowAndroidWebViewshowInfoFromJs(share);

自定义侧边字母导航栏,根据实际字母高度进行显示

先上效果图

public class SlideBar extends View {

    //当前手指滑动到的位置

    private int choosedPosition = -1;

    //画文字的画笔

    private Paint paint;

    //单个字母的高度

    private float perTextHeight;

    //字母的字体大小

    private float letterSize;

    //字母的垂直间距

    private float letterGap;

    //字母圆形背景半径

    private float bgRadius;

    private ArrayList<String> firstLetters = new ArrayList<>();

    //绘制点击时的蓝色背景

    private Paint backgroundPaint;

    private Context context;

    private OnTouchFirstListener listener;

    public RecyclerView getTiku_recycle_answer() {

        return tiku_recycle_answer;

    }

    public void setTiku_recycle_answer(RecyclerView tiku_recycle_answer) {

        thistiku_recycle_answer = tiku_recycle_answer;

    }

    RecyclerView tiku_recycle_answer;

    public SlideBar(Context context) {

        this(context, null);

    }

    public SlideBar(Context context, AttributeSet attrs) {

        this(context, attrs, 0);

    }

    public SlideBar(Context context, AttributeSet attrs, int defStyleAttr) {

        super(context, attrs, defStyleAttr);

        thiscontext = context;

        TypedArray typedArray = contextobtainStyledAttributes(attrs, RstyleableSlideBar);

        //字母的字体大小

        letterSize = typedArraygetDimension(RstyleableSlideBar_letter_size, DisplayUtilssp2px(context, 100f));

        //每个字母的高

        perTextHeight = typedArraygetDimension(RstyleableSlideBar_letter_height, DisplayUtilsdp2px(context, 100f));

        //字母垂直间距

        letterGap = typedArraygetDimension(RstyleableSlideBar_letter_gap, DisplayUtilsdp2px(context, 60f));

        //字母垂直间距

        bgRadius = typedArraygetDimension(RstyleableSlideBar_letter_bg_radius, DisplayUtilsdp2px(context, 80f));

        typedArrayrecycle();

        init();

    }

    public void init() {

        //初始化画笔

        paint = new Paint();

        paintsetAntiAlias(true);

        paintsetTextSize(letterSize);

        paintsetTypeface(TypefaceDEFAULT_BOLD);

        //初始化圆形背景画笔

        backgroundPaint = new Paint();

        backgroundPaintsetAntiAlias(true);

        backgroundPaintsetColor(contextgetResources()getColor(Rcolorcolor_368FFF));

    }

    public void setFirstLetters(ArrayList<String> letters) {

        firstLettersclear();

        firstLettersaddAll(letters);

        invalidate();

    }

    @Override

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int widthMode = MeasureSpecgetMode(widthMeasureSpec);  //获取宽的模式

        int heightMode = MeasureSpecgetMode(heightMeasureSpec); //获取高的模式

        int widthSize = MeasureSpecgetSize(widthMeasureSpec);  //获取宽的尺寸

        int heightSize = MeasureSpecgetSize(heightMeasureSpec); //获取高的尺寸

        int width = 0;

        int height;

        if (widthMode == MeasureSpecEXACTLY) {

            //如果match_parent或者具体的值,直接赋值

            width = widthSize;

        } else {

            //如果其他模式,则指定一个宽度

            width = DisplayUtilsdp2px(getContext(), 200f);

        }

        //高度跟宽度处理方式一样

        if (heightMode == MeasureSpecEXACTLY) {

            height = heightSize;

        } else {

            float textHeight = perTextHeight;

            height = (int) (getPaddingTop() + textHeight (firstLetterssize() + 1) + letterGap (firstLetterssize() - 1) + getPaddingBottom());

        }

        if (height > tiku_recycle_answergetMeasuredHeight()) {

            height = tiku_recycle_answergetMeasuredHeight();

        }

        //保存测量宽度和测量高度

        setMeasuredDimension(width, height);

    }

    @Override

    protected void onDraw(Canvas canvas) {

        superonDraw(canvas);

        for (int i = 0; i < firstLetterssize(); i++) {

            paintsetColor(i == choosedPosition ColorWHITE : contextgetResources()getColor(Rcolorcolor_368FFF));

            float x = (getWidth() - paintmeasureText(firstLettersget(i))) / 2;

            float y = (float) getHeight() / firstLetterssize();//每个字母的高度

            if (i == choosedPosition) {

                canvasdrawCircle((float) (getWidth() / 2), i y + y / 2, bgRadius, backgroundPaint);

            }

            //垂直位置需要增加一个偏移量,上移两个像素,因为根据计算得到的是baseline,将字母上移,使其居中在圆内

            canvasdrawText(firstLettersget(i), x, (perTextHeight + y) / 2 + y i-2, paint);

        }

    }

    //触碰事件

    //按下,松开,拖动

    @Override

    public boolean onTouchEvent(MotionEvent event) {

        switch (eventgetAction()) {

            case MotionEventACTION_DOWN:

            case MotionEventACTION_MOVE:

                thissetBackgroundColor(contextgetResources()getColor(androidRcolortransparent));

                float y = eventgetY();

                //获取触摸到字母的位置

                choosedPosition = (int) y firstLetterssize() / getHeight();

                //上滑超过边界,显示第一个

                if (choosedPosition < 0) {

                    choosedPosition = 0;

                }

                //下滑超过边界,显示最后一个

                if (choosedPosition >= firstLetterssize()) {

                    choosedPosition = firstLetterssize() - 1;

                }

                if (listener != null) {

                    //滑动A-Z字母联动外层数据

                    listeneronTouch(firstLettersget(choosedPosition));

                }

                break;

            case MotionEventACTION_UP:

                thissetBackgroundColor(contextgetResources()getColor(androidRcolortransparent));

                choosedPosition = -1;

                if (listener != null) {

                    //滑动A-Z字母联动外层数据

                    listeneronRelease();

                }

                break;

        }

        //重绘

        invalidate();

        return true;

    }

    public void setFirstListener(OnTouchFirstListener listener) {

        thislistener = listener;

    }

    /

    OnTouchFirstListener 接口

    onTouch:触摸到了那个字母

    onRelease:up释放时中间显示的字母需要设置为GONE

    /

    public interface OnTouchFirstListener {

        void onTouch(String firstLetter);

        void onRelease();

    }

}

<declare-styleable name="SlideBar">

    <attr name="letter_size" format="dimension" />

    <attr name="letter_height" format="dimension" />

    <attr name="letter_gap" format="dimension" />

    <attr name="letter_bg_radius" format="dimension" />

</declare-styleable>

xml中引入,我的是constraintlayout,具体设置看自己的布局

<comanswerviewSlideBar

    android:id="@+id/slideBar"

    android:layout_width="@dimen/dp_20"

    android:layout_height="wrap_content"

    app:layout_constraintBottom_toBottomOf="@+id/tiku_recycle_answer"

    app:layout_constraintEnd_toEndOf="parent"

    app:layout_constraintStart_toStartOf="@+id/guide_answer"

    app:layout_constraintTop_toTopOf="@+id/tiku_recycle_answer"

    app:letter_bg_radius="@dimen/dp_8"

    app:letter_gap="@dimen/dp_6"

    app:letter_height="@dimen/dp_10"

    app:letter_size="@dimen/sp_10" />

private void handleSlideBarEvent() {

    List<QuesCommentSubjectiveStuBean> datas = subjectiveCommentDetailAdaptergetDatas();//获取处理后的数据,赋值给导航栏

    ArrayList<String> letters = new ArrayList<>();

    for (QuesCommentSubjectiveStuBean stuBean : datas) {

        if (letterscontains(stuBeangetFirstLetter())) {

            continue;

        }

        lettersadd(stuBeangetFirstLetter());

    }

    slideBarsetFirstLetters(letters);

    slideBarsetTiku_recycle_answer(tiku_recycle_answer);

    slideBarsetFirstListener(new SlideBarOnTouchFirstListener() {

        @Override

        public void onTouch(String firstLetter, float dy) {

            tv_first_lettersetVisibility(VISIBLE);

            tv_first_lettersetText(firstLetter);

            ConstraintLayoutLayoutParams layoutParams = (ConstraintLayoutLayoutParams) tv_first_lettergetLayoutParams();

            //如果是第一个字母,修改提示框显示位置

            layoutParamstopMargin = (int) dy + slideBargetTop() - tv_first_lettergetMeasuredHeight() / 2;

            //异常情况,点击最后一个字符,提示框显示不全的场景,如果显示位置超过屏幕,则靠底部显示

            if ((int) dy + slideBargetTop() + tv_first_lettergetMeasuredHeight() / 2 > tiku_recycle_answergetBottom()) {

                layoutParamstopMargin = tiku_recycle_answergetBottom() - tv_first_lettergetMeasuredHeight();

            }

            tv_first_lettersetLayoutParams(layoutParams);

            //滑动后移动到对应的位置,找到第一个匹配到首字母的学生,位移到此处

            int newPosition = -1;

            for (QuesCommentSubjectiveStuBean stuBean : datas) {

                if (firstLetterequals(stuBeangetFirstLetter())) {

                    newPosition = datasindexOf(stuBean);

                    break;

                }

            }

            //move时会多次触发,此处只响应第一次

            if (newPosition != lastPosition) {

                lastPosition = newPosition;

                Lgd(TAG, "questionComment-->--滑动导航栏跳转到首字母:" + firstLetter);

                subJectLinearLayoutManagerscrollToPositionWithOffset(lastPosition, 0);

            }

        }

        @Override

        public void onRelease() {

            postDelayed(new Runnable() {

                @Override

                public void run() {

                    lastPosition = -1;

                    tv_first_lettersetVisibility(GONE);

                }

            }, 200);

        }

    });

}

5一个小问题。

用于放大显示选中字母的TextView在布局中,请设置为invisible,这样在加载xml布局时,会对这个控件进行测量和布局,只是不显示,这样我们才能获得tv_first_lettergetMeasuredHeight(),如果设置为gone,不会进行测量,获取的高度就为0,这样在第一次显示的时候就会有一个显示位置跳动的异常。设置为invisible就可以解决这个问题,目的就是让系统测量一下TextView的宽高,不想这么搞的话,在第4步之前手动测量一次也是可以的。

<TextView

    android:id="@+id/tv_first_letter"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_marginEnd="@dimen/dp_2"

    android:background="@mipmap/ic_bubble"

    android:fontFamily="sans-serif"

    android:gravity="center"

    android:text="C"

    android:textColor="@color/color_ffffff"

    android:textSize="@dimen/sp_18"

    android:visibility="invisible"

    app:layout_constraintEnd_toStartOf="@+id/guide_answer"

    app:layout_constraintTop_toTopOf="parent" />

具体步骤如下:

1 编写一个文本样式。

DIALOG的标题是一个textview,在sytlesxml中,添加如下代码来设置你自己的文本样式:

<style name="DialogWindowTitle">

<item name="android:textSize">22sp</item>

<item name="android:textColor">@color/font_dark_grey</item>

</style>

2 设置对话框的标题主题

上面的标题文本并不能直接设置为对话框的标题样式。 我们还需要编写一个表示标题的主题的style,在这里指定标题的文本样式。代码如下:

<style name="DialogWindowTitleDeviceDefault">

<item name="android:maxLines">1</item>

<item name="android:scrollHorizontally">true</item>

<item name="android:textAppearance">@style/DialogWindowTitle</item>

</style>

3 设置对话框主题。

接下来,我们编写我们的对话框主题,在这里指定标题的主题。由于一些属性并不是public的,所以我们需要继承自原来的某个style,代码如下:

<!--Dialog主题-->

<style name="ThemeDeviceDefaultDialog" parent="@android:style/ThemeDeviceDefaultLightDialog">

<item name="android:windowTitleStyle">@style/DialogWindowTitleDeviceDefault</item>

</style>

4自定义App的主题。

接下来,我们需要在我们的App theme中指定我们的对话框使用这种主题,所以需要定义一个App theme。同样由于App theme的许多属性并不是public的(比如下面要提到的标题下面的那条蓝线),所以我们要继承自一个原生的style。这里我根据程序需要选择了ThemeHoloLightNoActionBar,代码如下:

<style name="ParkingTheme" parent="@android:style/ThemeHoloLightNoActionBar">

<item name="android:dialogTheme">@style/ThemeDeviceDefaultDialog</item>

</style>

5 指定App主题

我们需要在AndroidManifestxml文件中,指定我们的app主题。这步很简单,只需要在application标签中指定android:theme的值即可,如下:

android:theme="@style/ParkingTheme"

6 编写AlertDialog主题。

我们无法直接继承系统主题里的AlertDialog的style。如把parent指定为ThemeDeviceDefaultDialogAlert,ThemeHoloDialogAlert,ThemeDeviceDefaultLightDialogAlert或ThemeHoloLightDialogAlert,都会导致编译不过。所以我们需要继承自Dialog的style。在这里我以ThemeHoloLightDialog为例,代码如下:

<!--AlderDialog主题-->

<style name="ThemeDeviceDefaultDialogAlert" parent="@android:style/ThemeHoloLightDialog">

<item name="android:windowBackground">@android:color/transparent</item>

<item name="android:windowTitleStyle">@style/DialogWindowTitleDeviceDefault</item>

<item name="android:windowContentOverlay">@null</item>

<item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>

<item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item>

</style>

7 指定AlertDialog的主题。

我们需要在第4步所说的自定义的AppTheme中,添加一行代码来指定要使用的AlertDialog的style,代码如下:

<item name="android:alertDialogTheme">@style/ThemeDeviceDefaultDialogAlert</item>

8修改标题下面的蓝色线。

表示这条蓝色的线的叫做titleDivider,我们可以通过getResources()的API来获取它的IP,然后设置颜色。代码如下:

public static final void dialogTitleLineColor(Dialog dialog, int color) {

Context context = dialoggetContext();

int divierId = contextgetResources()getIdentifier("android:id/titleDivider", null, null);

View divider = dialogfindViewById(divierId);

dividersetBackgroundColor(color);

这行代码对于自定义的Dialog,可以在setContentView之后调用。但是对于AlertDialog,必须在show()方法被调用之后才可以去调用,否则会报错。

Android是一种基于Linux的自由及开放源代码的 *** 作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。

尚未有统一中文名称,中国大陆地区较多人使用“安卓”或“安智”。Android *** 作系统最初由Andy Rubin开发,主要支持手机。2005年7月由Google收购注资。2007年11月,Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。

随后Google以Apache开源许可证的授权方式,发布了Android的源代码。第一部Android智能手机发布于2008年10月。

Android逐渐扩展到平板电脑及其他领域上,如电视、数码相机、游戏机等。2011年第一季度,Android在全球的市场份额首次超过塞班系统,跃居全球第一。

2013年的第四季度,Android平台手机的全球市场份额已经达到781%。2013年09月24日谷歌开发的 *** 作系统Android在迎来了5岁生日,全世界采用这款系统的设备数量已经达到10亿台。

android无法获取res资源文件夹路径,只能通过系统提供的封装函数访问。

资源文件夹有:

/res/drawable

,通过getresources()访问

/res/values

,通过getresources()访问

/res/layout,通过getresources()访问

/res/xml,通过getresources()访问

/res/raw,通过getresources()访问

/assets,通过getassets()访问

beforeDescendants:viewgroup会优先其子类控件而获取到焦点

afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点

blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点

所以,你应该用第二个设置,这样子控件就可以优先获取到焦点了

@dimen/activity_vertical_margin这个的意思就是在你的values文件夹下面的dimens文件里面有一个name叫做activity_vertical_margin的项,这个项里面值就是你android:paddingBottom的值,比如<dimen name="activity_vertical_margin">10dp</dimen> android:paddingBottom=“@dimen/activity_vertical_margin”

就等于

android:paddingBottom="10dp"

通过setText方法显示外部数据。

1、获取要显示数据的TextView组件

TextView tv = (TextView)findViewById(Ridxxxx);//根据id获取TextView组件

2、通过setText方法显示数据

tvsetText("要显示的数据内容");//设置字符串显示

沉浸式通知栏Android44以上才支持的新特性。43不支持。

具体实现方式如下:

1新建个公共style,设置android:fitsSystemWindows=true

<!-- 设置应用布局时是否考虑系统窗口布局;true --> <style name="AppBaseTheme" parent="android:ThemeLightNoTitleBar"> <item name="android:fitsSystemWindows">true</item> </style>

2 修改AndroidManifestxml,让所有的activity样式默认设置为AppBaseTheme(不同项目要灵活处理,笔者项目的activity样式都是统一的所以这样设置没问题,但是实际情况下不同的activity可能调用的样式不一样,需要读者自行按自己的项目来设置)

<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppBaseTheme" android:name="">

3新增沉浸式通知栏实现类,实现原理很简单。

1)判断当前系统版本是不是44以上,判断代码如下:

if (VERSIONSDK_INT >= VERSION_CODESKITKAT)

2)如果大于44则设置状态栏透明化,代码如下:

windowsetFlags(WindowManagerLayoutParamsFLAG_TRANSLUCENT_STATUS,WindowManagerLayoutParamsFLAG_TRANSLUCENT_STATUS);

3)获取activity的根rootView(DecorView),然后创建一个新的view stateBarView并把它添加到rootView(这里手动给它设置个ID,下次进来时先判断rootView是否已创建stateBarView,如果已创建则直接获取该View这样可以防止重复创建,导致内存泄露)

以下是具体代码实现:

import androidannotationSuppressLint;import androidappActivity;import androidcontentresResources;import androidgraphicsdrawableDrawable;import androidosBuild;import androidviewGravity;import androidviewView;import androidviewViewGroup;import androidviewWindow;import androidviewWindowManager;import androidwidgetFrameLayoutLayoutParams;/ 沉浸式通知栏公共类 @author hurrican /@SuppressLint({ "InlinedApi", "ResourceAsColor" })public class ImmersedNotificationBar { private Activity activity ; //设置沉浸式通知栏的ID(防止重复创建) private final static int IMMERSED_NOTIFICATION_BAR_ID = 12345678 ; private final static String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height" ; public ImmersedNotificationBar(Activity activity){ thisactivity = activity ; } //获取状态栏高度 private int getStatusBarHeight(Resources res){ int statusBarHeight = 0; int resourceId = resgetIdentifier(STATUS_BAR_HEIGHT_RES_NAME, "dimen", "android"); if (resourceId > 0) { statusBarHeight = resgetDimensionPixelSize(resourceId); } return statusBarHeight ; } //添加顶部状态栏 private View addStateBar(Activity activity,ViewGroup rootView,int statusBarHeight){ //创建新的View,并添加到rootView顶部) View statusBarView ; if(null!=rootViewfindViewById(IMMERSED_NOTIFICATION_BAR_ID)){ statusBarView = rootViewfindViewById(IMMERSED_NOTIFICATION_BAR_ID); }else{ statusBarView = new View(activity); rootViewaddView(statusBarView); } statusBarViewsetId(IMMERSED_NOTIFICATION_BAR_ID) ; LayoutParams params = new LayoutParams(LayoutParamsMATCH_PARENT,statusBarHeight); paramsgravity = GravityTOP; statusBarViewsetLayoutParams(params); statusBarViewsetVisibility(ViewVISIBLE); return statusBarView ; } / 设置状态栏颜色 @param ColorId / public void setStateBarColor(int ColorId){ if (BuildVERSIONSDK_INT >= BuildVERSION_CODESKITKAT) { Window window = activitygetWindow(); //activity的顶级布局 ViewGroup rootView = (ViewGroup) windowgetDecorView(); //透明化状态栏 windowsetFlags(WindowManagerLayoutParamsFLAG_TRANSLUCENT_STATUS, WindowManagerLayoutParamsFLAG_TRANSLUCENT_STATUS); Resources res = activitygetResources(); //获取状态栏目的高度 int statusBarHeight = getStatusBarHeight(res); View stateBarView = addStateBar(activity,rootView,statusBarHeight) ; stateBarViewsetBackgroundColor(ColorId) ; } } / 设置状态栏颜色 @param ColorId / public void setStateBarDrawable(Drawable drawable){ if (BuildVERSIONSDK_INT >= BuildVERSION_CODESKITKAT) { Window window = activitygetWindow(); //activity的顶级布局 ViewGroup rootView = (ViewGroup) windowgetDecorView(); //透明化状态栏 windowsetFlags(WindowManagerLayoutParamsFLAG_TRANSLUCENT_STATUS, WindowManagerLayoutParamsFLAG_TRANSLUCENT_STATUS); Resources res = activitygetResources(); //获取状态栏目的高度 int statusBarHeight = getStatusBarHeight(res); View stateBarView = addStateBar(activity,rootView,statusBarHeight) ; stateBarViewsetBackgroundDrawable(drawable) ; } }}

以上就是关于Android 在WebView中通过javascript获取网页源码,并在TextView或者在EditText中显示问题全部的内容,包括:Android 在WebView中通过javascript获取网页源码,并在TextView或者在EditText中显示问题、Android自定义字母导航栏、安卓怎么修改系统“DIALOG”风格等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/9344592.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-27
下一篇 2023-04-27

发表评论

登录后才能评论

评论列表(0条)

保存