• Android控件


    一、图片轮播 com.youth.banner.Banner

    1、需要在libs文件夹下导入三个包:

    • banner-2.1.0.arr
    • glide-4.10.0.aar   // Android 上的图片加载和缓存库,其目的是实现平滑的图片列表滚动效果
    • gifdecoder-4.10.0.aar

    以上三个文件已经打包放在libs.zip中供大家下载,先解压缩保存到app/libs文件夹下,然后在app/build.gradle文件添加依赖:

    dependencies {
    
        implementation 'androidx.appcompat:appcompat:1.3.0'
        implementation 'com.google.android.material:material:1.4.0'
        implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
        implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'], exclude: [])
        testImplementation 'junit:junit:4.13.2'
        androidTestImplementation 'androidx.test.ext:junit:1.1.3'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    }

    或者使用中心仓库的依赖

    // glide
    implementation 'com.github.bumptech.glide:glide:4.10.0'
    
    //  banner
    implementation 'com.youth.banner:banner:2.1.0'

    2、创建布局文件activity_guide.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout 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:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".activity.GuideActivity">
    
        <com.youth.banner.Banner
            android:id="@+id/banGuide"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:banner_indicator_marginBottom="70dp"
            app:banner_indicator_normal_color="@color/white"
            app:banner_indicator_normal_width="10dp"
            app:banner_indicator_selected_color="@color/blue"
            app:banner_indicator_selected_width="10dp"
            app:banner_indicator_space="10dp" />
    
    </RelativeLayout>

    3、编辑GuideActivity.java文件

    使用两种图片来源:

    (1)使用本地drawable文件夹下的资源

    我们提前在res/drawable文件夹下保存了5张引导页图片

     

    package com.sdbi.smartcityli01.activity;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.view.Window;
    import android.view.WindowManager;
    import android.widget.Button;
    
    import com.bumptech.glide.Glide;
    import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
    import com.bumptech.glide.request.RequestOptions;
    import com.sdbi.smartcityli01.R;
    import com.youth.banner.Banner;
    import com.youth.banner.adapter.BannerImageAdapter;
    import com.youth.banner.holder.BannerImageHolder;
    import com.youth.banner.indicator.CircleIndicator;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class GuideActivity extends AppCompatActivity implements View.OnClickListener {
        private static final String TAG = "GuideActivity";
        private Banner banGuide;
    
        private int[] guideImages = {R.drawable.guide1, R.drawable.guide2, R.drawable.guide3, R.drawable.guide4, R.drawable.guide5};
        private List<Integer> imagesList;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_guide);
    
            initView();
    
            imagesList = new ArrayList<Integer>();
            for (int i = 0; i < guideImages.length; i++) {
                imagesList.add(guideImages[i]);
            }
            banGuide.setAdapter(new BannerImageAdapter<Integer>(imagesList) {
                @Override
                public void onBindView(BannerImageHolder bannerImageHolder, Integer integer, int i, int i1) {
                    Glide.with(GuideActivity.this)
                            .load(integer)
                            .into(bannerImageHolder.imageView);
                }
            }).addBannerLifecycleObserver(this).setIndicator(new CircleIndicator(this)).isAutoLoop(false);
        }
    
        private void initView() {
            banGuide = (Banner) findViewById(R.id.banGuide);
        }
    
        @Override
        public void onClick(View view) {
    
        }
    }

    (2)使用网络图片资源

    package com.sdbi.smartcityli01.activity;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.view.Window;
    import android.view.WindowManager;
    import android.widget.Button;
    
    import com.bumptech.glide.Glide;
    import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
    import com.bumptech.glide.request.RequestOptions;
    import com.sdbi.smartcityli01.R;
    import com.youth.banner.Banner;
    import com.youth.banner.adapter.BannerImageAdapter;
    import com.youth.banner.holder.BannerImageHolder;
    import com.youth.banner.indicator.CircleIndicator;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class GuideActivity extends AppCompatActivity implements View.OnClickListener {
        private static final String TAG = "GuideActivity";
        private Banner banGuide;
    
        private int[] guideImages = {R.drawable.guide1, R.drawable.guide2, R.drawable.guide3, R.drawable.guide4, R.drawable.guide5};
    
        private List<String> imgList = new ArrayList<>();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_guide);
    
            initView();
         // 从网上找了几张手机桌面测试 imgList.add(
    "https://c-ssl.dtstatic.com/uploads/item/202007/19/20200719145236_BTCck.thumb.1000_0.jpeg"); imgList.add("https://c-ssl.dtstatic.com/uploads/item/202004/13/20200413191327_wkirm.thumb.1000_0.jpeg"); imgList.add("https://c-ssl.dtstatic.com/uploads/item/202107/23/20210723202754_8UCda.thumb.1000_0.jpeg"); imgList.add("https://c-ssl.dtstatic.com/uploads/blog/202105/15/20210515104524_26bf1.thumb.1000_0.jpg"); imgList.add("https://c-ssl.dtstatic.com/uploads/blog/202205/11/20220511171657_fa181.thumb.1000_0.jpeg"); banGuide.setAdapter(new BannerImageAdapter<String>(imgList) { @Override public void onBindView(BannerImageHolder holder, String s, int i, int i1) { Log.d(TAG, "onBindView: s = " + s); Glide.with(GuideActivity.this) .load(s) .into(holder.imageView); } }).addBannerLifecycleObserver(this).setIndicator(new CircleIndicator(this)).isAutoLoop(false); } private void initView() { banGuide = (Banner) findViewById(R.id.banGuide); } @Override public void onClick(View view) { } }

    注意,在清单文件AndroidManifest.xml文件中添加网络访问权限

    <uses-permission android:name="android.permission.INTERNET" />

    4、设置全屏显式

    我们可以通过修改AndroidManifest.xml文件中应用程序的主题样式(android:theme属性)来实现全屏显示。

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        package="com.sdbi.smartcityli01">
    
        <uses-permission android:name="android.permission.INTERNET" />
    
        <application
            android:allowBackup="true"
            android:dataExtractionRules="@xml/data_extraction_rules"
            android:fullBackupContent="@xml/backup_rules"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/Theme.SmartCityLi01"
            tools:targetApi="31">
            <activity
                android:name=".activity.GuideActivity"
                android:exported="true">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity
                android:name=".MainActivity"
                android:exported="true"></activity>
        </application>
    
    </manifest>

    首先,我们先在themes.xml文件中增加自定义主题。

    <resources xmlns:tools="http://schemas.android.com/tools">
        <!-- Base application theme. -->
        <style name="Theme.SmartCityLi01" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
            <!-- Primary brand color. -->
            <item name="colorPrimary">@color/purple_500</item>
            <item name="colorPrimaryVariant">@color/purple_700</item>
            <item name="colorOnPrimary">@color/white</item>
            <!-- Secondary brand color. -->
            <item name="colorSecondary">@color/teal_200</item>
            <item name="colorSecondaryVariant">@color/teal_700</item>
            <item name="colorOnSecondary">@color/black</item>
            <!-- Status bar color. -->
            <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
            <!-- Customize your theme here. -->
        </style>
    
        <style name="MyTheme" parent="Theme.AppCompat.Light.NoActionBar">
            <!-- Customize your theme here. -->
            <item name="android:windowTranslucentStatus">true</item>
            <item name="colorPrimary">@color/blue</item>
            <item name="colorPrimaryDark">@color/blue</item>
            <item name="colorAccent">@color/blue</item>
        </style>
    </resources>

    其次,我们修改AndroidManifest.xml文件中<application>标签的android:theme属性值,引用我们自定义的主题样式

    android:theme="@style/MyTheme"

    运行,查看效果。

      

    5、轮播图滑动切换

    通过addOnPageChangeListener()方法给Banner添加滑动事件,滑动事件监听器要实现OnPageChangeListener接口,实现三个方法:

    • onPageScrolled()
    • onPageSelected()
    • onPageScrollStateChanged()
    (1)onPageScrolled(int position, float positionOffset, int positionOffsetPixels)

    当页面在滑动的时候会调用此方法,在滑动被停止之前,此方法回一直得到调用。其中三个参数的含义分别为:

    • position :当前页面,即你点击滑动的页面(从A滑B,则是A页面的position。官方说明:Position index of the first page currently being displayed. Page position+1 will be visible if positionOffset is nonzero.)
    • positionOffset:当前页面偏移的百分比
    • positionOffsetPixels:当前页面偏移的像素位置
    (2)onPageSelected(int position)

    此方法是页面跳转完后得到调用,position是你当前选中的页面的Position(位置编号)(从A滑动到B,就是B的position)。

    (3)onPageScrollStateChanged(int state)

    此方法是在状态改变的时候调用,其中state这个参数有三种状态:

    • SCROLL_STATE_DRAGGING(1)表示用户手指“按在屏幕上并且开始拖动”的状态(手指按下但是还没有拖动的时候还不是这个状态,只有按下并且手指开始拖动后log才打出。)
    • SCROLL_STATE_IDLE(0)滑动动画做完的状态。
    • SCROLL_STATE_SETTLING(2)在“手指离开屏幕”的状态。

    一个完整的滑动动作,三种状态的出发顺序为(1,2,0)。

    我们通过日志输出,观察一下这三个方法的调用情况。

    // 给Banner添加滑动事件
    banGuide.addOnPageChangeListener(new OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            // 当页面在滑动的时候会调用此方法,在滑动被停止之前,此方法回一直得到调用
            Log.d(TAG, "onPageScrolled: position = " + position + "; positionOffset = " + positionOffset + "; positionOffsetPixels = " + positionOffsetPixels);
        }
    
        @Override
        public void onPageSelected(int position) {
            // 此方法是页面跳转完后得到调用,position是你当前选中的页面的Position(位置编号)(从A滑动到B,就是B的position)
            Log.d(TAG, "onPageSelected: position = " + position);
        }
    
        @Override
        public void onPageScrollStateChanged(int state) {
            // 此方法是在状态改变的时候调用
            Log.d(TAG, "onPageScrollStateChanged: state = " + state);
        }
    });

    我们如果要在滑动到最后一页显示出两个Button,我们可以这样来修改代码:

    // 给Banner添加滑动事件
    banGuide.addOnPageChangeListener(new OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            // 当页面在滑动的时候会调用此方法,在滑动被停止之前,此方法回一直得到调用
        }
    
        @Override
        public void onPageSelected(int position) {
            // 此方法是页面跳转完后得到调用,position是你当前选中的页面的Position(位置编号)(从A滑动到B,就是B的position)
            Log.d(TAG, "onPageSelected: position = " + position);
            if (position == imgList.size() - 1) {
                btnEntry.setVisibility(View.VISIBLE);
                btnNet.setVisibility(View.VISIBLE);
            } else {
                btnEntry.setVisibility(View.INVISIBLE);
                btnNet.setVisibility(View.INVISIBLE);
            }
        }
    
        @Override
        public void onPageScrollStateChanged(int state) {
            // 此方法是在状态改变的时候调用
        }
    });

     

     6、Glide介绍

    Glide是Google主导的图片加载开源库。

    可以本地添加库文件,也可以通过添加在线依赖。

    implementation 'com.github.bumptech.glide:glide:4.14.2'

    (1)基本加载

    Glide.with(context)
        .load(url)
        .into(imageView);

    关键就是三步走:先with(),再load(),最后into()。

    首先,调用Glide.with()方法用于创建一个加载图片的实例。

    with()方法可以接收Context、Activity或者Fragment类型的参数。

    也就是说我们选择的范围非常广,不管是在Activity还是Fragment中调用with()方法,都可以直接传this。

    那如果调用的地方既不在Activity中也不在Fragment中呢?

    也没关系,我们可以获取当前应用程序的ApplicationContext,传入到with()方法当中。

    注意with()方法中传入的实例会决定Glide加载图片的生命周期,如果传入的是Activity或者Fragment的实例,那么当这个Activity或Fragment被销毁的时候,图片加载也会停止。

    如果传入的是ApplicationContext,那么只有当应用程序被杀掉的时候,图片加载才会停止。

    接下来,看一下load()方法,这个方法用于指定待加载的图片资源。

    Glide支持加载各种各样的图片资源,包括网络图片、本地图片、应用资源、二进制流、Uri对象等等。

    因此load()方法也有很多个方法重载,除了我们刚才使用的加载一个字符串网址之外,你还可以这样使用load()方法:

    // 加载本地图片
    File file = new File(getExternalCacheDir() + "/image.jpg");
    Glide.with(this).load(file).into(imageView);
    
    // 加载应用资源
    int resource = R.drawable.image;
    Glide.with(this).load(resource).into(imageView);
    
    // 加载二进制流
    byte[] image = getImageBytes();
    Glide.with(this).load(image).into(imageView);
    
    // 加载Uri对象
    Uri imageUri = getImageUri();
    Glide.with(this).load(imageUri).into(imageView);

    最后,看一下into()方法,这个方法就很简单了,我们希望让图片显示在哪个ImageView上,把这个ImageView的实例传进去就可以了。

    当然,into()方法不仅仅是只能接收ImageView类型的参数,还支持很多更丰富的用法。

    (2)设置加载中和加载失败的情况

    Glide.with(context)
        .load(url)
        .placeholder(R.drawable.loading) //占位图,加载中的图片,可放个gif
        .error(R.drawable.failed) //异常占位图,失败图片
        .into(imageView);

    占位图,就是指在图片的加载过程中,我们先显示一张临时的图片,等图片加载出来了再替换成要加载的图片。

    我们只是在刚才的三步走之间插入了一个placeholder()方法,然后将占位图片的资源id传入到这个方法中即可。

    另外,这个占位图的用法其实也演示了Glide当中绝大多数API的用法,其实就是在load()和into()方法之间串接任意想添加的功能就可以了。

    不过如果现在重新运行一下代码,很可能是根本看不到占位图效果的。

    因为Glide有非常强大的缓存机制,我们刚才加载那张图的时候Glide自动就已经将它缓存下来了,下次加载的时候将会直接从缓存中读取,不会再去网络下载了,因而加载的速度非常快,所以占位图可能根本来不及显示。

    因此这里我们还需要稍微做一点修改,来让占位图能有机会显示出来,修改代码如下所示:

    Glide.with(context)
         .load(url)
         .placeholder(R.drawable.loading)
         .diskCacheStrategy(DiskCacheStrategy.NONE)
         .into(imageView);

    这里串接了一个diskCacheStrategy()方法,并传入DiskCacheStrategy.NONE参数,这样就可以禁用掉Glide的缓存功能。

    异常占位图,就是加载失败时显示的图片。

    如果因为某些异常情况导致图片加载失败,比如说手机网络信号不好,这个时候就显示这张异常占位图。

    这里又串接了一个error()方法就可以指定异常占位图了。

    我们可以将图片的url地址修改成一个不存在的图片地址,或者干脆直接将手机的网络给关了,然后重新运行程序,就可以见到异常占位图了。

    (3)指定图片大小

    Glide.with(context)
        .load(url)
        .asGif() // 只能加载gif文件
        .into(imageView); 

    实际上,使用Glide在绝大多数情况下我们都是不需要指定图片大小的。

    在这里,我们还需要先了解一个概念,就是我们平时在加载图片的时候很容易会造成内存浪费。

    什么叫内存浪费呢?比如说一张图片的尺寸是1000*1000像素,但是我们界面上的ImageView可能只有200*200像素,这个时候如果你不对图片进行任何压缩就直接读取到内存中,这就属于内存浪费了,因为程序中根本就用不到这么高像素的图片。

    而使用Glide,我们就完全不用担心图片内存浪费,甚至是内存溢出的问题。

    因为Glide从来都不会直接将图片的完整尺寸全部加载到内存中,而是用多少加载多少。

    Glide会自动判断ImageView的大小,然后只将这么大的图片像素加载到内存当中,帮助我们节省内存开支。

    不过,如果我们必须给图片指定一个固定的大小,Glide仍然是支持这个功能的。

    修改Glide加载部分的代码,如下所示:

    Glide.with(context)
         .load(url)
         .override(100, 100)
         .into(imageView);

    这里使用override()方法指定了一个图片的尺寸,也就是说,Glide现在只会将图片加载成100*100像素的尺寸,而不会管ImageView的大小是多少了。

    (4)添加图片淡入加载的效果

    二、VideoView

    1、

  • 相关阅读:
    近期目标
    HDU
    BZOJ
    UVALive
    UVA
    HNOI2004 宠物收养所 (平衡二叉树)
    UVA
    HDU
    POJ
    康托展开与逆康托展开模板(O(n^2)/O(nlogn))
  • 原文地址:https://www.cnblogs.com/lihuawei/p/16638224.html
Copyright © 2020-2023  润新知