安卓开发-高级组件

原视频链接

简要目录

1、复杂组件的使用

1、组件通用

1.1 控制组件显示状态

  • xml属性控制:
    安卓开发-高级组件
  • java属性控制:
			// View 为当前正在使用的控件
			View.setVisibility(View.GONE) 控件隐藏
            View.setVisibility(View.VISIBLE) 控件展示

1.2 设置触摸激活状态(只读)

  • java控制(setEnabled)
 View.setEnabled(false);

1.3 自定义样式

自定义样式: drawable文件创建xml
安卓开发-高级组件
在控件中引用即可

2、列表ListView的使用(上)

<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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activitys.ListViewTest">

    <ListView
        android:id="@+id/listView_lv_test"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

</LinearLayout>

2.1 属性

安卓开发-高级组件

2.2 事件

安卓开发-高级组件

2.3 适配器

2.3.1 ArrayAdapter(简单数组适配器)

安卓开发-高级组件

public class ListViewTest extends AppCompatActivity {

    private ListView mListViewLvTest;
    private List<String> list;
    private ArrayAdapter<String> arrayAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list_view_test);
        initView();
        setView();
    }

    private void setView() {
        mListViewLvTest.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Toast.makeText(getApplicationContext(),"点击"+list.get(i), Toast.LENGTH_LONG).show();
            }
        });
    }

    private void initView() {
        mListViewLvTest = (ListView) findViewById(R.id.listView_lv_test);
        list = new ArrayList<>();
        list.add("数据1");
        list.add("数据2");
        list.add("数据3");
        arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1, list);
        mListViewLvTest.setAdapter(arrayAdapter);
    }
}

2.3.2 BaseAdapter(自定义适配器)

2.3.2.1 准备自定义的View模版

安卓开发-高级组件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:padding="10dp"
    android:layout_height="match_parent">

    <!-- 这里的text不重要,只是一个提示作用-->
    <TextView
        android:id="@+id/adapter_listview_tv_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="15dp"
        android:text="name"/>
    
    <TextView
        android:id="@+id/adapter_listview_tv_age"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="15dp"
        android:text="age"/>

</LinearLayout>
2.3.2.2 准备数据的实体类
package com.example.study1.entity;

public class ListViewEntity {

    private String name;

    private Integer age;

    public ListViewEntity() {
    }

    public ListViewEntity(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "ListViewEntity{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

安卓开发-高级组件

2.3.2.3 准备实体的数据
		listViewEntities = new ArrayList<>();
        listViewEntities.add(new ListViewEntity("张三",14));
        listViewEntities.add(new ListViewEntity("李四",14));
        listViewEntities.add(new ListViewEntity("王五",14));
2.3.2.4 准备一个自定义的BaseAdapter的类
 private class ListViewAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return listViewEntities.size();
        }

        @Override
        public Object getItem(int i) {
            return listViewEntities.get(i);
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        // 渲染数据的方法
        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            ViewHolder vh = null;
            if(view == null){
                vh = new ViewHolder();
                // LayoutInflater.from(从哪个上下文) 获得LayoutInflater界面布局加载类
                // java获得一个静态界面的view对象采用的获得LayoutInflater.inflate(加载哪个界面的布局)
                view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.adapter_listview_test, null);
                vh.tvName = view.findViewById(R.id.adapter_listview_tv_name);
                vh.tvAge = view.findViewById(R.id.adapter_listview_tv_age);
                // 打包,存放到现在的界面当中
                view.setTag(vh);
            }else{
                vh = (ViewHolder) view.getTag();
            }
            // 处理数据
            vh.tvName.setText("名字:"+ listViewEntities.get(i).getName());
            vh.tvAge.setText("年龄:"+ listViewEntities.get(i).getAge());
            return view;
        }

        // 类似于DTO,方便抽出操作
        class ViewHolder{
            TextView tvName;
            TextView tvAge;
        }
    }
1.3.2.4 为原来的ListView设置自定义适配器
 private void initView() {
        mListViewLvTest = (ListView) findViewById(R.id.listView_lv_test);
        listViewEntities = new ArrayList<>();
        listViewEntities.add(new ListViewEntity("张三",14));
        listViewEntities.add(new ListViewEntity("李四",14));
        listViewEntities.add(new ListViewEntity("王五",14));
        listViewAdapter = new ListViewAdapter();
        mListViewLvTest.setAdapter(listViewAdapter);
    }

2、列表ListView的使用(下)

2.1 插件

安卓开发-高级组件
==2020.3 AS无法使用该插件 ==

3、优化跳转界面

3.1 普通的跳转方法

只要当前的界面继承了AppCompatActivity类,就会有startActivity()跳转方法

// new Intent(当前上下文的对象, 跳转到那里)
 startActivity(new Intent(getApplicationContext(), ImageViewTest.class));

3.2 优化跳转方法

public void onClick(View view) {
                        // 根据点击元素(布局拦)进行相应的跳转效果
                        //Intent intent = new Intent(getApplicationContext(), ImageViewTest.class);
                        //startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(
                        //        ListViewTest.this, new Pair[]{Pair.<View, String>create(holder.adapter_listview_layout, "set_Img")}
                        //).toBundle());
                        // 根据点击元素(图片)进行相应的跳转效果
                        Intent intent = new Intent(getApplicationContext(), ImageViewTest.class);
                        startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(
                                ListViewTest.this, new Pair[]{Pair.<View, String>create(holder.adapter_listview_iv_test, "set_Img")}
                        ).toBundle());
                    }

在跳转到的相应界面对相应元素进行绑定,设置跳转效果
安卓开发-高级组件

android:transitionName="set_Img"

3、横向列表HorizontalListView(自定义View)的使用

3.1 简单自定义View的理解

  • 通过java程序构成xml样式
  • 直接可以在xml中使用
  • 导出属性

  • 原文地址
import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.Scroller;

import java.util.LinkedList;
import java.util.Queue;

public class HorizontalListView extends AdapterView<ListAdapter> {

    float startX;
    float startY;
    public boolean mAlwaysOverrideTouch = true;
    protected ListAdapter mAdapter;
    private int mLeftViewIndex = -1;
    private int mRightViewIndex = 0;
    protected int mCurrentX;
    protected int mNextX;
    private int mMaxX = Integer.MAX_VALUE;
    private int mDisplayOffset = 0;
    protected Scroller mScroller;
    private GestureDetector mGesture;
    private Queue<View> mRemovedViewQueue = new LinkedList<View>();
    private OnItemSelectedListener mOnItemSelected;
    private OnItemClickListener mOnItemClicked;
    private OnItemLongClickListener mOnItemLongClicked;
    private boolean mDataChanged = false;


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

    private synchronized void initView() {
        mLeftViewIndex = -1;
        mRightViewIndex = 0;
        mDisplayOffset = 0;
        mCurrentX = 0;
        mNextX = 0;
        mMaxX = Integer.MAX_VALUE;
        mScroller = new Scroller(getContext());
        mGesture = new GestureDetector(getContext(), mOnGesture);
    }

    @Override
    public void setOnItemSelectedListener(OnItemSelectedListener listener) {
        mOnItemSelected = listener;
    }

    @Override
    public void setOnItemClickListener(OnItemClickListener listener) {
        mOnItemClicked = listener;
    }

    @Override
    public void setOnItemLongClickListener(OnItemLongClickListener listener) {
        mOnItemLongClicked = listener;
    }

    private DataSetObserver mDataObserver = new DataSetObserver() {

        @Override
        public void onChanged() {
            synchronized (HorizontalListView.this) {
                mDataChanged = true;
            }
            invalidate();
            requestLayout();
        }

        @Override
        public void onInvalidated() {
            reset();
            invalidate();
            requestLayout();
        }
    };

    @Override
    public ListAdapter getAdapter() {
        return mAdapter;
    }

    @Override
    public View getSelectedView() {
        return null;
    }

    @Override
    public void setAdapter(ListAdapter adapter) {
        if (mAdapter != null) {
            mAdapter.unregisterDataSetObserver(mDataObserver);
        }
        mAdapter = adapter;
        mAdapter.registerDataSetObserver(mDataObserver);
        reset();
    }

    private synchronized void reset() {
        initView();
        removeAllViewsInLayout();
        requestLayout();
    }

    @Override
    public void setSelection(int position) {
    }

    private void addAndMeasureChild(final View child, int viewPos) {
        LayoutParams params = child.getLayoutParams();
        if (params == null) {
            params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
        }

        addViewInLayout(child, viewPos, params, true);
        child.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),
                MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST));
    }

    @Override
    protected synchronized void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        if (mAdapter == null) {
            return;
        }

        if (mDataChanged) {
            int oldCurrentX = mCurrentX;
            initView();
            removeAllViewsInLayout();
            mNextX = oldCurrentX;
            mDataChanged = false;
        }

        if (mScroller.computeScrollOffset()) {
            int scrollx = mScroller.getCurrX();
            mNextX = scrollx;
        }

        if (mNextX <= 0) {
            mNextX = 0;
            mScroller.forceFinished(true);
        }
        if (mNextX >= mMaxX) {
            mNextX = mMaxX;
            mScroller.forceFinished(true);
        }

        int dx = mCurrentX - mNextX;

        removeNonVisibleItems(dx);
        fillList(dx);
        positionItems(dx);

        mCurrentX = mNextX;

        if (!mScroller.isFinished()) {
            post(new Runnable() {
                @Override
                public void run() {
                    requestLayout();
                }
            });
        }
    }

    private void fillList(final int dx) {
        int edge = 0;
        View child = getChildAt(getChildCount() - 1);
        if (child != null) {
            edge = child.getRight();
        }
        fillListRight(edge, dx);

        edge = 0;
        child = getChildAt(0);
        if (child != null) {
            edge = child.getLeft();
        }
        fillListLeft(edge, dx);
    }

    private void fillListRight(int rightEdge, final int dx) {
        while (rightEdge + dx < getWidth() && mRightViewIndex < mAdapter.getCount()) {

            View child = mAdapter.getView(mRightViewIndex, mRemovedViewQueue.poll(), this);
            addAndMeasureChild(child, -1);
            rightEdge += child.getMeasuredWidth();

            if (mRightViewIndex == mAdapter.getCount() - 1) {
                mMaxX = mCurrentX + rightEdge - getWidth();
            }

            if (mMaxX < 0) {
                mMaxX = 0;
            }
            mRightViewIndex++;
        }
    }

    private void fillListLeft(int leftEdge, final int dx) {
        while (leftEdge + dx > 0 && mLeftViewIndex >= 0) {
            View child = mAdapter.getView(mLeftViewIndex, mRemovedViewQueue.poll(), this);
            addAndMeasureChild(child, 0);
            leftEdge -= child.getMeasuredWidth();
            mLeftViewIndex--;
            mDisplayOffset -= child.getMeasuredWidth();
        }
    }

    private void removeNonVisibleItems(final int dx) {
        View child = getChildAt(0);
        while (child != null && child.getRight() + dx <= 0) {
            mDisplayOffset += child.getMeasuredWidth();
            mRemovedViewQueue.offer(child);
            removeViewInLayout(child);
            mLeftViewIndex++;
            child = getChildAt(0);

        }

        child = getChildAt(getChildCount() - 1);
        while (child != null && child.getLeft() + dx >= getWidth()) {
            mRemovedViewQueue.offer(child);
            removeViewInLayout(child);
            mRightViewIndex--;
            child = getChildAt(getChildCount() - 1);
        }
    }

    private void positionItems(final int dx) {
        if (getChildCount() > 0) {
            mDisplayOffset += dx;
            int left = mDisplayOffset;
            for (int i = 0; i < getChildCount(); i++) {
                View child = getChildAt(i);
                int childWidth = child.getMeasuredWidth();
                child.layout(left, 0, left + childWidth, child.getMeasuredHeight());
                left += childWidth + child.getPaddingRight();
            }
        }
    }

    public synchronized void scrollTo(int x) {
        mScroller.startScroll(mNextX, 0, x - mNextX, 0);
        requestLayout();
    }


    /**
     * 上下滑动需要拦截,
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        boolean handled = super.dispatchTouchEvent(ev);
        handled |= mGesture.onTouchEvent(ev);
        getParent().requestDisallowInterceptTouchEvent(true);

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                startX = (int) ev.getX();
                startY = (int) ev.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                int endX = (int) ev.getX();
                int endY = (int) ev.getY();

                int dx = (int) (endX - startX);
                int dy = (int) (endY - startY);

                if (Math.abs(dx) + 50 > Math.abs(dy)) {

                } else {
                    // 上下滑动,需要拦截
                    getParent().requestDisallowInterceptTouchEvent(false);
                }
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return handled | super.dispatchTouchEvent(ev);
    }

    protected boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                              float velocityY) {
        synchronized (HorizontalListView.this) {
            mScroller.fling(mNextX, 0, (int) -velocityX, 0, 0, mMaxX, 0, 0);
        }
        requestLayout();
        return true;
    }

    protected boolean onDown(MotionEvent e) {
        mScroller.forceFinished(true);
        return true;
    }

    private OnGestureListener mOnGesture = new GestureDetector.SimpleOnGestureListener() {

        @Override
        public boolean onDown(MotionEvent e) {
            return HorizontalListView.this.onDown(e);
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                               float velocityY) {
            return HorizontalListView.this.onFling(e1, e2, velocityX, velocityY);
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                float distanceX, float distanceY) {

            synchronized (HorizontalListView.this) {
                mNextX += (int) distanceX;
            }
            requestLayout();
            return true;
        }

        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            for (int i = 0; i < getChildCount(); i++) {
                View child = getChildAt(i);
                if (isEventWithinView(e, child)) {
                    if (mOnItemClicked != null) {
                        mOnItemClicked.onItemClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i));
                    }
                    if (mOnItemSelected != null) {
                        mOnItemSelected.onItemSelected(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i));
                    }
                    break;
                }
            }
            return true;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            int childCount = getChildCount();
            for (int i = 0; i < childCount; i++) {
                View child = getChildAt(i);
                if (isEventWithinView(e, child)) {
                    if (mOnItemLongClicked != null) {
                        mOnItemLongClicked.onItemLongClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i));
                    }
                    break;
                }

            }
        }

        private boolean isEventWithinView(MotionEvent e, View child) {
            Rect viewRect = new Rect();
            int[] childPosition = new int[2];
            child.getLocationOnScreen(childPosition);
            int left = childPosition[0];
            int right = left + child.getWidth();
            int top = childPosition[1];
            int bottom = top + child.getHeight();
            viewRect.set(left, top, right, bottom);
            return viewRect.contains((int) e.getRawX(), (int) e.getRawY());
        }
    };

    //解决滑动和点击冲突问题
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                startX = ev.getX();
                startY = ev.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                float endX = ev.getX();
                float endY = ev.getY();

                float dx = endX - startX;
                float dy = endY - startY;

                if (Math.abs(dx) - 10 > Math.abs(dy)) {
                    return true;
                } else if (Math.abs(dx) < Math.abs(dy) - 10) {
                    return true;
                }
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }
}

在xml文件中使用

    <com.example.study1.customView.HorizontalListView
        android:id="@+id/horizontal_hr_test"
        android:layout_width="match_parent"
        android:layout_height="100dp">
    </com.example.study1.customView.HorizontalListView>

java设置自定义适配器

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.example.study1.R;
import com.example.study1.customView.HorizontalListView;

import java.util.ArrayList;
import java.util.List;

public class HorizontalListViewTest extends AppCompatActivity {

    private HorizontalListView mHorizontalHrTest;
    private List<String> names;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_horizontal_list_view_test);
        initView();
        names = new ArrayList<>();
        names.add("张三");
        names.add("李四");
        names.add("王五");
        names.add("张三");
        names.add("李四");
        names.add("王五");
        names.add("张三");
        names.add("李四");
        names.add("王五");
        names.add("张三");
        names.add("李四");
        names.add("王五");
        AdapterHlistviewTestAdapter adapterHlistviewTestAdapter = new AdapterHlistviewTestAdapter(names, getApplicationContext());
        mHorizontalHrTest.setAdapter(adapterHlistviewTestAdapter);

    }

    private void initView() {
        mHorizontalHrTest = (HorizontalListView) findViewById(R.id.horizontal_hr_test);
    }

    public class AdapterHlistviewTestAdapter extends BaseAdapter {
        List<String> listBeans;
        Context context;

        public  AdapterHlistviewTestAdapter (List<String> listBeans, Context context){
            this.listBeans = listBeans;
            this.context = context;
        }

        @Override
        public int getCount() {
            return listBeans.size();
        }

        @Override
        public String getItem(int position) {
            return listBeans.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = LayoutInflater.from(context).inflate(R.layout.adapter_hlistview_test, null);
                convertView.setTag(new ViewHolder(convertView));
            }
            initializeViews((String)getItem(position), (ViewHolder) convertView.getTag());
            return convertView;
        }

        private void initializeViews(final String object, final ViewHolder holder) {
            //TODO implement
            try {
                //此处编写你的逻辑代码
                holder.adapterHlistViewTvTest.setText(object);
            }catch (Exception e){
            }
        }

        protected class ViewHolder {
            private ImageView adapterHlistViewIvTest;
            private TextView adapterHlistViewTvTest;

            public ViewHolder(View view) {
                adapterHlistViewIvTest = (ImageView) view.findViewById(R.id.adapter_hlist_view_iv_test);
                adapterHlistViewTvTest = (TextView) view.findViewById(R.id.adapter_hlist_view_tv_test);
            }
        }
    }
}

4、网格列表GridView的使用

4.1 属性

安卓开发-高级组件

4.2 关联BaseAdapter适配器

4.3 事件

  • setOnItemClickListener: 点击事件
 <!--
    numColumn: 列数
    verticalSpacing: 垂直空格

    -->
    <GridView
        android:numColumns="3"
        android:id="@+id/grid_view_test"
        android:verticalSpacing="10dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </GridView>

绑定 相应的适配器/设置相应的事件即可

public class GridViewTest extends AppCompatActivity {


    private GridView mGridViewTest;
    private List<String> names;
    private AdapterHlistviewTestAdapter listViewTestAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_grid_view_test);
        initView();
        setView();
    }

    private void setView() {
    }

    private void initView() {
        mGridViewTest = (GridView) findViewById(R.id.grid_view_test);
        names = new ArrayList<>();
        names.add("张三");
        names.add("张三");
        names.add("张三");
        names.add("张三");
        names.add("张三");
        names.add("张三");
        names.add("张三");
        names.add("张三");
        names.add("张三");
        listViewTestAdapter = new AdapterHlistviewTestAdapter(names, getApplication());
        mGridViewTest.setAdapter(listViewTestAdapter);

    }

    public class AdapterHlistviewTestAdapter extends BaseAdapter {
        List<String> listBeans;
        Context context;

        public  AdapterHlistviewTestAdapter ( List<String> listBeans, Context context){
            this.listBeans = listBeans;
            this.context = context;
        }

        @Override
        public int getCount() {
            return listBeans.size();
        }

        @Override
        public String getItem(int position) {
            return listBeans.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = LayoutInflater.from(context).inflate(R.layout.adapter_hlistview_test, null);
                convertView.setTag(new ViewHolder(convertView));
            }
            initializeViews((String)getItem(position), (ViewHolder) convertView.getTag());
            return convertView;
        }

        private void initializeViews(final String object, final ViewHolder holder) {
            //TODO implement
            try {
                //此处编写你的逻辑代码
                holder.adapterHlistViewTvTest.setText(object);
            }catch (Exception e){
            }
        }

        protected class ViewHolder {
            private TextView adapterHlistViewTvTest;

            public ViewHolder(View view) {
                adapterHlistViewTvTest = (TextView) view.findViewById(R.id.adapter_hlist_view_tv_test);
            }
        }
    }

}

5、静态进度条xxxBar的使用

5.1 SeekBar: 拖动条

5.1.1 属性

安卓开发-高级组件

<!--
        拖动条
        max: 最大值
        progress: 当前值
        secondaryProgress: 缓存条
     -->
    <SeekBar
        android:id="@+id/bar_seek_test"
        android:layout_width="match_parent"
        android:max="100"
        android:progress="10"
        android:layout_height="wrap_content"
        android:secondaryProgress="20"/>

5.1.2 事件

安卓开发-高级组件

 private SeekBar mBarSeekTest;
    private String logTag = "logStatus";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_seek_progress_rating_bar);
        initView();
        setView();
    }

    private void setView() {
        // 监听事件
        mBarSeekTest.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            // 进度条改变事件
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                Log.d(logTag, "seekBar发生改变了");
            }
            // 开始触碰
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                Log.d(logTag, "seekBar触碰了");
            }
            // 停止触碰
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                Log.d(logTag, "seekBar停止触碰了");
            }
        });
    }

    private void initView() {
        mBarSeekTest = (SeekBar) findViewById(R.id.bar_seek_test);
    }

5.2 ProgressBar: 加载条

5.2.1 属性

安卓开发-高级组件

<ProgressBar
        android:id="@+id/bar_pro_test"
        android:max="100"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

5.2.2 方法

安卓开发-高级组件

public class SeekProgressRatingBar extends AppCompatActivity implements View.OnClickListener {

    private SeekBar mBarSeekTest;
    private String logTag = "logStatus";
    private ProgressBar mBarProTest;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_seek_progress_rating_bar);
        initView();
        setView();
    }

    private void setView() {
        // 监听事件
        mBarSeekTest.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            // 进度条改变事件
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                Log.d(logTag, "seekBar发生改变了");
                // View.setVisibility(View.GONE) 控件隐藏
                // View.setVisibility(View.VISIBLE) 控件展示
                if(seekBar.getProgress() == 100){
                    mBarProTest.setVisibility(View.GONE);
                }else{
                    mBarProTest.setVisibility(View.VISIBLE);
                }
            }

            // 开始触碰
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                Log.d(logTag, "seekBar触碰了");
            }

            // 停止触碰
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                Log.d(logTag, "seekBar停止触碰了");
            }
        });
    }

    private void initView() {
        mBarSeekTest = (SeekBar) findViewById(R.id.bar_seek_test);
        mBarProTest = (ProgressBar) findViewById(R.id.bar_pro_test);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            default:
                break;
        }
    }
}

5.3 RatingBar: 评价条

5.2.1 属性

安卓开发-高级组件

   <RatingBar
        android:numStars="5"
        android:rating="3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:secondaryProgress="20" />

5.2.2 方法

安卓开发-高级组件

mBarRatingTest.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
            @Override
            public void onRatingChanged(RatingBar ratingBar, float v, boolean b) {
                Log.d(logTag, ""+ratingBar.getProgress());
                Toast.makeText(getApplicationContext(), "当前评价"+ratingBar.getProgress(), Toast.LENGTH_SHORT).show();
            }
        });

5、动态进度条xxxBar的使用

5.1 多种线程方法实现

安卓开发-高级组件

5.2 Handler+Thread: 线程(定时器/监听器)

  • 创建线程类
		// 动态线程进度条
        Thread thread = new Thread(){
            @Override
            public void run() {
                while (true){
                    try {
                        sleep(1000);
                        // 逻辑代码

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        thread.start();

5.2.1 通过Handler主线程ui机制

子线程使用Handler对主线程中的UI组件进行修改

  • 解析

通过Message传递消息,然后Handler接受消息并修改组件

  • 发送消息模版
    Handle
 Handler handler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what){
                case MESSAGE_TEST1:
                    // 传入接受的是test1的消息,并修改主线程的UI
                    mBarSeekTest.setProgress(progress);
                    mBarTvTest.setText(progress+"%");
                    break;
            }
        }
    };

Thread

			// 通过handle与主线程UI进行通信
             Message message = new Message();
             message.what = MESSAGE_TEST1;
             handler.sendMessage(message);

注意
在线程中每次开始都要重新new一下Message对象

6、网页显示WebView的使用(类似于iframe)

6.1 权限

开启网络权限
安卓开发-高级组件

6.2 应用领域

  • app显示网页
  • 简单浏览器
  • 前端app

6.3 方法

6.3.1 配置

安卓开发-高级组件

6.3.1 使用

安卓开发-高级组件

<WebView
        android:id="@+id/web_view_test"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

实例1(通过url获得webView)

public class WebViewTest extends AppCompatActivity {

    private WebView mWebViewTest;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web_view_test);
        initView();
        setView();
    }

    private void initWebView(){
        // 设置可操作
        mWebViewTest.setWebViewClient(new WebViewClient());
        // 获得浏览器设置
        WebSettings webSettings = mWebViewTest.getSettings();
        // 将图片设置为相应大小
        webSettings.setUseWideViewPort(true);
    }

    private void setView() {
        mWebViewTest.loadUrl("https://www.58pic.com/?tid=1100857&utm_source=baidu&utm_medium=cpc&utm_campaign=%C9%E8%BC%C6-%BE%AB%C8%B7&utm_content=%CB%D8%B2%C4-%CD%A8%D3%C31&utm_term=%CD%BC%C6%AC&sdclkid=Asjpb5-pALoz15-N&renqun_youhua=2216851&bd_vid=7270136719499164176");
        // 初始化WebView
        initWebView();
    }

    private void initView() {
        mWebViewTest = (WebView) findViewById(R.id.web_view_test);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if(keyCode == KeyEvent.KEYCODE_BACK){
            // 如果当前界面可以后退
            if(mWebViewTest.canGoBack()){
                mWebViewTest.goBack();
                return false;
            }
        }
        return super.onKeyDown(keyCode, event);
    }
}

实例2(通过html代码获得webView)

private void setView() {
//        mWebViewTest.loadUrl("https://www.58pic.com/?tid=1100857&utm_source=baidu&utm_medium=cpc&utm_campaign=%C9%E8%BC%C6-%BE%AB%C8%B7&utm_content=%CB%D8%B2%C4-%CD%A8%D3%C31&utm_term=%CD%BC%C6%AC&sdclkid=Asjpb5-pALoz15-N&renqun_youhua=2216851&bd_vid=7270136719499164176");
        String htmlData = "<h2>1111111</h2>";
        mWebViewTest.loadDataWithBaseURL("about:blank", htmlData,"text/html", "utf-8", null );
        // 初始化WebView
        initWebView();
    }

6.3.2 监听

安卓开发-高级组件
实例3(监听加载完成事件)

<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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".activitys.WebViewTest">

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <ProgressBar
            android:id="@+id/web_view_pro_bar"
            android:layout_width="match_parent"
            android:layout_height="500dp" />
        <TextView
            android:id="@+id/web_view_tv_test"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="60dp"
            android:gravity="center"
            android:layout_centerInParent="true"
            android:text="0%">

        </TextView>
    </RelativeLayout>

    <WebView
        android:id="@+id/web_view_test"
        android:visibility="gone"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>
public class WebViewTest extends AppCompatActivity {

    private WebView mWebViewTest;
    private ProgressBar mWebViewProBar;
    private TextView mWebViewTvTest;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web_view_test);
        initView();
        setView();
    }

    private void initWebView() {
        // 设置可操作
        mWebViewTest.setWebViewClient(new WebViewClient());
        // 获得浏览器设置
        WebSettings webSettings = mWebViewTest.getSettings();
        // 将图片设置为相应大小
        webSettings.setUseWideViewPort(true);
    }

    private void setView() {
        mWebViewTest.loadUrl("https://www.58pic.com/?tid=1100857&utm_source=baidu&utm_medium=cpc&utm_campaign=%C9%E8%BC%C6-%BE%AB%C8%B7&utm_content=%CB%D8%B2%C4-%CD%A8%D3%C31&utm_term=%CD%BC%C6%AC&sdclkid=Asjpb5-pALoz15-N&renqun_youhua=2216851&bd_vid=7270136719499164176");
        // 监听加载完成事件
        mWebViewTest.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                mWebViewProBar.setVisibility(View.GONE);
                mWebViewTvTest.setVisibility(View.GONE);
                mWebViewTest.setVisibility(View.VISIBLE);
            }
        });
        mWebViewTest.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                if(newProgress < 100){
                    mWebViewProBar.setProgress(newProgress);
                    mWebViewTvTest.setText(newProgress+"%");
                }else{
                    mWebViewProBar.setVisibility(View.GONE);
                    mWebViewTvTest.setVisibility(View.GONE);
                    mWebViewTest.setVisibility(View.VISIBLE);
                }
            }
        });
        // String htmlData = "<h2>1111111</h2>";
        // mWebViewTest.loadDataWithBaseURL("about:blank", htmlData,"text/html", "utf-8", null );
        // 初始化WebView
        // initWebView();
    }

    private void initView() {
        mWebViewTest = (WebView) findViewById(R.id.web_view_test);
        mWebViewProBar = (ProgressBar) findViewById(R.id.web_view_pro_bar);
        mWebViewTvTest = (TextView) findViewById(R.id.web_view_tv_test);
    }
	// 点击返回不退出程序
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            // 如果当前界面可以后退
            if (mWebViewTest.canGoBack()) {
                mWebViewTest.goBack();
                return false;
            }
        }
        return super.onKeyDown(keyCode, event);
    }
}

7、碎片界面Fragment的使用(类似于vue layout内部的界面)

7.1 简述

使用Fragment可以把屏幕分成几块,然后进行分组,进行一个模块化管理。Fragment不能够单独使用, 需要嵌套在Activity中使用,其生命周期也收到宿主Activity的生命周期影响

7.2 使用

7.2.1 步骤一: 准备一个碎片存放处(占位)

 <LinearLayout
        android:id="@+id/fm_layout_test"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    </LinearLayout>

7.2.2 步骤二: 准备一个Fregment碎片界面

安卓开发-高级组件

<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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    tools:context=".fragment.Fragment01">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="我是fragment01界面"/>

</LinearLayout>

安卓开发-高级组件

public class Fragment01 extends Fragment {

    private View view;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    // fragment组装xml
        view = inflater.inflate(R.layout.activity_fragment01,container, false);
        return view;
    }
}

7.2.2 步骤三: 替换占位

  • 方法一: 链式替换<=>分步骤
// 链式替换
 getSupportFragmentManager().beginTransaction().replace(R.id.fm_layout_test, new Fragment01()).commit();    
  • 方法二: 状态保持
    安卓开发-高级组件
    安卓开发-高级组件

8、轮播组件ViewPager的使用

8.1 使用范围

  • 图片查看器
  • 首页轮播图片
  • 首页多页面(fragment)

8.2 方法

  • setCurrentItem: 跳转页面(第二个参数为false: 没有动画)
  • setOffscreenPageLimit: 设置缓存界面个数
// 默认显示第一个
mViewPagerTest.setCurrentItem(1);

8.3 使用

8.3.1 准备数据

安卓开发-高级组件

 private void initView() {
        mViewPagerTest = (ViewPager) findViewById(R.id.view_pager_test);
        list = new ArrayList<>();
        list.add(LayoutInflater.from(getApplication()).inflate(R.layout.activity_button_test, null));
        list.add(LayoutInflater.from(getApplication()).inflate(R.layout.activity_button_test, null));
        list.add(LayoutInflater.from(getApplication()).inflate(R.layout.activity_button_test, null));
    }

8.3.2 设置适配器(PagerAdapter)

安卓开发-高级组件

private void setView() {
        mViewPagerTest.setAdapter(new PagerAdapter() {

            // 获得当前窗体的数量
            @Override
            public int getCount() {
                return list.size();
            }

            // 判断是否是由对象生成的界面
            @Override
            public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
                return view == object;
            }

            // 从ViewGroup中移除当前view
            @Override
            public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
                container.removeView(list.get(position));
            }

            // 返回对象, 这个对象表明了PageAdapter装载了哪个对象到当前的界面当中,也是适配器的装载过程
            @NonNull
            @Override
            public Object instantiateItem(@NonNull ViewGroup container, int position) {
                mViewPagerTest.addView(list.get(position));
                return list.get(position);
            }
        });
    }

9、轮播组件ViewPager+Fragment+TabLayout的使用

9.1 三方插件: TabLayout

使用介绍

implementation 'com.android.support:design:27.1.1'

9.2 ViewPage+Fragment

private void setView() {
        // FragmentStatePagerAdapter 有缓存的作用,不需要在初始化view等操作,系统内部自动处理
        mViewPagerTest.setAdapter(new FragmentStatePagerAdapter(getSupportFragmentManager()) {
            @NonNull
            @Override
            public Fragment getItem(int position) {
                return fragments.get(position);
            }

            @Override
            public int getCount() {
                return fragments.size();
            }
        });

    }

    private void initView() {
        mViewPagerTest = (ViewPager) findViewById(R.id.view_pager_test);
        fragments = new ArrayList<>();
        fragments.add(new Fragment01());
        fragments.add(new Fragment02());
    }

9.2 TabLayout+ ViewPage +Fragment

使用场景

  • 主页
  • 轮播图
  • 引导界面

9.2.1 xml引入TabLayout

<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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".activitys.ViewPageTest">

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/view_pager_tl_test"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/view_pager_test"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

9.2.2 java控制tab切换

public class ViewPageTest extends AppCompatActivity {

    private ViewPager mViewPagerTest;
    private List<Fragment> fragments;
    private List<String> titles;
    private TabLayout mViewPagerTlTest;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_page_test);
        initView();
        setView();
    }

    private void setView() {

        // FragmentStatePagerAdapter 有缓存的作用,不需要在初始化view等操作,系统内部自动处理-兼容以前那种方式实现的懒加载
        mViewPagerTest.setAdapter(new FragmentStatePagerAdapter(getSupportFragmentManager(), FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
            @NonNull
            @Override
            public Fragment getItem(int position) {
                return fragments.get(position);
            }

            @Override
            public int getCount() {
                return fragments.size();
            }

            @Nullable
            @Override
            public CharSequence getPageTitle(int position) {
                return titles.get(position);
            }
        });
        // 将tabLayout与viewPager做关联
        mViewPagerTlTest.setupWithViewPager(mViewPagerTest);
    }

    private void initView() {
        mViewPagerTest = (ViewPager) findViewById(R.id.view_pager_test);
        fragments = new ArrayList<>();
        fragments.add(new Fragment01());
        fragments.add(new Fragment02());
        mViewPagerTlTest = (TabLayout) findViewById(R.id.view_pager_tl_test);
        titles = new ArrayList<>();
        titles.add("第一个");
        titles.add("第二个");
    }
}

10、侧滑菜单栏 SlidingPaneLayout || DrawerLayout的使用

10.1 引入相应配置

	// SlidingPaneLayout
    implementation "androidx.slidingpanelayout:slidingpanelayout:1.1.0-beta01"

10.2 写入xml界面(写死内容区)

   <androidx.slidingpanelayout.widget.SlidingPaneLayout
        android:id="@+id/sl_layout_test"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:background="#287777"
            android:layout_gravity="start"
            android:layout_width="240dp"
            android:layout_height="match_parent">

        </LinearLayout>
        <LinearLayout
            android:layout_gravity="right"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:src="@mipmap/ic_launcher"/>
        </LinearLayout>

    </androidx.slidingpanelayout.widget.SlidingPaneLayout>

通过layout_gravity判断是内容区还是列表区
layout_gravity: start 列表区
layout_gravity: right 内容区

10.2 写入xml界面(使用fragment)

   <androidx.slidingpanelayout.widget.SlidingPaneLayout
        android:id="@+id/sl_layout_test"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:background="#287777"
            android:layout_gravity="start"
            android:layout_width="240dp"
            android:layout_height="match_parent">

        </LinearLayout>
        <LinearLayout
            android:layout_gravity="right"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        </LinearLayout>

    </androidx.slidingpanelayout.widget.SlidingPaneLayout>

通过layout_gravity判断是内容区还是列表区
layout_gravity: start 列表区
layout_gravity: right 内容区

10.3 属性

  • 属性
    • 设置透明颜色
      安卓开发-高级组件
    mSlLayoutTest.setSliderFadeColor(Color.TRANSPARENT);
    
    • 打开/关闭-api
      安卓开发-高级组件
    mSlLayoutTest.openPane();
    
    • 设置显示样式
    // 获得滑动的样式监听
        mSlLayoutTest.setPanelSlideListener(new SlidingPaneLayout.PanelSlideListener() {
            @Override
            public void onPanelSlide(@NonNull View panel, float slideOffset) {
                Log.d("SLDrawerLayout", slideOffset+"------");
                //覆盖样式
                //panel:移动的View,slideOffset:移动的值
                //覆盖界面
                leftView.setScaleX(0.8f + 0.2f * slideOffset);//0.8~1//设置X偏移
                leftView.setScaleY(0.8f + 0.2f * slideOffset);//0.8~1//设置y偏移
                leftView.setAlpha(0.8f + 0.2f * slideOffset);//0.8~1//设置透明度
                //主界面
                panel.setScaleX(1 - 0.2f * slideOffset);//1~0.8 //设置X偏移
                panel.setScaleY(1 - 0.2f * slideOffset);//1~0.8//设置y偏移
                panel.setAlpha(1 - 0.8f * slideOffset);//1~0.8//设置透明度
            }
    
            @Override
            public void onPanelOpened(@NonNull View panel) {
    
            }
    
            @Override
            public void onPanelClosed(@NonNull View panel) {
    
            }
        });
    

10.4 DrawrLayout

安卓开发-高级组件

10、下拉刷新SwipeRefreshLayout的使用

10.1 条件(类似于vue的template)

只能有一个根元素

10.2 使用

<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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activitys.SwipeRefreshLayoutTest">

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <LinearLayout
            android:gravity="center"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="刷新"/>
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="300dp"
                android:src="@mipmap/ic_launcher"/>
        </LinearLayout>
    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</LinearLayout>

10.3 方法属性

安卓开发-高级组件

private void setView() {
        // 设置不可滑动
        mSwipeRefreshTest.setEnabled(false);
        // 出现加载动画
        mSwipeRefreshTest.setRefreshing(true);
        // 设置刷新框的颜色
        mSwipeRefreshTest.setColorSchemeResources(R.color.myColor2,R.color.myColor);
        new Thread(){
            @Override
            public void run() {
                try {
                    sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 获取数据成功/失败
                mSwipeRefreshTest.setRefreshing(false);
            }
        }.start();
        // 监听下拉事件
        mSwipeRefreshTest.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                // 下拉触发
                // 请求接口获取下拉数据
                new Thread(){
                    @Override
                    public void run() {
                        try {
                            sleep(5000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        // 获取数据成功/失败
                        mSwipeRefreshTest.setRefreshing(false);
                    }
                }.start();
            }
        });
    }
上一篇:第七章:Servlet


下一篇:LeetCode-171 Excel 表列序号--进制转换