这篇博客作为我写博客之旅的开篇之作,是希望以一个结构清晰的优质代码内容来开启。之前在进行Android开发的过程中,一直都是作为一个汲取者,取猎各位大神们的作品。让我一直觉得很好意思呀。同享一个平台,也希望自己能成为一个优质代码提供者呀。让彼此在开发过程中,都少走弯路,共同进步。废话说了这么多,自己都嫌麻烦了。直接上效果图:

实现此效果的关键 简单来说 就在于: 滚动ListView填入横向滚动HorizontalScrollView中 

当然,需要处理的细节还是很多。我会将完整代码以及Demo附上,方便大家查看,使用。

为了便于观看,我就先从MainActivity的代码,来讲起。当然,讲解就不多说了。主要是代码。代码注释部分 已经很多了,每一个细节也都进行了标注。绝对能让大家看得懂,看得明白。

1、MainActivity:

package com.example.administrator.timetabledemo;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;import com.example.administrator.timetabledemo.adapter.TimeTableAdapter;
import com.example.administrator.timetabledemo.view.TableListRecyclerView;import java.util.ArrayList;
import java.util.List;
/*** Created by YangHao on 2017/7/28 0028.*/
public class MainActivity extends AppCompatActivity {TableListRecyclerView tableListRecyclerView; //重写的SuperRecyclerViewTimeTableAdapter timeTableAdapter;private List<String> list;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();initData();}private void initView() {tableListRecyclerView = (TableListRecyclerView) findViewById(R.id.rv_data);}private void initData() {/*** 必须重写 LinearLayoutManager方法 、* 避免 ScrollView 与 RecyclerView 滑动冲突* 关闭 RecyclerView的 纵向 滚动事件 即可*/LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this){@Overridepublic boolean canScrollVertically() {return false;}};tableListRecyclerView.setLayoutManager(linearLayoutManager);tableListRecyclerView.setRefreshEnabled(false); //关闭 下拉刷新tableListRecyclerView.setLoadMoreEnabled(false);//关闭 上拉加载更多list = new ArrayList<>();timeTableAdapter = new TimeTableAdapter(this,list);tableListRecyclerView.setAdapter(timeTableAdapter);upDataList();}// 写入 时间格 数据内容private void upDataList() {/***  将 一天 24 小时 以 半小时为节点 拆分开*  从 -1 开始 因为 有一个抬头 数据 需要 多一行*/for (int i = -1; i < 48; i++) {StringBuffer hour = new StringBuffer(); // StringBuffer 效率 高于 String  在当前存放地址改变 数据内容if(i<20){hour.append("0"+i/2);}else {hour.append(i/2+"");}if(i%2 == 0){hour.append(":00");}else {hour.append(":30");}list.add(hour.toString());}timeTableAdapter.setEmptyTimeList();}
}

2.对应的Adapter:

package com.example.administrator.timetabledemo.adapter;import android.content.Context;
import android.view.View;
import android.widget.TextView;import com.example.administrator.timetabledemo.R;
import com.example.administrator.timetabledemo.utils.ConstantUtils;
import com.superrecycleview.superlibrary.adapter.BaseViewHolder;
import com.superrecycleview.superlibrary.adapter.SuperBaseAdapter;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** Created by YangHao on 2017/7/28 0025.*/public class TimeTableAdapter extends SuperBaseAdapter<String> {private final int HEAD_TYPE = 1;private final int TIME_TYPE = 2;private Context context;private List<String> timeTableList;private Map<Integer,List<Boolean>>integerListMap;   //存放当前 时间格 是否被选中的 Map集合public TimeTableAdapter(Context context) {super(context);}public TimeTableAdapter(Context context, List<String> data) {super(context, data);this.context = context;timeTableList = data;integerListMap = new HashMap<>();}/*** 处理数据 View填充内容* */@Overrideprotected void convert(BaseViewHolder holder, String item, final int position) {switch (getAdapterItemType(position)){case HEAD_TYPE:         //顶部的日期表TextView head1 = holder.getView(R.id.head1);TextView head2 = holder.getView(R.id.head2);TextView head3 = holder.getView(R.id.head3);TextView head4 = holder.getView(R.id.head4);TextView head5 = holder.getView(R.id.head5);TextView head6 = holder.getView(R.id.head6);TextView head7 = holder.getView(R.id.head7);TextView head21 = holder.getView(R.id.head21);TextView head22 = holder.getView(R.id.head22);TextView head23 = holder.getView(R.id.head23);TextView head24 = holder.getView(R.id.head24);TextView head25 = holder.getView(R.id.head25);TextView head26 = holder.getView(R.id.head26);TextView head27 = holder.getView(R.id.head27);// 放入数组中 统一管理 View 优化代码量(处理方式一样 放入更便捷)TextView[] viewDates = {head1,head2,head3,head4,head5,head6,head7};TextView[] viewWays = {head21,head22,head23,head24,head25,head26,head27};// 从 常量工具类中 获取 当前 日期时间 集合List<String> dates = ConstantUtils.getInstance().get7Date();List<String> ways = ConstantUtils.getInstance().get7Ways();for (int i = 0; i < dates.size(); i++) {viewDates[i].setText(dates.get(i));viewWays[i].setText(ways.get(i));}break;case TIME_TYPE:     // 单位时间表TextView time1 = holder.getView(R.id.time1);TextView time2 = holder.getView(R.id.time2);TextView time3 = holder.getView(R.id.time3);TextView time4 = holder.getView(R.id.time4);TextView time5 = holder.getView(R.id.time5);TextView time6 = holder.getView(R.id.time6);TextView time7 = holder.getView(R.id.time7);final TextView timeTexts[] = {time1,time2,time3,time4,time5,time6,time7};for (int i = 0; i < timeTexts.length; i++) {timeTexts[i].setText(item);}//填充 时间格 当前所处状态List<Boolean> booleanList = integerListMap.get(position);for (int i = 0; i < booleanList.size(); i++) {if(booleanList.get(i)){timeTexts[i].setBackgroundResource(R.drawable.text_view_frame);timeTexts[i].setTextColor(context.getResources().getColor(R.color.grass_green));}else {timeTexts[i].setTextColor(context.getResources().getColor(R.color.gray));timeTexts[i].setBackgroundResource(R.drawable.text_view_no_frame);}}/***  对时间格 点击状态的处理 同样 放在 数组中 统一管理(优化代码量)*  处理方式:先改变当前状态 之后改变 存放状态的 数据内容*  直接处理的优点: 减少页面整体的 重刷次数*/for (int i = 0; i < timeTexts.length; i++) {final int finalI = i;timeTexts[i].setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {boolean b = integerListMap.get(position).get(finalI);if(!b){ //被点击后 当前 是 未被选中的状态 即false时,变为选中状态timeTexts[finalI].setBackgroundResource(R.drawable.text_view_frame);timeTexts[finalI].setTextColor(context.getResources().getColor(R.color.grass_green));}else {timeTexts[finalI].setBackgroundResource(R.drawable.text_view_no_frame);timeTexts[finalI].setTextColor(context.getResources().getColor(R.color.gray));}integerListMap.get(position).set(finalI,!b);}});}break;}}/***  获取多布局对应的 布局样式*/@Overrideprotected int getItemViewLayoutId(int position, String item) {switch (getAdapterItemType(position)){case HEAD_TYPE:return R.layout.item_time_head;case TIME_TYPE:return R.layout.item_time_data;}return 0;}// 布局类型private int getAdapterItemType(int position){if(position == 0){return HEAD_TYPE;}else {return TIME_TYPE;}}/**写入数据 更新数据*/public void setEmptyTimeList(){for (int i = 0; i < timeTableList.size(); i++) {List<Boolean>list2 = new ArrayList<>();for (int j = 0; j < 7; j++) {list2.add(false);}integerListMap.put(i,list2);}}/** 返回所有的数据 即可以返回 处于选中状态的数据 */public Map<Integer,List<Boolean>> getAllListData(){return integerListMap;}
}

3.三个重写的View类: (1)HorizontalScrollView

package com.example.administrator.timetabledemo.view;import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.HorizontalScrollView;/*** Created by YangHao on 2017/7/28 0024.* 重写 横向滚动 (并未使用到)* 当 头部 日期 数据 与 时间格 拆分开 存入 不同的 HorizontalScrollView 是会被用到的*/public class SyncHorizontalScrollView extends HorizontalScrollView {private View mView;public SyncHorizontalScrollView(Context context) {super(context);}public SyncHorizontalScrollView(Context context, AttributeSet attrs) {super(context, attrs);}public SyncHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}protected void onScrollChanged(int l, int t, int oldl, int oldt) {super.onScrollChanged(l, t, oldl, oldt);if (mView != null) {mView.scrollTo(l, t);}}// 写入 同步滚动的 Viewpublic void setScrollView(View view) {mView = view;}
}

(2).重写SuperRecyclerView  重新 绘制高度 使得内容可以填满 ScrollView

package com.example.administrator.timetabledemo.view;import android.content.Context;
import android.util.AttributeSet;
import android.view.View;import com.superrecycleview.superlibrary.recycleview.SuperRecyclerView;/*** Created by YangHao on 2017/7/28 0025.* SuperRecyclerView  RecyclerView 的 二次封装*   处理更加方便: (下次抽空 可以 详细介绍一下 SuperRecyclerView的 使用 以及 源码 解析)*   简单介绍一下优点:*   1、 不需要在写 ViewHolder类;*   2、 集成了 上拉记载 下拉刷新;*   3、可以不需要在Adapter中处理头部数据  外边可以添加 头部内容 而且加几个都很方便*/public class TableListRecyclerView extends SuperRecyclerView {public TableListRecyclerView(Context context) {super(context);}public TableListRecyclerView(Context context, AttributeSet attrs) {super(context, attrs);}public TableListRecyclerView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}// 高度重新绘制 的 方法 高度最大化 避免 RecyclerView 展示不全@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int expandSpec = View.MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, View.MeasureSpec.AT_MOST);super.onMeasure(widthMeasureSpec, expandSpec);}}

(3).重写  ScrollView  可以实现ScrollView的上拉下拉 返回  弹框(此块内容 借鉴 来自  网友博客)

package com.example.administrator.timetabledemo.view;/*** Created by YangHao on 2017/7/28 0028.*/import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.TranslateAnimation;
import android.widget.ScrollView;/*** 有弹性的ScrollView* 实现下拉弹回和上拉弹回*/
public class ReboundScrollView extends ScrollView {private static final String TAG = "ElasticScrollView";//移动因子, 是一个百分比, 比如手指移动了100px, 那么View就只移动50px//目的是达到一个延迟的效果private static final float MOVE_FACTOR = 0.5f;//松开手指后, 界面回到正常位置需要的动画时间private static final int ANIM_TIME = 300;//ScrollView的子View, 也是ScrollView的唯一一个子Viewprivate View contentView;//手指按下时的Y值, 用于在移动时计算移动距离//如果按下时不能上拉和下拉, 会在手指移动时更新为当前手指的Y值private float startY;//用于记录正常的布局位置private Rect originalRect = new Rect();//手指按下时记录是否可以继续下拉private boolean canPullDown = false;//手指按下时记录是否可以继续上拉private boolean canPullUp = false;//在手指滑动的过程中记录是否移动了布局private boolean isMoved = false;public ReboundScrollView(Context context) {super(context);}public ReboundScrollView(Context context, AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onFinishInflate() {if (getChildCount() > 0) {contentView = getChildAt(0);}}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);if (contentView == null) return;//ScrollView中的唯一子控件的位置信息, 这个位置信息在整个控件的生命周期中保持不变originalRect.set(contentView.getLeft(), contentView.getTop(), contentView.getRight(), contentView.getBottom());}/*** 在触摸事件中, 处理上拉和下拉的逻辑*/@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {if (contentView == null) {return super.dispatchTouchEvent(ev);}int action = ev.getAction();switch (action) {case MotionEvent.ACTION_DOWN://判断是否可以上拉和下拉canPullDown = isCanPullDown();canPullUp = isCanPullUp();//记录按下时的Y值startY = ev.getY();break;case MotionEvent.ACTION_UP:if (!isMoved) break;  //如果没有移动布局, 则跳过执行// 开启动画TranslateAnimation anim = new TranslateAnimation(0, 0, contentView.getTop(),originalRect.top);anim.setDuration(ANIM_TIME);contentView.startAnimation(anim);// 设置回到正常的布局位置contentView.layout(originalRect.left, originalRect.top,originalRect.right, originalRect.bottom);//将标志位设回falsecanPullDown = false;canPullUp = false;isMoved = false;break;case MotionEvent.ACTION_MOVE://在移动的过程中, 既没有滚动到可以上拉的程度, 也没有滚动到可以下拉的程度if (!canPullDown && !canPullUp) {startY = ev.getY();canPullDown = isCanPullDown();canPullUp = isCanPullUp();break;}//计算手指移动的距离float nowY = ev.getY();int deltaY = (int) (nowY - startY);//是否应该移动布局boolean shouldMove =(canPullDown && deltaY > 0)    //可以下拉, 并且手指向下移动|| (canPullUp && deltaY < 0)    //可以上拉, 并且手指向上移动|| (canPullUp && canPullDown); //既可以上拉也可以下拉(这种情况出现在ScrollView包裹的控件比ScrollView还小)if (shouldMove) {//计算偏移量int offset = (int) (deltaY * MOVE_FACTOR);//随着手指的移动而移动布局contentView.layout(originalRect.left, originalRect.top + offset,originalRect.right, originalRect.bottom + offset);isMoved = true;  //记录移动了布局}break;default:break;}return super.dispatchTouchEvent(ev);}/*** 判断是否滚动到顶部*/private boolean isCanPullDown() {return getScrollY() == 0 ||contentView.getHeight() < getHeight() + getScrollY();}/*** 判断是否滚动到底部*/private boolean isCanPullUp() {return contentView.getHeight() <= getHeight() + getScrollY();}}


4、附上封装好的当前时间工具类

package com.example.administrator.timetabledemo.utils;import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;/*** Created by YangHao on 2017/7/28   0025.*  常量工具类*/public class ConstantUtils {private static ConstantUtils constantUtils;private ConstantUtils(){}public static ConstantUtils getInstance(){if(constantUtils == null){constantUtils = new ConstantUtils();}return constantUtils;}/*** 日期类*/private String mYear;private String mMonth;private String mDay;private String mWay;private Calendar calendar = Calendar.getInstance();public void setNowDate(){calendar.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));mYear = String.valueOf(calendar.get(Calendar.YEAR)); // 获取当前年份  mMonth = String.valueOf(calendar.get(Calendar.MONTH) + 1);// 获取当前月份  mDay = String.valueOf(calendar.get(Calendar.DAY_OF_MONTH));// 获取当前月份的日期号码  mWay = String.valueOf(calendar.get(Calendar.DAY_OF_WEEK));if("1".equals(mWay)){mWay ="星期天";}else if("2".equals(mWay)){mWay ="星期一";}else if("3".equals(mWay)){mWay ="星期二";}else if("4".equals(mWay)){mWay ="星期三";}else if("5".equals(mWay)){mWay ="星期四";}else if("6".equals(mWay)){mWay ="星期五";}else if("7".equals(mWay)){mWay ="星期六";}}/**获取当前周几*/public String getTodayWay(){calendar.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));String mWay = String.valueOf(calendar.get(Calendar.DAY_OF_WEEK));if("1".equals(mWay)){mWay ="星期天";}else if("2".equals(mWay)){mWay ="星期一";}else if("3".equals(mWay)){mWay ="星期二";}else if("4".equals(mWay)){mWay ="星期三";}else if("5".equals(mWay)){mWay ="星期四";}else if("6".equals(mWay)){mWay ="星期五";}else if("7".equals(mWay)){mWay ="星期六";}return mWay;}/**获取未来一周星期集合*/public List<String> get7Ways(){calendar.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));String todayWay = getTodayWay();String mWay = String.valueOf(calendar.get(Calendar.DAY_OF_WEEK));String []strings = {"星期天","星期一","星期二","星期三","星期四","星期五","星期六",};int t = -1;List<String> ways = new ArrayList<>();for (int i = 0; i < 7; i++) {if(todayWay.equals(strings[i])){t = i;int j = i;for (; t < j+7; t++) {ways.add(strings[t%7]);}}}return ways;}/** 返回 01-01 样式的 日期 */public String getMMdd(){SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM-dd");String date = simpleDateFormat.format(calendar.getTime());return date;}/*** 返回今天往后一星期的集合*/public List<String> get7Date() {List<String> dates = new ArrayList<String>();final Calendar c = Calendar.getInstance();c.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));SimpleDateFormat sim = new SimpleDateFormat("MM-dd");String date = sim.format(c.getTime());dates.add(date);for (int i = 0; i < 6; i++) {c.add(Calendar.DAY_OF_MONTH, 1);date = sim.format(c.getTime());dates.add(date);}return dates;}}
5、接下来就是很重要的布局样式了。 
(1)首先是MainActivity的:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:background="#f8faf6"tools:context=".MainActivity"><com.example.administrator.timetabledemo.view.ReboundScrollViewandroid:id="@+id/scroll_content"android:layout_width="match_parent"android:layout_height="match_parent"android:overScrollMode="never"android:scrollbars="none"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_alignParentTop="true"android:orientation="horizontal"><LinearLayoutandroid:id="@+id/lin_data_content"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="3"android:orientation="vertical"><com.example.administrator.timetabledemo.view.SyncHorizontalScrollViewandroid:id="@+id/data_horizontal"android:layout_width="match_parent"android:layout_height="match_parent"android:overScrollMode="never"android:scrollbars="none"><com.example.administrator.timetabledemo.view.TableListRecyclerViewandroid:id="@+id/rv_data"android:layout_width="match_parent"android:layout_height="match_parent"android:overScrollMode="never"/></com.example.administrator.timetabledemo.view.SyncHorizontalScrollView></LinearLayout></LinearLayout></com.example.administrator.timetabledemo.view.ReboundScrollView>
</LinearLayout>

(2)时间表头布局的

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="50dp"android:orientation="vertical"android:layout_marginTop="18dp"android:background="#f4f4f4"android:paddingTop="5dp"android:paddingBottom="5dp"><LinearLayoutandroid:id="@+id/lin_content"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:id="@+id/head1"android:layout_width="90dp"android:layout_height="20dp"android:layout_gravity="center"android:gravity="center"android:text="1"/><TextViewandroid:id="@+id/head2"android:layout_width="90dp"android:layout_height="20dp"android:layout_gravity="center"android:gravity="center"android:text="2" /><TextViewandroid:layout_width="90dp"android:layout_height="20dp"android:layout_gravity="center"android:gravity="center"android:id="@+id/head3"android:text="3"/><TextViewandroid:layout_width="90dp"android:layout_height="20dp"android:layout_gravity="center"android:gravity="center"android:id="@+id/head4"android:text="4"/><TextViewandroid:layout_width="90dp"android:layout_height="20dp"android:layout_gravity="center"android:gravity="center"android:id="@+id/head5"android:text="5"/><TextViewandroid:layout_width="90dp"android:layout_height="20dp"android:layout_gravity="center"android:gravity="center"android:id="@+id/head6"android:text="6"/><TextViewandroid:layout_width="90dp"android:layout_height="20dp"android:layout_gravity="center"android:gravity="center"android:id="@+id/head7"android:text="7"/></LinearLayout><LinearLayoutandroid:id="@+id/lin_content_way"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:id="@+id/head21"android:layout_width="90dp"android:layout_height="20dp"android:layout_gravity="center"android:gravity="center"android:text="1"/><TextViewandroid:id="@+id/head22"android:layout_width="90dp"android:layout_height="20dp"android:layout_gravity="center"android:gravity="center"android:text="2" /><TextViewandroid:layout_width="90dp"android:layout_height="20dp"android:layout_gravity="center"android:gravity="center"android:id="@+id/head23"android:text="3"/><TextViewandroid:layout_width="90dp"android:layout_height="20dp"android:layout_gravity="center"android:gravity="center"android:id="@+id/head24"android:text="4"/><TextViewandroid:layout_width="90dp"android:layout_height="20dp"android:layout_gravity="center"android:gravity="center"android:id="@+id/head25"android:text="5"/><TextViewandroid:layout_width="90dp"android:layout_height="20dp"android:layout_gravity="center"android:gravity="center"android:id="@+id/head26"android:text="6"/><TextViewandroid:layout_width="90dp"android:layout_height="20dp"android:layout_gravity="center"android:gravity="center"android:id="@+id/head27"android:text="7"/></LinearLayout></LinearLayout></LinearLayout>

(3)时间表 时间格内容的

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><LinearLayoutandroid:id="@+id/lin_content"android:layout_width="match_parent"android:layout_height="50dp"android:orientation="horizontal"><TextViewandroid:id="@+id/time1"android:layout_width="70dp"android:layout_height="30dp"android:layout_gravity="center"android:gravity="center"android:text="00:00"android:layout_margin="10dp"/><TextViewandroid:id="@+id/time2"android:layout_width="70dp"android:layout_height="30dp"android:layout_gravity="center"android:gravity="center"android:text="00:00"android:layout_margin="10dp"/><TextViewandroid:id="@+id/time3"android:layout_width="70dp"android:layout_height="30dp"android:layout_gravity="center"android:gravity="center"android:layout_margin="10dp"android:text="00:00"/><TextViewandroid:id="@+id/time4"android:layout_width="70dp"android:layout_height="30dp"android:layout_gravity="center"android:gravity="center"android:layout_margin="10dp"android:text="00:00"/><TextViewandroid:id="@+id/time5"android:layout_width="70dp"android:layout_height="30dp"android:layout_gravity="center"android:gravity="center"android:layout_margin="10dp"android:text="00:00"/><TextViewandroid:id="@+id/time6"android:layout_width="70dp"android:layout_height="30dp"android:layout_gravity="center"android:gravity="center"android:layout_margin="10dp"android:text="00:00"/><TextViewandroid:id="@+id/time7"android:layout_width="70dp"android:layout_height="30dp"android:layout_gravity="center"android:gravity="center"android:layout_margin="10dp"android:text="00:00"/><!--<View--><!--android:layout_width="1px"--><!--android:layout_height="30dp"--><!--android:background="#cccccc"/>--></LinearLayout>
</LinearLayout>

(4)然后需要的就是两个对应的drawable样式了。这个直接附 代码

1 、text_view_frame

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><!-- 实心 --><solid android:color="@android:color/white" /><!-- 边框 --><strokeandroid:width="0.5dp"android:color="@color/grass_green" /><!-- 圆角 --><corners android:radius="10dp" /><!-- 边距 --><paddingandroid:bottom="5dp"android:left="5dp"android:right="5dp"android:top="5dp" />
</shape>

2、text_view_no_frame

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"></selector>

这三种布局都是很简单的样式的,就不给大家附图了。

附言:其中用到了 SuperRecyclerView ,需要的jar包呢,大家直接在demo中就可以找到,当然 apk文件也附在其中。

最后附上demo下载链接(没有下载积分的哦):点击打开链接

祝各位码农大家生活娱乐,技能步步升。

将RecyclerView变为可以左右上下滑动的Excel时间表格相关推荐

  1. RecyclerView拖拽排序和滑动删除实现

    效果图 如何实现 那么是如何实现的呢?主要就要使用到ItemTouchHelper ,ItemTouchHelper 一个帮助开发人员处理拖拽和滑动删除的实现类,它能够让你非常容易实现侧滑删除.拖拽的 ...

  2. 深入理解 RecyclerView 的绘制流程和滑动原理,直面春招

    归纳分发布局的三个步骤: dispatchLayoutStep1():  表示进行预布局,适配器更新.动画运行.保存当前视图的信息等工作: dispatchLayoutStep2():  表示对最终状 ...

  3. 利用RecyclerView实现仿陌陌滑动浏览图片

    利用RecyclerView实现仿陌陌滑动浏览图片,效果如下 图片效果真是太差了..主要是看这个效果..没有什么好的gif制作软件. 下面是正题. 我们利用自定义LayoutManager来实现这种类 ...

  4. RPA—pyautogui+PIL+pandas识别全版本(2.0-3.0)滑动验证码,获取表格数据

    文章目录 引言 破解滑块验证码 最终运行效果 个人公众号:螺旋编程极客  >>期待您的关注 引言   最近公司有个新需求,大体流程是这样的,进入天津市市场主体信用信息公示系统,根据exce ...

  5. recyclerview探探_RecyclerView Item滑动特效 仿探探

    ReSwipeCard 本项目是在 CardSwipeLayout的基础上进行的修改,感谢原作者. 项目功能: - 解决滑动与点击事件冲突 - 增加硬件加速支持 - 滑动方向控制 - 滑出方向控制 - ...

  6. php中表头不跟着滑动,JS实现table表格固定表头且表头随横向滚动而滚动

    这篇文章主要介绍了JS实现table表格固定表头且表头可以随横向滚动而滚动,对js的朋友可以参考下本篇文章 先看一张效果图 思路: 1.头部用一个table并用一个p包裹着, 表格的具体内容用一个ta ...

  7. layui 鼠标移入变为小手_如何在 LayUI 数据表格的列元素上,鼠标悬浮,显示所有文字内容(修改源码)...

    文中使用的LayUI版本:layui-v2.5.5 问题描述: 最近参与开发了 问题分析: 要实现鼠标悬浮显示所有内容,一般采用的都是给对应元素上添加 title 属性,这样当鼠标悬浮在对应列的时候, ...

  8. RecyclerView横向滑动与ViewPager冲突问题

    问题出现场景: TabLayout + ViewPager + Fragment,Fragment中包含一个横向滑动的RecyclerView,出现了左右滑动RecyclerView时会与ViewPa ...

  9. Android RecyclerView(九)滑动监听综述

    Android RecyclerView(九)滑动监听 1 RecyclerView 的滑动监听 1.1 RecyclerView 设置滑动监听 mRecyclerView.setOnScrollLi ...

最新文章

  1. 一致性Hash算法(KetamaHash)的c#实现
  2. OSS- OSS brower 登陆失败
  3. 2300+ commits,80+ Contributors,阿里 PouchContainer 工程质量实践
  4. Qt Creator使用其他构建系统
  5. springboot+hbase 集成
  6. 如何通过像素点找到世界坐标_如何通过阅读来找到自己理论研究的“视域”?...
  7. javascript HTMLElement
  8. text-overflow:ellipsis的巧妙运用
  9. 分治法( Divide and Conquer)
  10. aic准则和bic准则_用户故事准则
  11. 程序员请万分珍重你的第一份工作,否则后悔了概不负责
  12. 账号、密码管理系统 python
  13. sql 修改时间正价 2天_“熬夜3天,修改17遍,我终于写出了1篇稿费2万的稿子”...
  14. GMK4045-ASEMI光伏逆变器二极管GMK4045
  15. Linux命令学习总结
  16. python实现一元线性回归预测电影票房收入
  17. 地图选择区域遮罩层自定义控件实现
  18. vue生命周期函数面试题
  19. Matlab如何提取偶数行,得到矩阵的偶数/奇数索引 – MATLAB
  20. 奋斗吧,程序员!——第二章 君因风送入青云,我被人驱向鸭群

热门文章

  1. 报名开启|和你约定在 Google 应用出海指南针
  2. java mediatype属性_基于ServletRequest实现请求获取内容类型的媒体类型MediaType、字符集Charset的工具类ContentTypeUtil...
  3. Linux产生序列seq命令
  4. 高精度② P1601 A+B Problem
  5. element的密码框实现睁眼闭眼效果
  6. system(“shutdown“)的用法
  7. oracle中映射表到timesten的方法
  8. 新!uniapp微信小程序微信授权登录
  9. Chapter2:描述数据:频数分布和图形表示
  10. c++ tuple的用法