专栏首页Android、鸿蒙开发Android 天气APP(十八)常用城市

Android 天气APP(十八)常用城市

完成此篇文章实现的效果图如下:

前言

常用城市对于那些经常在外面出差的朋友来说相信是不陌生的,因为涉及到在不同城市之间居住,所以对于其他城市的天气是比较在意的,假如我要去一个城市的话,肯定要先了解天气怎么样,不然过去之后身体都受不了,何谈工作和生活呢,所以说我们需要在去之前做好准备工作,未雨绸缪,说实话这个功能是应该早就要有的,所以为了提高可用性,这里增加常用城市的功能。

正文

① 创建Activity

既然是一个新的功能当然是通过创建Activity来实现了,在app模块下的ui包下创建一个Empty Activity,命名为CommonlyUsedCityActivity

然后修改布局

这是布局中用到的图标

然后是颜色,

	<color name="shallow_gray">#F2F2F2</color><!--浅灰色-->
    <color name="dark_gray">#707070</color><!--深灰色-->
    <color name="shallow_black">#6D6D6D</color><!--褐黑色-->
    <color name="red">#FF0A00</color><!--红色-->
    <color name="line_gray">#E3E5E8</color><!--灰色分割线-->
    <color name="shallow_yellow">#E7C373</color><!--浅黄色-->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:fitsSystemWindows="true"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/shallow_gray"
    tools:context=".ui.CommonlyUsedCityActivity">

    <!--头部-->
    <androidx.appcompat.widget.Toolbar
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/white"
        android:elevation="@dimen/dp_2"
        app:contentInsetLeft="0dp"
        app:contentInsetStart="0dp"
        app:contentInsetStartWithNavigation="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navigationIcon="@mipmap/icon_return"
        app:popupTheme="@style/AppTheme.PopupOverlay">

        <!--输入框布局-->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_30"
            android:layout_marginRight="@dimen/dp_12"
            android:layout_weight="1"
            android:background="@drawable/shape_gray_bg_14"
            android:gravity="center_vertical"
            android:paddingLeft="@dimen/dp_12"
            android:paddingRight="@dimen/dp_12">
            <!--搜索图标-->
            <ImageView
                android:layout_width="@dimen/dp_16"
                android:layout_height="@dimen/dp_16"
                android:src="@mipmap/icon_search" />
            <!--输入框-->
            <EditText
                android:id="@+id/edit_query"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:background="@null"
                android:hint="添加城市"
                android:imeOptions="actionSearch"
                android:paddingLeft="@dimen/dp_8"
                android:paddingRight="@dimen/dp_4"
                android:singleLine="true"
                android:textColor="@color/black"
                android:textCursorDrawable="@drawable/cursor_style"
                android:textSize="@dimen/sp_14" />
            <!--清除输入的内容-->
            <ImageView
                android:id="@+id/iv_clear_search"
                android:layout_width="@dimen/dp_16"
                android:layout_height="@dimen/dp_16"
                android:src="@mipmap/icon_delete"
                android:visibility="gone" />
        </LinearLayout>
    </androidx.appcompat.widget.Toolbar>
    <!--没有数据时显示-->
    <LinearLayout
        android:visibility="gone"
        android:id="@+id/lay_normal"
        android:gravity="center"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <ImageView
            android:layout_width="@dimen/dp_160"
            android:layout_height="@dimen/dp_160"
            android:src="@mipmap/icon_normal"/>

        <TextView
            android:textSize="@dimen/sp_16"
            android:text="空空如也~"
            android:textColor="@color/dark_gray"
            android:layout_marginTop="@dimen/dp_12"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>

    <!--常用城市展示列表-->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_commonly_used"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="none" />

    <!--搜索城市展示列表-->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_search"
        android:visibility="gone"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="none" />
</LinearLayout>

可以看到这里布局和搜索城市的布局有些类似,但不一样,这里的搜索出来的结果不会产生搜索记录,当点击搜索出来的城市时,就去查询这个城市的天气,同时这个城市也会放入常用城市列表里面,这里可以用缓存来做处理,也可以通过数据库来处理。

② Android SQLite

相信很多从事Android开发的程序员都了解过SQLite,但是用过的人并不多,这是为什么呢?因为一旦数据量很多的情况下我们不会用SQLite,而是通过服务器的数据库返回数据,而数据量少的时候用缓存就可以解决问题,所以这也是SQLite尴尬的地方,这是我个人看法,不过这个SQLite还是很重要的,不然我还是会用缓存的,如果是使用原生的SQLite代码就会比较的繁琐,所以这里我们可以用第三方库来快速实现功能,这里使用郭霖大神的LitePal框架 首先是在mvplibrary下的build.gradle中添加依赖

	//Android SQLite操作框架
    api 'org.litepal.guolindev:core:3.1.1'
    //列表item侧滑删除
    api 'com.github.mcxtzhang:SwipeDelMenuLayout:V1.3.0'

应该是一目了然吧,记得Sync哦~ 然后配置litepal.xml,将项目预览模式切换为Project,然后打开mvplibrary,创建一个assets文件夹,再创建一个litepal.xml文件

文件中的代码如下

<?xml version="1.0" encoding="utf-8"?>
<litepal>
    <!--数据库名称-->
    <dbname value="GoodWeather" />
    <!--数据库版本-->
    <version value="1" />

    <!--数据列表-->
    <list>
    </list>
</litepal>

比较的简单 然后要在app下的WeatherApplication中进行初始化

现在你可以创建数据实体了,然后在mvplibrary下创建一个数据实体bean

代码如下:

package com.llw.mvplibrary.bean;

import org.litepal.crud.LitePalSupport;

public class ResidentCity extends LitePalSupport {

    private int id;//编号

    private String location;//地区/城市名称

    private String parent_city;//该地区/城市的上级城市

    private String admin_area;//该地区/城市所属行政区域

    private String cnty;//该地区/城市所属国家名称

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public String getParent_city() {
        return parent_city;
    }

    public void setParent_city(String parent_city) {
        this.parent_city = parent_city;
    }

    public String getAdmin_area() {
        return admin_area;
    }

    public void setAdmin_area(String admin_area) {
        this.admin_area = admin_area;
    }

    public String getCnty() {
        return cnty;
    }

    public void setCnty(String cnty) {
        this.cnty = cnty;
    }
}

然后在litepal.xml中增加一个mapping

最后在WeatherApplication中的onCreate方法中初始化,初始化的时候,你的数据库就创建好了,数据库名称是GoodWeather,表名是ResidentCity

那么这一块的内容就写完了,只需要在实际应用中结合业务逻辑使用就可以了,当然你也可以去自己尝试一下,感兴趣的可以看Android LitePal的简单使用这篇文章。

③ 布局item

通过最上面的效果图可以看到是两个列表,其中一个是已经添加的城市列表,另一个是搜索出来的城市列表,既然两个列表就要有两个item,当然你也可以用一个item来写,只不过用的时候要多写一些代码,首先当然是从布局开始着手了。

在app中res下的layout中创建两个布局文件 item_commonly_city_list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:orientation="vertical"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <!--支持侧滑的布局-->
    <com.mcxtzhang.swipemenulib.SwipeMenuLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_50"
        android:clickable="true"
        android:paddingBottom="1dp">
        <!--显示文本-->
        <TextView
            android:id="@+id/tv_city_name"
            android:gravity="center_vertical"
            android:paddingLeft="@dimen/dp_16"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:textColor="@color/shallow_black"
            android:background="?android:attr/selectableItemBackground"
            android:text="城市"/>

        <!-- 侧滑菜单的内容  现在里面只有一个按钮 -->
        <Button
            android:id="@+id/btn_delete"
            android:layout_width="@dimen/dp_100"
            android:layout_height="match_parent"
            android:background="@color/red"
            android:text="删除"
            android:textColor="@android:color/white"/>

    </com.mcxtzhang.swipemenulib.SwipeMenuLayout>
    <!--分隔线-->
    <View
        android:background="@color/line_gray"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_1"/>
</LinearLayout>

item_commonly_city_add_list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:id="@+id/item_add_city"
    android:background="?android:attr/selectableItemBackground"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <!--城市信息-->
    <TextView
        android:id="@+id/tv_location"
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:textSize="@dimen/sp_16"
        android:paddingLeft="@dimen/dp_16"
        android:layout_height="@dimen/dp_50"
        android:textColor="@color/shallow_black" />
    <!--分隔线-->
    <View
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_1"
        android:background="@color/line_gray" />
</LinearLayout>

④ 列表适配器

然后创建适配器

CommonlyCityAdapter.java

package com.llw.goodweather.adapter;

import androidx.annotation.Nullable;

import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.llw.goodweather.R;
import com.llw.mvplibrary.bean.ResidentCity;

import java.util.List;

/**
 * 常用城市列表适配器
 */
public class CommonlyCityAdapter extends BaseQuickAdapter<ResidentCity, BaseViewHolder> {
    public CommonlyCityAdapter(int layoutResId, @Nullable List<ResidentCity> data) {
        super(layoutResId, data);
    }

    @Override
    protected void convert(BaseViewHolder helper, ResidentCity item) {
        helper.setText(R.id.tv_city_name, item.getLocation());
        //添加点击事件
        helper.addOnClickListener(R.id.tv_city_name)
                .addOnClickListener(R.id.btn_delete);
    }
}

CommonlyCityAddAdapter.java

package com.llw.goodweather.adapter;

import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.widget.TextView;

import androidx.annotation.Nullable;

import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.llw.goodweather.R;
import com.llw.goodweather.bean.SearchCityResponse;

import java.util.List;

import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;

/**
 * 添加城市时搜索返回结果列表适配器
 */
public class CommonlyCityAddAdapter extends BaseQuickAdapter<SearchCityResponse.HeWeather6Bean.BasicBean, BaseViewHolder> {

    private String edStr;//关键字

    public CommonlyCityAddAdapter(int layoutResId, @Nullable List<SearchCityResponse.HeWeather6Bean.BasicBean> data) {
        super(layoutResId, data);
    }

    @Override
    protected void convert(BaseViewHolder helper, SearchCityResponse.HeWeather6Bean.BasicBean item) {
        TextView textView = helper.getView(R.id.tv_location);

        String result = item.getLocation() + " , " + item.getParent_city() + " , " + item.getAdmin_area() + " , " + item.getCnty();
        if (edStr != null && edStr.length() > 0) {
            textView.setText(matcherSearchText(mContext.getResources().getColor(R.color.shallow_yellow),result,edStr));

        } else {
            textView.setText(item.getLocation() + " , " +
                            item.getParent_city() + " , " +
                            item.getAdmin_area() + " , " +
                            item.getCnty());
        }

        helper.addOnClickListener(R.id.item_add_city);

    }

    /**
     * 改变颜色
     * @param str  输入的文本
     */
    public void changTxColor(String str) {
        edStr = str;
        notifyDataSetChanged();
    }


    /**
     * 改变一段文本中第一个关键字的文字颜色
     * @param color  要改变文字的颜色
     * @param string  文本字符串
     * @param keyWord  关键字
     * @return
     */
    public static CharSequence matcherSearchText(int color, String string, String keyWord) {
        SpannableStringBuilder builder = new SpannableStringBuilder(string);
        int indexOf = string.indexOf(keyWord);
        if (indexOf != -1) {
            builder.setSpan(new ForegroundColorSpan(color), indexOf, indexOf + keyWord.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        return builder;
    }
}

适配器的代码都是比较简单的,其中matcherSearchText方法是根据传入的关键字找到它在一段字符串中的第一次出现的位置,并修改字体颜色。

⑤ 代码整合

打开CommonlyUsedCityActivity.java

然后会出现五个构造方法,分别是

	//数据初始化
	@Override
    public void initData(Bundle savedInstanceState) {
    
    }
    
	@Override
    public int getLayoutId() {
        return R.layout.activity_commonly_used_city;
    }

    @Override
    protected SearchCityContract.SearchCityPresenter createPresent() {
        return new SearchCityContract.SearchCityPresenter();
    }
    
	/**
     * 请求数据返回处理
     * @param response
     */
	@Override
    public void getSearchCityResult(Response<SearchCityResponse> response) {
      
    }

	/**
     * 网络异常返回处理
     */
    @Override
    public void getDataFailed() {
        dismissLoadingDialog();//关闭弹窗
        ToastUtils.showShortToast(context, "网络异常");//这里的context是框架中封装好的,等同于this
    }

现在你可以把onCreate方法删掉了。

首先初始化控件

	@BindView(R.id.edit_query)
    EditText editQuery;//输入框
    @BindView(R.id.iv_clear_search)
    ImageView ivClearSearch;//清除输入框内容的图标
    @BindView(R.id.toolbar)
    Toolbar toolbar;//标题控件
    @BindView(R.id.rv_commonly_used)
    RecyclerView rvCommonlyUsed;//常用城市列表
    @BindView(R.id.rv_search)
    RecyclerView rvSearch;//搜索城市列表
    @BindView(R.id.lay_normal)
    LinearLayout layNormal;//常用城市为空时展示的布局

    CommonlyCityAdapter mAdapter;//常用城市列表适配器
    List<SearchCityResponse.HeWeather6Bean.BasicBean> mList = new ArrayList<>();//数据源
    CommonlyCityAddAdapter mAdapterAdd;//搜索城市列表适配器

    List<ResidentCity> cityList;//常用城市列表

根据常用城市数据来进行页面控件显示/隐藏

	/**
     * 根据常用城市数据来进行页面控件显示/隐藏
     */
    private void initHideOrShow() {
        ivClearSearch.setVisibility(View.GONE);//隐藏清除输入框内容的图标
        rvSearch.setVisibility(View.GONE);//隐藏搜索结果列表
        if (cityList != null && cityList.size() > 0) {//有数据
            rvCommonlyUsed.setVisibility(View.VISIBLE);//显示常用城市列表
            layNormal.setVisibility(View.GONE);//隐藏没有数据时的布局
        } else {//没数据
            rvCommonlyUsed.setVisibility(View.GONE);//隐藏常用城市列表
            layNormal.setVisibility(View.VISIBLE);//显示没有数据时的布局
        }
    }

初始化常用城市列表数据

这个方法主要是查询表中的所有数据,有数据就渲染出来,没有数据就更换为相应的表示布局,其中对item中的点击事件做了处理,分别item的点击和侧滑菜单的点击。

 	/**
     * 初始化常用城市列表数据
     */
    private void initCityList() {
        //查询ResidentCity表中所有数据
        cityList = LitePal.findAll(ResidentCity.class);

        if (cityList.size() > 0 && cityList != null) {
            mAdapter = new CommonlyCityAdapter(R.layout.item_commonly_city_list, cityList);
            rvCommonlyUsed.setLayoutManager(new LinearLayoutManager(context));
            rvCommonlyUsed.setAdapter(mAdapter);
            mAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
                @Override
                public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
                    switch (view.getId()) {
                        case R.id.tv_city_name:
                            SPUtils.putString(Constant.LOCATION, cityList.get(position).getLocation(), context);
                            //发送消息
                            EventBus.getDefault().post(new SearchCityEvent(cityList.get(position).getLocation(),
                                    cityList.get(position).getParent_city()));
                            finish();
                            break;
                        case R.id.btn_delete://删除
                            LitePal.delete(ResidentCity.class, cityList.get(position).getId());//删除指定id
                            initCityList();
                            //删除数据后判断一下显示和隐藏的控件
                            initHideOrShow();
                            break;
                    }

                }
            });

            mAdapter.notifyDataSetChanged();
        } else {
            rvCommonlyUsed.setVisibility(View.GONE);
            layNormal.setVisibility(View.VISIBLE);
        }


    }

添加城市列表item,点击保存数据并发送事件

/**
     * 添加城市列表item,点击保存数据并发送事件
     *
     * @param position
     */
    private void QueryWeather(int position) {
        ResidentCity residentCity = new ResidentCity();
        residentCity.setLocation(mList.get(position).getLocation());//地区/城市名称
        residentCity.setParent_city(mList.get(position).getParent_city());//该地区/城市的上级城市
        residentCity.setAdmin_area(mList.get(position).getAdmin_area());//该地区/城市所属行政区域
        residentCity.setCnty(mList.get(position).getCnty());//该地区/城市所属国家名称

        residentCity.save();//保存数据到数据库中
        if (residentCity.save()) {//保存成功
            //然后使用之前在搜索城市天气中写好的代码
            SPUtils.putString(Constant.LOCATION, mList.get(position).getLocation(), context);
            //发送消息
            EventBus.getDefault().post(new SearchCityEvent(mList.get(position).getLocation(),
                    mList.get(position).getParent_city()));
            finish();
        } else {//保存失败
            ToastUtils.showShortToast(context, "添加城市失败");
        }
    }

初始化搜索要添加的城市列表

	/**
     * 初始化搜索要添加的城市列表
     */
    private void initQueryAddList() {
        mAdapterAdd = new CommonlyCityAddAdapter(R.layout.item_commonly_city_add_list, mList);
        rvSearch.setLayoutManager(new LinearLayoutManager(context));
        rvSearch.setAdapter(mAdapterAdd);

        //点击item时保存到数据库中,同时传递数据到主页面查询出天气
        mAdapterAdd.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
            @Override
            public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
                QueryWeather(position);

            }
        });
    }

初始化搜索输入框 ,输入后马上查询数据,不需要额外点击,同时查询到数据之后隐藏默认城市列表

	/**
     * 初始化搜索输入框 ,输入后马上查询数据,不需要额外点击,同时查询到数据之后隐藏默认城市列表
     */
    private void initEdit() {
        editQuery.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                if (!s.toString().equals("")) {//输入后,显示清除按钮
                    ivClearSearch.setVisibility(View.VISIBLE);
                    mAdapterAdd.changTxColor(s.toString());
                    mPresent.searchCity(context, s.toString());//开始搜索
                } else {//隐藏和显示控件
                    initHideOrShow();

                }
            }
        });
    }

然后修改返回数据的方法

	/**
     * 请求数据返回处理
     * @param response
     */
    @Override
    public void getSearchCityResult(Response<SearchCityResponse> response) {
        dismissLoadingDialog();
        if (("ok").equals(response.body().getHeWeather6().get(0).getStatus())) {
            if (response.body().getHeWeather6().get(0).getBasic().size() > 0) {
                rvCommonlyUsed.setVisibility(View.GONE);//隐藏常用城市列表
                mList.clear();
                mList.addAll(response.body().getHeWeather6().get(0).getBasic());
                mAdapterAdd.notifyDataSetChanged();
                rvSearch.setVisibility(View.VISIBLE);//显示搜索城市列表
                layNormal.setVisibility(View.GONE);
            } else {
                ToastUtils.showShortToast(context, "很抱歉,未找到相应的城市");
            }

        } else {
            ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getHeWeather6().get(0).getStatus()));
        }
    }

再修改initData

	@Override
	public void initData(Bundle savedInstanceState) {
        StatusBarUtil.setStatusBarColor(context, R.color.white);//白色状态栏
        StatusBarUtil.StatusBarLightMode(context);//黑色字体
        Back(toolbar);

        initCityList();//初始化常用城市列表

        initQueryAddList();//初始化搜索城市列表

        initEdit();//初始化输入框
    }

OK,整合完毕,运行,效果图如下:

OK,写完收工。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Android MediaPlayer 音乐播放器扫描 本地音乐、上一曲、下一曲切歌、播放本地音乐

    项目请在真机(自己的手机)上测试运行,因为我不喜欢用虚拟机。 为了不浪费您的时间,先看一下运行的效果图, 一进去先进行音乐扫描,然后列表展示出来,点击即可播...

    晨曦_LLW
  • Android 自定义加载动画Dialog弹窗

    这是上面用到的 以shape_bg_5_blue.xml为例,其他的三个无非就是里面的颜色不一样而已

    晨曦_LLW
  • Android 音乐APP(二)启动白屏优化、定位当前播放歌曲

      Android应用冷启动时,又会短暂的黑屏或者白屏,然后才会进入主页面,黑屏是在Android版本低的时候才会出现,比如Android4.4、5.0。而现在...

    晨曦_LLW
  • 相对布局RelativeLayout(三)

    最新Android开发视频教程(共6章)Android Studio教程(2017-2018) 19 Android 相对布局的使用(视频+笔记,从01开始点...

    李小白是一只喵
  • Android 自定义ListView实现QQ空间界面(说说内包含图片、视频、点赞、评论、转发功能)

    前端时间刚好需要做一个类似于QQ空间的社区分享功能,说说内容包含文字(话题、内容)、视频、图片,还需包含点赞,评论,位置信息等功能。 就采用LIstview做了...

    砸漏
  • Android仿京东分类效果

    本文实例为大家分享了Android仿京东分类效果展示的具体代码,供大家参考,具体内容如下

    砸漏
  • Android-Service实现手机壁纸自动更换

    本文实例为大家分享了Android Service实现自动更换手机壁纸的具体代码,供大家参考,具体内容如下

    砸漏
  • Android实现美团下拉功能

    本文实例为大家分享了Android实现美团下拉功能的具体代码,供大家参考,具体内容如下

    砸漏
  • Android自定义带进度条WebView仿微信加载过程

    在正常开发中,我们客户端需要用webView加载网页,再遇到网络慢或者访问的服务器响应时,页面是空白的,所以为了用户更好的体验,我们可以提供一个正在加载的进度条...

    砸漏
  • android多媒体类VideoView使用方法详解

    VideoView类将视频的显示和控制集于一身,我们可以借助它完成一个简易的视频播放器。VideoView和MediaPlayer也比较相似。

    砸漏

扫码关注云+社区

领取腾讯云代金券