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”风格等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)