Commit 04a61060 by Any

目前最新的体育项目

parent 6e2a5eec
*.iml
.gradle
/local.properties
/.idea/caches/build_file_checksums.ser
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
.DS_Store
/build
/captures
.externalNativeBuild
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
<option name="TOP_LEVEL_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="INNER_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="METHOD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
</value>
</option>
<option name="FIELD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="IGNORE_DEPRECATED" value="false" />
<option name="IGNORE_JAVADOC_PERIOD" value="true" />
<option name="IGNORE_DUPLICATED_THROWS" value="false" />
<option name="IGNORE_POINT_TO_ITSELF" value="false" />
<option name="myAdditionalJavadocTags" value="date" />
</inspection_tool>
</profile>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeSettings">
<configurations>
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
</configurations>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>
\ No newline at end of file
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.jimind.sportdemo"
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.android.support:recyclerview-v7:28.0.0'
//网络请求相关
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
implementation 'io.reactivex.rxjava2:rxjava:2.1.12'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
//刷新,加载
implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.0.5.1'
//注解
implementation 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
//加载图片
implementation 'com.github.bumptech.glide:glide:4.8.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
//图表
implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3'
//水平分页
implementation 'com.gcssloop.recyclerview:pagerlayoutmanager:2.3.8'
//数据库
implementation files('libs/mysql-connector-java-5.1.47.jar')
//视频
implementation('de.mrmaffen:vlc-android-sdk:3.0.0') {
exclude module: 'support-v4'
}
//百度语音唤醒在线识别
implementation files('libs/bdasr_V3_20180801_d6f298a.jar')
}
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
package com.jimind.sportdemo;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.jimind.sportdemo", appContext.getPackageName());
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jimind.sportdemo">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<!--唤醒词 需要以下权限-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--动态授权-->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!--添加百度唤醒识别信息-->
<meta-data
android:name="com.baidu.speech.APP_ID"
android:value="15143091" />
<meta-data
android:name="com.baidu.speech.API_KEY"
android:value="RePcB6M3UR7VC6P8Gr2Omk8G" />
<meta-data
android:name="com.baidu.speech.SECRET_KEY"
android:value="zMxFHu7T4N0QGFPrSvP5qh0i1V69yzGb " />
<!--添加唤醒识别服务-->
<service
android:name="com.baidu.speech.VoiceRecognitionService"
android:exported="false" />
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".CourseDescActivity"
android:configChanges="orientation|screenSize|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
</intent-filter>
</activity>
<activity
android:name=".CoursePlayActivity"
android:configChanges="orientation|screenSize|keyboardHidden" />
<activity
android:name=".SignActivity"
android:configChanges="orientation|screenSize|keyboardHidden" />
<activity
android:name=".SummaryActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:screenOrientation="landscape" />
<activity
android:name=".StatisticsActivity"
android:configChanges="orientation|screenSize|keyboardHidden" />
<activity
android:name=".SettingActivity"
android:configChanges="orientation|screenSize|keyboardHidden" />
</application>
</manifest>
\ No newline at end of file
package com.jimind.sportdemo;
import android.content.Intent;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.jimind.sportdemo.api.ApiManager;
import com.jimind.sportdemo.base.BaseActivity;
import com.jimind.sportdemo.base.BaseObserver;
import com.jimind.sportdemo.base.ResponseResult;
import com.jimind.sportdemo.bean.Course;
import com.jimind.sportdemo.utils.AppManager;
import com.jimind.sportdemo.utils.CommonUtils;
import com.jimind.sportdemo.utils.Constant;
import com.jimind.sportdemo.utils.GlideApp;
import butterknife.BindView;
import butterknife.OnClick;
import io.reactivex.schedulers.Schedulers;
/**
* 课程详情
*
* @author Any
*/
public class CourseDescActivity extends BaseActivity {
@BindView(R.id.include_title)
FrameLayout flTitleBar;
@BindView(R.id.tv_bar_title)
TextView tvBarTitle;
@BindView(R.id.tv_course_name)
TextView tvCourseName;
@BindView(R.id.pb_star)
ProgressBar pbStar;
@BindView(R.id.tv_introduce)
TextView tvIntroduce;
@BindView(R.id.tv_grade_class)
TextView tvGradeClass;
@BindView(R.id.tv_number)
TextView tvNumber;
@BindView(R.id.iv_video)
ImageView ivVideo;
private Course mCourse;
private String mClassName;
private int mTotalNumber;
public static CourseDescActivity mActivity;
@Override
protected int getLayoutResource() {
return R.layout.activity_course_desc;
}
@Override
protected void initView() {
CommonUtils.initTitleBar(this, flTitleBar);
mActivity=this;
mTotalNumber = Integer.valueOf(tvNumber.getText().toString());
}
@Override
protected void initData() {
Intent intent = this.getIntent();
mClassName = intent.getStringExtra(Constant.CLASS_NAME);
mCourse= (Course)intent.getSerializableExtra(Constant.COURSE);
tvBarTitle.setText(mCourse.getCourseName());
tvCourseName.setText(mCourse.getCourseName());
pbStar.setProgress(mCourse.getDifficultyLevel() * CommonUtils.dip2px(this, 20));
tvGradeClass.setText(mCourse.getGradeName() + mClassName);
tvIntroduce.setText(mCourse.getCourseDescribe());
GlideApp
.with(this)
.load(Constant.LABEL+
MyApplication.getInstance().getHost()
+Constant.RESOURCE_PORT+mCourse.getCourseDescUrl())
.into(ivVideo);
}
@OnClick({R.id.ib_bar_back, R.id.bt_subtract, R.id.bt_plus, R.id.bt_start})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.ib_bar_back:
finish();
break;
case R.id.bt_subtract:
//减少
mTotalNumber = mTotalNumber - 5;
tvNumber.setText(String.valueOf(mTotalNumber));
break;
case R.id.bt_plus:
//增加
mTotalNumber = mTotalNumber + 5;
tvNumber.setText(String.valueOf(mTotalNumber));
break;
case R.id.bt_start:
sendToService();
Intent intent = new Intent(this, SignActivity.class);
intent.putExtra(Constant.CLASS_NAME,mClassName);
intent.putExtra(Constant.COURSE,mCourse);
intent.putExtra(Constant.TOTAL_NUMBER,mTotalNumber);
startActivity(intent);
break;
default:
}
}
/**
* 传给服务器
*/
private void sendToService() {
ApiManager.getInstance().requestService
.sendCommand(Constant.SIGN, "", "")
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(new BaseObserver<ResponseResult>() {
@Override
protected void onSuccess(ResponseResult responseResult) {
}
@Override
protected void onFailure(int code, String message) {
}
});
}
}
package com.jimind.sportdemo;
import android.app.Application;
import android.content.Context;
import android.support.annotation.NonNull;
import com.jimind.sportdemo.bean.Course;
import com.jimind.sportdemo.utils.DynamicTimeFormat;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.DefaultRefreshFooterCreator;
import com.scwang.smartrefresh.layout.api.DefaultRefreshHeaderCreator;
import com.scwang.smartrefresh.layout.api.RefreshFooter;
import com.scwang.smartrefresh.layout.api.RefreshHeader;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.footer.ClassicsFooter;
import com.scwang.smartrefresh.layout.header.ClassicsHeader;
/**
* Application
*
* @author Any
*/
public class MyApplication extends Application {
private String mTeacherName;
private Course mCourse;
private String mClassName;
private int mTotalNumber;
private String mHost;
private static MyApplication myApplication;
@Override
public void onCreate() {
super.onCreate();
myApplication = this;
}
public static MyApplication getInstance() {
return myApplication;
}
public String getTeacherName() {
return mTeacherName;
}
public void setTeacherName(String teacherName) {
this.mTeacherName = teacherName;
}
public String getHost() {
return mHost;
}
public void setHost(String host) {
this.mHost = host;
}
static {
//设置全局的Header构建器
SmartRefreshLayout.setDefaultRefreshHeaderCreator(new DefaultRefreshHeaderCreator() {
@NonNull
@Override
public RefreshHeader createRefreshHeader(@NonNull Context context, @NonNull RefreshLayout layout) {
//全局设置主题颜色
layout.setPrimaryColorsId(android.R.color.transparent, R.color.textColor);
return new ClassicsHeader(context).setTimeFormat(new DynamicTimeFormat("更新于 %s"));
}
});
//设置全局的Footer构建器
SmartRefreshLayout.setDefaultRefreshFooterCreator(new DefaultRefreshFooterCreator() {
@NonNull
@Override
public RefreshFooter createRefreshFooter(@NonNull Context context, @NonNull RefreshLayout layout) {
//指定为经典Footer,默认是 BallPulseFooter
return new ClassicsFooter(context).setDrawableSize(20);
}
});
}
}
package com.jimind.sportdemo;
import android.content.Intent;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.jimind.sportdemo.base.BaseActivity;
import com.jimind.sportdemo.utils.CommonUtils;
import butterknife.BindView;
import butterknife.OnClick;
/**
* 系统配置
*
* @author Any
*/
public class SettingActivity extends BaseActivity {
@BindView(R.id.fl_setting)
FrameLayout flTitleBar;
@BindView(R.id.tv_bar_title)
TextView tvBarTitle;
@BindView(R.id.et_ip)
EditText etIp;
@Override
protected int getLayoutResource() {
return R.layout.activity_setting;
}
@Override
protected void initView() {
CommonUtils.initTitleBar(this, flTitleBar);
tvBarTitle.setText("系统设置");
}
@OnClick({R.id.ib_bar_back, R.id.bt_sure})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.ib_bar_back:
showTip();
Intent intent=new Intent();
intent.putExtra("ip",etIp.getText().toString());
setResult(200,intent);
finish();
break;
case R.id.bt_sure:
showTip();
break;
default:
}
}
/**
* 显示提示
*/
private void showTip() {
String ip = etIp.getText().toString();
if (TextUtils.isEmpty(ip)) {
Toast.makeText(SettingActivity.this, "您还没有设置IP!", Toast.LENGTH_SHORT).show();
}
MyApplication.getInstance().setHost(ip);
Toast.makeText(SettingActivity.this, "设置成功", Toast.LENGTH_SHORT).show();
}
}
package com.jimind.sportdemo;
import android.content.Intent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.jimind.sportdemo.api.ApiManager;
import com.jimind.sportdemo.base.BaseActivity;
import com.jimind.sportdemo.base.BaseObserver;
import com.jimind.sportdemo.base.ResponseResult;
import com.jimind.sportdemo.bean.Course;
import com.jimind.sportdemo.utils.CommonUtils;
import com.jimind.sportdemo.utils.Constant;
import com.jimind.sportdemo.view.SignProgressBar;
import java.util.concurrent.TimeUnit;
import butterknife.BindView;
import butterknife.OnClick;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
/**
* 签到
*
* @author Any
*/
public class SignActivity extends BaseActivity {
@BindView(R.id.fl_title_bar)
FrameLayout flTitleBar;
@BindView(R.id.tv_bar_title)
TextView tvBarTitle;
@BindView(R.id.tv_sign_course)
TextView tvSignCourse;
@BindView(R.id.tv_sign_class)
TextView tvSignClass;
@BindView(R.id.tv_total_count)
TextView tvTotalCount;
@BindView(R.id.tv_minute)
TextView tvMinute;
@BindView(R.id.tv_second)
TextView tvSecond;
@BindView(R.id.pb_sign)
SignProgressBar pbSign;
private Course mCourse;
private String mClassName;
private Disposable mDisposable;
private int mCurrentMills, mCurrentProgress, mTotalNumber;
@Override
protected int getLayoutResource() {
return R.layout.activity_sign;
}
@Override
protected void initView() {
CommonUtils.initTitleBar(this, flTitleBar);
tvBarTitle.setText("正在签入中");
Intent intent = this.getIntent();
mClassName = intent.getStringExtra(Constant.CLASS_NAME);
mTotalNumber = intent.getIntExtra(Constant.TOTAL_NUMBER, 0);
mCourse = (Course) intent.getSerializableExtra(Constant.COURSE);
tvSignCourse.setText(mCourse.getCourseName());
tvSignClass.setText(mCourse.getGradeName() + mClassName);
tvTotalCount.setText("应到:" + mTotalNumber + "人");
pbSign.setTotalProgress(mTotalNumber);
}
@Override
protected void initData() {
Observable.interval(0, 1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {
mDisposable = d;
}
@Override
public void onNext(Long aLong) {
mCurrentMills++;
int minute = mCurrentMills / 60;
int second = mCurrentMills % 60;
if (second < 10) {
tvSecond.setText("0" + second + "秒");
} else {
tvSecond.setText(second + "秒");
}
if (minute < 10) {
tvMinute.setText("0" + minute + "分钟");
} else {
tvMinute.setText(minute + "分钟");
}
if (mCurrentProgress < mTotalNumber) {
mCurrentProgress++;
pbSign.setProgress(mCurrentProgress);
}
}
@Override
public void onError(Throwable e) {
close();
}
@Override
public void onComplete() {
close();
}
});
}
/**
* 防止泄露
*/
private void close() {
if (mDisposable != null && !mDisposable.isDisposed()) {
mDisposable.dispose();
mDisposable = null;
}
}
@OnClick({R.id.ib_bar_back, R.id.bt_finish, R.id.bt_skip})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.ib_bar_back:
finish();
break;
case R.id.bt_finish:
case R.id.bt_skip:
sendToService();
Intent intent = new Intent(this, CoursePlayActivity.class);
intent.putExtra(Constant.COURSE,mCourse);
intent.putExtra(Constant.TOTAL_NUMBER,mTotalNumber);
startActivity(intent);
finish();
break;
default:
}
}
/**
* 传给服务器
*/
private void sendToService() {
ApiManager.getInstance().requestService
.sendCommand(Constant.START_COURSE, String.valueOf(mCourse.getCourseId()), "")
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(new BaseObserver<ResponseResult>() {
@Override
protected void onSuccess(ResponseResult responseResult) {
}
@Override
protected void onFailure(int code, String message) {
}
});
}
@Override
protected void onPause() {
super.onPause();
close();
}
}
package com.jimind.sportdemo;
import android.content.Intent;
import android.graphics.Color;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.TextView;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.jimind.sportdemo.adapter.BillAdapter;
import com.jimind.sportdemo.api.ApiManager;
import com.jimind.sportdemo.base.BaseActivity;
import com.jimind.sportdemo.base.BaseObserver;
import com.jimind.sportdemo.base.ResponseResult;
import com.jimind.sportdemo.bean.Bill;
import com.jimind.sportdemo.bean.Course;
import com.jimind.sportdemo.utils.AppManager;
import com.jimind.sportdemo.utils.CommonUtils;
import com.jimind.sportdemo.utils.Constant;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.List;
import butterknife.BindView;
import butterknife.OnClick;
import io.reactivex.schedulers.Schedulers;
/**
* 课程总结
*
* @author Any
*/
public class SummaryActivity extends BaseActivity {
@BindView(R.id.tv_title_label)
TextView tvTitleLabel;
@BindView(R.id.tv_class_course)
TextView tvClassCourse;
@BindView(R.id.tv_summary_density)
TextView tvSummaryDensity;
@BindView(R.id.tv_summary_strength)
TextView tvSummaryStrength;
@BindView(R.id.tv_summary_rate)
TextView tvSummaryRate;
@BindView(R.id.tv_remark)
TextView tvRemark;
@BindView(R.id.chart_hear_beat)
LineChart heartBeatChart;
@BindView(R.id.rlv_bill)
RecyclerView rlvBill;
private BillAdapter mBillAdapter;
private LineDataSet mStepSet, mHeartSet;
private List<Entry> mStepEntry = new ArrayList<>(), mHeartEntry = new ArrayList<>();
@Override
protected int getLayoutResource() {
return R.layout.activity_summary;
}
@Override
protected void initView() {
CommonUtils.initTitle(this, tvTitleLabel);
int textColor = ContextCompat.getColor(this, R.color.lengendColor);
rlvBill.setLayoutManager(new LinearLayoutManager(this));
mBillAdapter = new BillAdapter(this);
rlvBill.setAdapter(mBillAdapter);
//设置图表参数
heartBeatChart.getDescription().setEnabled(false);
heartBeatChart.setDoubleTapToZoomEnabled(false);
heartBeatChart.getLegend().setEnabled(true);
heartBeatChart.setTouchEnabled(false);
heartBeatChart.setExtraOffsets(30f, 0f, 30f, 20f);
Legend legend = heartBeatChart.getLegend();
legend.setTextSize(12f);
legend.setTextColor(textColor);
legend.setForm(Legend.LegendForm.LINE);
legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER);
legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);
legend.setOrientation(Legend.LegendOrientation.HORIZONTAL);
final XAxis xAxis = heartBeatChart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setTextColor(textColor);
xAxis.setTextSize(12f);
xAxis.setDrawGridLines(false);
xAxis.setLabelCount(6, true);
xAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
int xValue = (int) value;
if (xValue >= 0 && xValue < 6) {
return String.valueOf(xValue * 10 + 10) + "分钟";
}
return null;
}
});
YAxis rightAxis = heartBeatChart.getAxisRight();
rightAxis.setTextColor(textColor);
rightAxis.setTextSize(12f);
rightAxis.setDrawGridLines(true);
rightAxis.setDrawAxisLine(false);
rightAxis.setAxisMinimum(40f);
rightAxis.setAxisMaximum(180f);
rightAxis.setLabelCount(8, true);
rightAxis.enableGridDashedLine(5f, 5f, 0);
YAxis leftAxis = heartBeatChart.getAxisLeft();
leftAxis.setTextColor(textColor);
leftAxis.setTextSize(12f);
leftAxis.setDrawGridLines(false);
leftAxis.setDrawAxisLine(false);
leftAxis.setAxisMinimum(200f);
leftAxis.setAxisMaximum(1600f);
leftAxis.setLabelCount(8, true);
}
@Override
protected void initData() {
Intent intent = this.getIntent();
String className = intent.getStringExtra(Constant.CLASS_NAME);
int totalNumber = intent.getIntExtra(Constant.TOTAL_NUMBER, 0);
Course course = (Course) intent.getSerializableExtra(Constant.COURSE);
String gradeClass = course.getGradeName() + className;
String teacherName = MyApplication.getInstance().getTeacherName();
tvClassCourse.setText("年级班级:" + gradeClass + "\t课程:" + course.getCourseName());
tvRemark.setText("老师:" + teacherName + "\t人数:" + totalNumber + "人\t时间: 40分钟");
int lineColor = ContextCompat.getColor(this, R.color.highLightColor);
List<Bill> billList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
Bill bill = new Bill();
bill.setName("王明");
bill.setLoad("1.7");
bill.setDensity("60%");
billList.add(bill);
}
mBillAdapter.setDataList(billList);
for (int i = 0; i < 6; i++) {
float val1 = (float) (Math.random() * 100 + 40);
float val2 = (float) (Math.random() * 1000);
mHeartEntry.add(new Entry(i, val1));
mStepEntry.add(new Entry(i, val2));
}
mStepSet = new LineDataSet(mStepEntry, "步数");
mStepSet.setAxisDependency(YAxis.AxisDependency.LEFT);
mStepSet.setColor(lineColor);
mStepSet.setDrawCircles(false);
mStepSet.setDrawValues(false);
mStepSet.setLineWidth(2f);
mHeartSet = new LineDataSet(mHeartEntry, "心跳");
mHeartSet.setAxisDependency(YAxis.AxisDependency.RIGHT);
mHeartSet.setColor(Color.parseColor("#9013FE"));
mHeartSet.setDrawCircles(false);
mHeartSet.setDrawValues(false);
mHeartSet.setLineWidth(2f);
LineData lineData = new LineData(mStepSet, mHeartSet);
heartBeatChart.setData(lineData);
heartBeatChart.invalidate();
}
@OnClick(R.id.bt_over)
public void onClick() {
try {
CourseDescActivity.mActivity.finish();
} catch (ConcurrentModificationException e) {
e.printStackTrace();
}
finish();
sendToService();
}
/**
* 传给服务器
*/
private void sendToService() {
ApiManager.getInstance().requestService
.sendCommand(Constant.RETURN, "", "")
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(new BaseObserver<ResponseResult>() {
@Override
protected void onSuccess(ResponseResult responseResult) {
}
@Override
protected void onFailure(int code, String message) {
}
});
}
}
package com.jimind.sportdemo.adapter;
import android.content.Context;
import android.graphics.Color;
import android.support.constraint.ConstraintLayout;
import android.widget.TextView;
import com.jimind.sportdemo.R;
import com.jimind.sportdemo.base.BaseRecyclerAdapter;
import com.jimind.sportdemo.base.BaseViewHolder;
import com.jimind.sportdemo.bean.Bill;
/**
* 学生排行榜
*
* @author Any
*/
public class BillAdapter extends BaseRecyclerAdapter<Bill> {
private int backgroundColor;
public BillAdapter(Context context) {
super(context);
backgroundColor = Color.parseColor("#19000000");
}
@Override
protected int getLayoutId() {
return R.layout.item_bill;
}
@Override
protected void onBindItemHolder(BaseViewHolder holder, int position) {
ConstraintLayout clBill = holder.getView(R.id.cl_bill);
TextView tvStudentBill = holder.getView(R.id.tv_student_bill);
TextView tvStudentName = holder.getView(R.id.tv_student_name);
TextView tvStudentLoad = holder.getView(R.id.tv_student_load);
TextView tvStudentDensity = holder.getView(R.id.tv_student_density);
Bill bill = mDataList.get(position);
if (position % 2 == 0) {
clBill.setBackgroundColor(backgroundColor);
}
tvStudentBill.setText(String.valueOf(position + 1));
tvStudentName.setText(bill.getName());
tvStudentLoad.setText(bill.getLoad());
tvStudentDensity.setText(bill.getDensity());
}
}
package com.jimind.sportdemo.adapter;
import android.content.Context;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.jimind.sportdemo.MyApplication;
import com.jimind.sportdemo.R;
import com.jimind.sportdemo.base.BaseRecyclerAdapter;
import com.jimind.sportdemo.base.BaseViewHolder;
import com.jimind.sportdemo.bean.Course;
import com.jimind.sportdemo.listener.MyClickListener;
import com.jimind.sportdemo.utils.CommonUtils;
import com.jimind.sportdemo.utils.Constant;
import com.jimind.sportdemo.utils.GlideApp;
/**
* 课程列表
*
* @author Any
*/
public class CourseAdapter extends BaseRecyclerAdapter<Course> {
private MyClickListener mListener;
public CourseAdapter(Context context) {
super(context);
mListener = (MyClickListener) mContext;
}
@Override
protected int getLayoutId() {
return R.layout.item_course_list;
}
@Override
protected void onBindItemHolder(final BaseViewHolder holder, final int position) {
ImageView ivCourse = holder.getView(R.id.iv_course);
TextView tvGrade = holder.getView(R.id.tv_grade);
TextView tvCourseName = holder.getView(R.id.tv_course_china);
ProgressBar progressBar = holder.getView(R.id.pb_little_star);
final Course course = mDataList.get(position);
tvGrade.setText(course.getGradeName());
tvCourseName.setText(course.getCourseName());
progressBar.setProgress(course.getDifficultyLevel() * CommonUtils.dip2px(mContext, 8));
GlideApp
.with(mContext)
.load(Constant.LABEL+MyApplication.getInstance().getHost()
+Constant.RESOURCE_PORT + course.getCourseListUrl())
.into(ivCourse);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mListener.click(holder.getAdapterPosition());
}
});
}
}
package com.jimind.sportdemo.adapter;
import android.content.Context;
import android.view.View;
import android.widget.TextView;
import com.jimind.sportdemo.listener.PopupListener;
import com.jimind.sportdemo.R;
import com.jimind.sportdemo.base.BaseRecyclerAdapter;
import com.jimind.sportdemo.base.BaseViewHolder;
/**
* 弹出框
*
* @author Any
*/
public class PopupAdapter extends BaseRecyclerAdapter<String> {
private PopupListener mListener;
public PopupAdapter(Context context) {
super(context);
mListener = (PopupListener) mContext;
}
@Override
protected int getLayoutId() {
return R.layout.item_popup;
}
@Override
protected void onBindItemHolder(final BaseViewHolder holder, final int position) {
final TextView tvContent = holder.getView(R.id.tv_content);
tvContent.setText(mDataList.get(position));
tvContent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mListener.click(mDataList.get(holder.getAdapterPosition()));
}
});
}
}
package com.jimind.sportdemo.adapter;
import android.content.Context;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.jimind.sportdemo.MyApplication;
import com.jimind.sportdemo.R;
import com.jimind.sportdemo.base.BaseRecyclerAdapter;
import com.jimind.sportdemo.base.BaseViewHolder;
import com.jimind.sportdemo.bean.Section;
import com.jimind.sportdemo.listener.MyClickListener;
import com.jimind.sportdemo.utils.Constant;
import com.jimind.sportdemo.utils.GlideApp;
import com.jimind.sportdemo.utils.TimeFormatUtils;
/**
* 课程详情
*
* @author Any
*/
public class SectionAdapter extends BaseRecyclerAdapter<Section> {
private MyClickListener mListener;
public SectionAdapter(Context context) {
super(context);
mListener = (MyClickListener) mContext;
}
@Override
protected int getLayoutId() {
return R.layout.item_course_desc;
}
@Override
protected void onBindItemHolder(final BaseViewHolder holder, final int position) {
ImageView ivSection = holder.getView(R.id.iv_section);
TextView tvSectionTitle = holder.getView(R.id.tv_section_title);
TextView tvSectionDuration = holder.getView(R.id.tv_section_duration);
final Section section = mDataList.get(position);
GlideApp.with(mContext)
.load(Constant.LABEL+MyApplication.getInstance().getHost()
+ Constant.RESOURCE_PORT + section.getSectionUrl())
.into(ivSection);
tvSectionTitle.setText(section.getSectionName());
tvSectionDuration.setText(TimeFormatUtils.formatSeconds(section.getSectionDuration()));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mListener.click(holder.getAdapterPosition());
}
});
}
}
package com.jimind.sportdemo.adapter;
import android.content.Context;
import android.graphics.Color;
import android.support.constraint.ConstraintLayout;
import android.widget.TextView;
import com.jimind.sportdemo.R;
import com.jimind.sportdemo.base.BaseRecyclerAdapter;
import com.jimind.sportdemo.base.BaseViewHolder;
import com.jimind.sportdemo.bean.Bill;
/**
* 老师课时
*
* @author Any
*/
public class TeacherAdapter extends BaseRecyclerAdapter<Bill> {
private int backgroundColor;
public TeacherAdapter(Context context) {
super(context);
backgroundColor = Color.parseColor("#19000000");
}
@Override
protected int getLayoutId() {
return R.layout.item_teacher;
}
@Override
protected void onBindItemHolder(BaseViewHolder holder, int position) {
ConstraintLayout clBill = holder.getView(R.id.cl_teacher);
TextView tvTeacherBill = holder.getView(R.id.tv_teacher_bill);
TextView tvTeacherName = holder.getView(R.id.tv_teacher_name);
TextView tvCourseHour = holder.getView(R.id.tv_teacher_hour);
TextView tvTeacherLoad = holder.getView(R.id.tv_teacher_load);
TextView tvTeacherDensity = holder.getView(R.id.tv_teacher_density);
Bill bill = mDataList.get(position);
if (position % 2 == 0) {
clBill.setBackgroundColor(backgroundColor);
}
tvTeacherBill.setText(String.valueOf(position + 1));
tvTeacherName.setText(bill.getName());
tvCourseHour.setText("4");
tvTeacherLoad.setText(bill.getLoad());
tvTeacherDensity.setText(bill.getDensity());
}
}
package com.jimind.sportdemo.api;
import com.jimind.sportdemo.MyApplication;
import com.jimind.sportdemo.utils.Constant;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* api
*
* @author Any
*/
public class ApiManager {
public RequestService requestService;
private static ApiManager apiManager;
/**
* 初始化
*/
private ApiManager() {
//日志拦截器
HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor();
logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.addInterceptor(logInterceptor);
OkHttpClient client = builder.build();
requestService = new Retrofit.Builder()
.client(client)
.baseUrl(Constant.LABEL+MyApplication.getInstance().getHost() +Constant.API_PORT)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
.create(RequestService.class);
}
/**
* 单例
*
* @return
*/
public static ApiManager getInstance() {
if (apiManager == null) {
synchronized (ApiManager.class) {
if (apiManager == null) {
apiManager = new ApiManager();
}
}
}
return apiManager;
}
}
package com.jimind.sportdemo.api;
import com.jimind.sportdemo.base.ResponseResult;
import io.reactivex.Observable;
import retrofit2.http.GET;
import retrofit2.http.Query;
/**
* request api
*
* @author Any
*/
public interface RequestService {
/**
* 启动播放
*
* @param type
* @param v1
* @param v2
* @return
*/
@GET("Command?")
Observable<ResponseResult> sendCommand(@Query("type") String type,
@Query("v1") String v1,
@Query("v2") String v2);
}
package com.jimind.sportdemo.base;
import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import butterknife.ButterKnife;
import butterknife.Unbinder;
/**
* Activity基类
*
* @author Any
*/
public abstract class BaseActivity extends AppCompatActivity {
private Unbinder bind;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutResource());
bind = ButterKnife.bind(this);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
//屏幕常亮
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
initStatusBar();
initView();
initData();
}
/**
* 获取布局资源ID
*
* @return
*/
protected abstract int getLayoutResource();
/**
* 初始化布局
*/
protected abstract void initView();
/**
* 初始化数据
*/
protected void initData() {
}
/**
* 初始化沉浸式状态栏
*/
private void initStatusBar() {
Window window = getWindow();
//5.0版本及以上
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
View decorView = window.getDecorView();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.setStatusBarColor(Color.TRANSPARENT);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//4.4版本及以上,5.0以下
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
@Override
protected void onDestroy() {
bind.unbind();
super.onDestroy();
}
}
package com.jimind.sportdemo.base;
import android.content.Context;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.LinkedList;
import java.util.List;
/**
* ListView的通用适配器
*
* @param <T>
* @author Any
*/
public abstract class BaseListAdapter<T> extends android.widget.BaseAdapter {
protected final Context mContext;
private LayoutInflater mInflater;
private List<T> mData = new LinkedList<>();
protected BaseListAdapter(Context context) {
mContext=context;
mInflater = LayoutInflater.from(context);
}
@Override
final public int getCount() {
return mData.size();
}
@Override
final public T getItem(int position) {
return mData.get(position);
}
/**
* 设置数据
*/
final public void setData(List<T> data, boolean reset) {
if (reset) {
mData.clear();
}
if (data != null) {
mData.addAll(data);
}
notifyDataSetChanged();
}
@Override
final public long getItemId(int position) {
return position;
}
@Override
final public View getView(int position, View convertView, ViewGroup parent) {
int itemViewType = getItemViewType(position);
T item = getItem(position);
ViewHolder holder;
boolean reused = false;
if (convertView == null) {
int itemLayoutId = getItemLayoutId(itemViewType);
convertView = mInflater.inflate(itemLayoutId, parent, false);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
reused = true;
holder = (ViewHolder) convertView.getTag();
}
handleItem(itemViewType, position, item, holder, reused);
return convertView;
}
/**
* 返回视图类型
*
* @param itemViewType 视图类型
* @return 布局id
*/
protected abstract int getItemLayoutId(int itemViewType);
/**
* 处理item,主要是填充数据
*
* @param itemViewType item对应的视图类型
* @param position 实体对应的索引位置
* @param item 具体实体
* @param holder holder
* @param reused reused
*/
protected abstract void handleItem(int itemViewType, int position, T item, ViewHolder holder, boolean reused);
protected static class ViewHolder {
private View mItemLayout;
SparseArray<View> mViews = new SparseArray<>();
protected ViewHolder(View itemLayout) {
mItemLayout = itemLayout;
}
public View getItemLayout() {
return mItemLayout;
}
public <T extends View> T get(int viewId) {
View childView = mViews.get(viewId);
if (childView == null) {
childView = mItemLayout.findViewById(viewId);
mViews.put(viewId, childView);
}
return (T) childView;
}
public <T extends View> T get(int viewId, Class<T> viewClass) {
View childView = mViews.get(viewId);
if (childView == null) {
childView = mItemLayout.findViewById(viewId);
mViews.put(viewId, childView);
}
return (T) childView;
}
}
}
package com.jimind.sportdemo.base;
import android.util.MalformedJsonException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.exceptions.CompositeException;
/**
* 观察者基类
*
* @param <T>
* @author Any
*/
public abstract class BaseObserver<T> implements Observer<T> {
private Disposable disposable;
private static final int CODE_TIMEOUT = 1000;
private static final int CODE_UNCONNECTED = 1001;
private static final int CODE_JSON = 1020;
private static final int CODE_DEFAULT = 1003;
private static final String CONNECT_EXCEPTION = "网络出现了些许小问题,请检查网络连接";
private static final String SOCKET_TIMEOUT_EXCEPTION = "网络连接超时,请检查您的网络状态,稍后重试";
private static final String MALFORMED_JSON_EXCEPTION = "数据解析错误";
@Override
public void onSubscribe(Disposable d) {
disposable = d;
}
@Override
public void onNext(T t) {
onSuccess(t);
}
@Override
public void onError(Throwable e) {
if (e instanceof CompositeException) {
CompositeException compositeE = (CompositeException) e;
for (Throwable throwable : compositeE.getExceptions()) {
if (throwable instanceof SocketTimeoutException) {
onFailure(CODE_TIMEOUT, SOCKET_TIMEOUT_EXCEPTION);
} else if (throwable instanceof ConnectException) {
onFailure(CODE_UNCONNECTED, CONNECT_EXCEPTION);
} else if (throwable instanceof UnknownHostException) {
onFailure(CODE_UNCONNECTED, CONNECT_EXCEPTION);
} else if (throwable instanceof MalformedJsonException) {
onFailure(CODE_JSON, MALFORMED_JSON_EXCEPTION);
}
}
} else {
onFailure(CODE_DEFAULT, e.getMessage());
}
close();
}
@Override
public void onComplete() {
close();
}
private void close() {
if (disposable != null && !disposable.isDisposed()) {
disposable.dispose();
disposable = null;
}
}
/**
* 请求成功
*
* @param t
*/
protected abstract void onSuccess(T t);
/**
* 请求失败
*
* @param code
* @param message
*/
protected abstract void onFailure(int code, String message);
}
package com.jimind.sportdemo.base;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* RecyclerView 的通用适配器基类
*
* @author Any
*/
public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHolder> {
protected Context mContext;
private LayoutInflater mInflater;
protected List<T> mDataList = new ArrayList<>();
protected BaseRecyclerAdapter(Context context) {
mContext = context;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@NonNull
@Override
public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = mInflater.inflate(getLayoutId(), parent, false);
return new BaseViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {
onBindItemHolder(holder, holder.getAdapterPosition());
}
/**
* 局部刷新关键:带payload的这个onBindViewHolder方法必须实现
*
* @param holder
* @param position
* @param payloads
*/
@Override
public void onBindViewHolder(@NonNull BaseViewHolder holder, int position, @NonNull List<Object> payloads) {
if (payloads.isEmpty()) {
onBindViewHolder(holder, position);
} else {
onBindItemHolder(holder, position, payloads);
}
}
/**
* 获取布局资源ID
*
* @return
*/
protected abstract int getLayoutId();
/**
* 绑定数据
*
* @param holder
* @param position
*/
protected abstract void onBindItemHolder(BaseViewHolder holder, int position);
private void onBindItemHolder(BaseViewHolder holder, int position, List<Object> payloads) {
}
@Override
public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
super.onDetachedFromRecyclerView(recyclerView);
mDataList.clear();
mDataList = null;
}
@Override
public int getItemCount() {
return mDataList.size();
}
public List<T> getDataList() {
return mDataList;
}
public void setDataList(Collection<T> list) {
this.mDataList.clear();
this.mDataList.addAll(list);
notifyDataSetChanged();
}
public void addAll(Collection<T> list) {
int lastIndex = this.mDataList.size();
if (this.mDataList.addAll(list)) {
notifyItemRangeInserted(lastIndex, list.size());
}
}
public void remove(int position) {
this.mDataList.remove(position);
notifyItemRemoved(position);
if (position != (getDataList().size())) {
// 如果移除的是最后一个,忽略
notifyItemRangeChanged(position, this.mDataList.size() - position);
}
}
public void clear() {
mDataList.clear();
notifyDataSetChanged();
}
}
package com.jimind.sportdemo.base;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.View;
/**
* 普通item的holder
*
* @author Any
*/
public class BaseViewHolder extends RecyclerView.ViewHolder {
private View mItemView;
private SparseArray<View> views;
public BaseViewHolder(View itemView) {
super(itemView);
this.mItemView=itemView;
this.views = new SparseArray<>();
}
@SuppressWarnings("unchecked")
public <T extends View> T getView(int viewId) {
View view = views.get(viewId);
if (view == null) {
view = mItemView.findViewById(viewId);
views.put(viewId, view);
}
return (T) view;
}
}
package com.jimind.sportdemo.base;
/**
* 服务器返回结果
* @author Any
*/
public class ResponseResult {
/**
* type : FromBeginPlay
* status : false
* msg : 404错误
*/
private String type;
private String status;
private String msg;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
package com.jimind.sportdemo.bean;
/**
* 排行榜
*
* @author Any
*/
public class Bill {
private String name;
private String load;
private String density;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLoad() {
return load;
}
public void setLoad(String load) {
this.load = load;
}
public String getDensity() {
return density;
}
public void setDensity(String density) {
this.density = density;
}
}
package com.jimind.sportdemo.bean;
import java.io.Serializable;
/**
* 课程
*
* @author Any
*/
public class Course implements Serializable {
private int courseId;
private String courseName;
private String courseListUrl;
private String courseDescUrl;
private String courseDescribe;
private String gradeName;
private int difficultyLevel;
public int getCourseId() {
return courseId;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public String getCourseListUrl() {
return courseListUrl;
}
public void setCourseListUrl(String courseListUrl) {
this.courseListUrl = courseListUrl;
}
public String getCourseDescUrl() {
return courseDescUrl;
}
public void setCourseDescUrl(String courseDescUrl) {
this.courseDescUrl = courseDescUrl;
}
public String getCourseDescribe() {
return courseDescribe;
}
public void setCourseDescribe(String courseDescribe) {
this.courseDescribe = courseDescribe;
}
public String getGradeName() {
return gradeName;
}
public void setGradeName(String gradeName) {
this.gradeName = gradeName;
}
public int getDifficultyLevel() {
return difficultyLevel;
}
public void setDifficultyLevel(int difficultyLevel) {
this.difficultyLevel = difficultyLevel;
}
}
package com.jimind.sportdemo.bean;
/**
* 课程小节
*
* @author Any
*/
public class Section {
private String sectionId;
private String sectionName;
private String sectionDescribe;
private String sectionUrl;
private int sectionDuration;
private String resourceUrl;
private int resourceDuration;
private int resourceType;
public String getSectionId() {
return sectionId;
}
public void setSectionId(String sectionId) {
this.sectionId = sectionId;
}
public String getSectionName() {
return sectionName;
}
public void setSectionName(String sectionName) {
this.sectionName = sectionName;
}
public String getSectionDescribe() {
return sectionDescribe;
}
public void setSectionDescribe(String sectionDescribe) {
this.sectionDescribe = sectionDescribe;
}
public String getSectionUrl() {
return sectionUrl;
}
public void setSectionUrl(String sectionUrl) {
this.sectionUrl = sectionUrl;
}
public int getSectionDuration() {
return sectionDuration;
}
public void setSectionDuration(int sectionDuration) {
this.sectionDuration = sectionDuration;
}
public String getResourceUrl() {
return resourceUrl;
}
public void setResourceUrl(String resourceUrl) {
this.resourceUrl = resourceUrl;
}
public int getResourceDuration() {
return resourceDuration;
}
public void setResourceDuration(int resourceDuration) {
this.resourceDuration = resourceDuration;
}
public int getResourceType() {
return resourceType;
}
public void setResourceType(int resourceType) {
this.resourceType = resourceType;
}
}
package com.jimind.sportdemo.factory;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 线程池代理
*
* @author Any
*/
public class ThreadPoolProxy {
private ThreadPoolExecutor mExecutor;
private int mCorePoolSize, mMaximumPoolSize;
/**
* @param corePoolSize 核心池的大小
* @param maximumPoolSize 最大线程数
*/
public ThreadPoolProxy(int corePoolSize, int maximumPoolSize) {
mCorePoolSize = corePoolSize;
mMaximumPoolSize = maximumPoolSize;
initThreadPoolExecutor();
}
/**
* 初始化ThreadPoolExecutor
* 双重检查加锁,只有在第一次实例化的时候才启用同步机制,提高了性能
*/
private void initThreadPoolExecutor() {
if (mExecutor == null || mExecutor.isShutdown() || mExecutor.isTerminated()) {
synchronized (ThreadPoolProxy.class) {
if (mExecutor == null || mExecutor.isShutdown() || mExecutor.isTerminated()) {
long keepAliveTime = 5000;
TimeUnit unit = TimeUnit.MILLISECONDS;
LinkedBlockingDeque<Runnable> queue = new LinkedBlockingDeque<>();
ThreadFactory threadFactory = Executors.defaultThreadFactory();
RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();
mExecutor = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, keepAliveTime, unit, queue,
threadFactory, handler);
}
}
}
}
/**
* 执行任务
* <p>
* 执行任务和提交任务的区别?
* 1.有无返回值
* execute->没有返回值
* submit-->有返回值
* 2.Future的具体作用?
* 1.有方法可以接收一个任务执行完成之后的结果,其实就是get方法,get方法是一个阻塞方法
* 2.get方法的签名抛出了异常===>可以处理任务执行过程中可能遇到的异常
*/
public void execute(Runnable task) {
mExecutor.execute(task);
}
/**
* 提交任务
*/
public Future submit(Runnable task) {
return mExecutor.submit(task);
}
/**
* 移除任务
*/
public void remove(Runnable task) {
mExecutor.remove(task);
}
}
package com.jimind.sportdemo.factory;
/**
* 线程池代理工厂
*
* @author Any
*/
public class ThreadPoolProxyFactory {
private static ThreadPoolProxy mNormalThreadPoolProxy;
private static ThreadPoolProxy mDownLoadThreadPoolProxy;
/**
* 得到普通线程池代理对象mNormalThreadPoolProxy
*/
public static ThreadPoolProxy getNormalThreadPoolProxy() {
if (mNormalThreadPoolProxy == null) {
synchronized (ThreadPoolProxyFactory.class) {
if (mNormalThreadPoolProxy == null) {
mNormalThreadPoolProxy = new ThreadPoolProxy(5, 5);
}
}
}
return mNormalThreadPoolProxy;
}
/**
* 得到下载线程池代理对象mDownLoadThreadPoolProxy
*/
public static ThreadPoolProxy getDownLoadThreadPoolProxy() {
if (mDownLoadThreadPoolProxy == null) {
synchronized (ThreadPoolProxyFactory.class) {
if (mDownLoadThreadPoolProxy == null) {
mDownLoadThreadPoolProxy = new ThreadPoolProxy(3, 3);
}
}
}
return mDownLoadThreadPoolProxy;
}
}
package com.jimind.sportdemo.listener;
/**
* 点击接口
*
* @author Any
*/
public interface MyClickListener {
/**
* 点击事件
* @param position
*/
void click(int position);
}
\ No newline at end of file
package com.jimind.sportdemo.listener;
/**
* 点击接口
*
* @author Any
*/
public interface PopupListener {
/**
* 点击事件
*
* @param content
*/
void click(String content);
}
\ No newline at end of file
package com.jimind.sportdemo.utils;
import android.app.Activity;
import android.content.Context;
import java.util.Stack;
/**
* 应用程序Activity管理类:用于Activity管理和应用程序退出
*/
public class AppManager {
private static Stack<Activity> activityStack;
private static AppManager instance;
private AppManager() {
}
/**
* 单一实例
*/
public static AppManager getAppManager() {
if (instance == null) {
instance = new AppManager();
}
return instance;
}
/**
* 添加Activity到堆栈
*/
public void addActivity(Activity activity) {
if (activityStack == null) {
activityStack = new Stack<Activity>();
}
activityStack.add(activity);
}
/**
* 获取当前Activity(堆栈中最后一个压入的)
*/
public Activity currentActivity() {
Activity activity = activityStack.lastElement();
return activity;
}
/**
* 结束当前Activity(堆栈中最后一个压入的)
*/
public void finishActivity() {
Activity activity = activityStack.lastElement();
finishActivity(activity);
}
/**
* 结束指定的Activity
*/
public void finishActivity(Activity activity) {
if (activity != null) {
activityStack.remove(activity);
activity.finish();
activity = null;
}
}
/**
* 结束指定类名的Activity
*/
public void finishActivity(Class<?> cls) {
for (Activity activity : activityStack) {
if (activity.getClass().equals(cls)) {
finishActivity(activity);
}
}
}
/**
* 结束所有Activity
*/
public void finishAllActivity() {
for (int i = 0, size = activityStack.size(); i < size; i++) {
if (null != activityStack.get(i)) {
activityStack.get(i).finish();
}
}
activityStack.clear();
}
/**
* 退出应用程序
*/
public void AppExit(Context context) {
try {
finishAllActivity();
System.exit(0);
android.os.Process.killProcess(android.os.Process.myPid());
} catch (Exception e) {
}
}
/**
* 结束指定的Activity
*/
public void getActivity(Activity activity) {
if (activity != null) {
activityStack.remove(activity);
activity.finish();
activity = null;
}
}
/**
* 得到指定类名的Activity
*/
public Activity getActivity(Class<?> cls) {
for (Activity activity : activityStack) {
if (activity.getClass().equals(cls)) {
return activity;
}
}
return null;
}
}
package com.jimind.sportdemo.utils;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import java.text.DecimalFormat;
/**
* 常用工具类
*
* @author Any
*/
public class CommonUtils {
/**
* 初始化title高度
*
* @param layout
*/
public static void initTitleBar(Context context, ViewGroup layout){
ViewGroup.LayoutParams layoutParams = layout.getLayoutParams();
int height = CommonUtils.getStatusHeight(context);
layoutParams.height = height + CommonUtils.dip2px(context, 60);
layout.setLayoutParams(layoutParams);
layout.setPadding(0,height,0,0);
}
/**
* 初始化title高度
*
* @param view
*/
public static void initTitle(Context context, View view){
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
int height = CommonUtils.getStatusHeight(context);
layoutParams.height = height + CommonUtils.dip2px(context, 60);
view.setLayoutParams(layoutParams);
view.setPadding(0,height,0,0);
}
/**
* 利用反射获取状态栏高度+标题栏高度
*
* @return
*/
public static int getStatusHeight(Context context) {
int result = 0;
//获取状态栏高度的资源id
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
/**
* dp转成px
*
* @param context
* @param dipValue
* @return
*/
public static int dip2px(Context context, float dipValue) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
public static int px2dip(Context context, float pxValue) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 显示软键盘
*
* @param context
* @param mEditText
*/
public static void showKeyBoard(Context context, EditText mEditText) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(mEditText, InputMethodManager.RESULT_SHOWN);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
}
/**
* 隐藏软键盘
*
* @param context
* @param view
*/
public static void hideSoftKeyboard(Context context, View view) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm.isActive()) {
imm.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0);
}
}
/**
* 获得屏幕高度
*
* @param context
* @return
*/
public static int getScreenWidth(Context context) {
return context.getResources().getDisplayMetrics().widthPixels;
}
/**
* 获得屏幕宽度
*
* @param context
* @return
*/
public static int getScreenHeight(Context context) {
return context.getResources().getDisplayMetrics().heightPixels;
}
/**
* 保留两位小数
*
* @param number double
* @return String类型的两位小数
*/
public static String setDoubleTwo(double number) {
DecimalFormat df = new DecimalFormat("0.00");
return df.format(number);
}
}
package com.jimind.sportdemo.utils;
public class Constant {
/**
* API接口
*/
public static final String HOST = "http://192.168.2.159";
/**
* 共享资源
*/
public static final String LABEL="http://";
public static final String API_PORT = ":8024/";
public static final String RESOURCE_PORT = ":8023";
public static final String GRADE = "年级";
public static final String CLASS = "班级";
/**
* 参数传递
*/
public static String COURSE="course";
public static String CLASS_NAME="class_name";
public static String TOTAL_NUMBER="total_number";
/**
* 语音指令
*/
public static final String START = "启动课程";
public static final String PLAY = "播放";
public static final String PAUSE = "暂停";
public static final String RESTART = "重播视频";
public static final String INCREASE_VOLUME = "增大音量";
public static final String DECREASE_VOLUME = "减小音量";
public static final String INCREASE_LIGHT = "增大亮度";
public static final String DECREASE_LIGHT = "减小亮度";
/**
* 服务器指令
*/
public static final String BEGIN="FromBeginPlay";
public static final String SUSPEND="Suspend";
public static final String CONTINUE="ContinuePlay";
public static final String VOLUME="Volume";
public static final String START_COURSE="BeginCourse";
public static final String STOP_COURSE="EndCourse";
public static final String CHECK_COURSE= "CheckCourse";
public static final String SIGN="Signin";
public static final String RETURN= "ReturnHome";
}
package com.jimind.sportdemo.utils;
import android.support.annotation.NonNull;
import java.text.FieldPosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
/**
* 动态时间格式化
*
* @author Any
*/
public class DynamicTimeFormat extends SimpleDateFormat {
private static Locale mLocale = Locale.CHINA;
private static String[] mWeeks = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
private static String[] mMoments = {"中午", "凌晨", "早上", "下午", "晚上"};
private String mFormat = "%s";
public DynamicTimeFormat() {
this("%s", "yyyy年", "M月d日", "HH:mm");
}
public DynamicTimeFormat(String format) {
this();
this.mFormat = format;
}
public DynamicTimeFormat(String yearFormat, String dateFormat, String timeFormat) {
super(String.format(mLocale, "%s %s %s", yearFormat, dateFormat, timeFormat), mLocale);
}
public DynamicTimeFormat(String format, String yearFormat, String dateFormat, String timeFormat) {
this(yearFormat, dateFormat, timeFormat);
this.mFormat = format;
}
@Override
public StringBuffer format(@NonNull Date date, @NonNull StringBuffer toAppendTo, @NonNull FieldPosition pos) {
toAppendTo = super.format(date, toAppendTo, pos);
Calendar otherCalendar = calendar;
Calendar todayCalendar = Calendar.getInstance();
int hour = otherCalendar.get(Calendar.HOUR_OF_DAY);
String[] times = toAppendTo.toString().split(" ");
String moment = hour == 12 ? mMoments[0] : mMoments[hour / 6 + 1];
String timeFormat = moment + " " + times[2];
String dateFormat = times[1] + " " + timeFormat;
String yearFormat = times[0] + dateFormat;
toAppendTo.delete(0, toAppendTo.length());
boolean yearTemp = todayCalendar.get(Calendar.YEAR) == otherCalendar.get(Calendar.YEAR);
if (yearTemp) {
int todayMonth = todayCalendar.get(Calendar.MONTH);
int otherMonth = otherCalendar.get(Calendar.MONTH);
if (todayMonth == otherMonth) {
//表示是同一个月
int temp = todayCalendar.get(Calendar.DATE) - otherCalendar.get(Calendar.DATE);
switch (temp) {
case 0:
toAppendTo.append(timeFormat);
break;
case 1:
toAppendTo.append("昨天 ");
toAppendTo.append(timeFormat);
break;
case 2:
toAppendTo.append("前天 ");
toAppendTo.append(timeFormat);
break;
case 3:
case 4:
case 5:
case 6:
int dayOfMonth = otherCalendar.get(Calendar.WEEK_OF_MONTH);
int todayOfMonth = todayCalendar.get(Calendar.WEEK_OF_MONTH);
if (dayOfMonth == todayOfMonth) {
//表示是同一周
int dayOfWeek = otherCalendar.get(Calendar.DAY_OF_WEEK);
if (dayOfWeek != 1) {
//判断当前是不是星期日 如想显示为:周日 12:09 可去掉此判断
toAppendTo.append(mWeeks[otherCalendar.get(Calendar.DAY_OF_WEEK) - 1]);
toAppendTo.append(' ');
toAppendTo.append(timeFormat);
} else {
toAppendTo.append(dateFormat);
}
} else {
toAppendTo.append(dateFormat);
}
break;
default:
toAppendTo.append(dateFormat);
break;
}
} else {
toAppendTo.append(dateFormat);
}
} else {
toAppendTo.append(yearFormat);
}
int length = toAppendTo.length();
toAppendTo.append(String.format(mLocale, mFormat, toAppendTo.toString()));
toAppendTo.delete(0, length);
return toAppendTo;
}
}
package com.jimind.sportdemo.utils;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Gson解析工具类
*
* @author Any
*/
public class GsonUtils {
/**
* 转成JSon格式的字符串
* @param object
* @return
*/
public static String createGsonString(Object object) {
Gson gson = new Gson();
return gson.toJson(object);
}
/**
* 转成Bean对象
* @param string
* @param cls
* @param <T>
* @return
*/
public static <T> T changeGsonToBean(String string, Class<T> cls) {
Gson gson = new Gson();
return gson.fromJson(string, cls);
}
/**
* 转成list
* 解决泛型问题
* @param json
* @param cls
* @param <T>
* @return
*/
public static <T> List<T> jsonToList(String json, Class<T> cls) {
Gson gson = new Gson();
List<T> list = new ArrayList<>();
JsonArray array = new JsonParser().parse(json).getAsJsonArray();
for(final JsonElement elem : array){
list.add(gson.fromJson(elem, cls));
}
return list;
}
/**
* 转成List集合
* @param string
* @param cls
* @param <T>
* @return
*/
public static <T> List<T> changeGsonToList(String string, Class<T> cls) {
Gson gson = new Gson();
return gson.fromJson(string, new TypeToken<List<T>>() {
}.getType());
}
/**
* 转成含有map的List集合
* @param string
* @param <T>
* @return
*/
public static <T> List<Map<String, T>> changeGsonToListMaps(
String string) {
List<Map<String, T>> list;
Gson gson = new Gson();
list = gson.fromJson(string, new TypeToken<List<Map<String, T>>>() {
}.getType());
return list;
}
/**
* 转成map
* @param string
* @param <T>
* @return
*/
public static <T> Map<String, T> changeGsonToMaps(String string) {
Map<String, T> map;
Gson gson = new Gson();
map = gson.fromJson(string, new TypeToken<Map<String, T>>() {
}.getType());
return map;
}
}
package com.jimind.sportdemo.utils;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.AppGlideModule;
/**
* 图片加载
* @author Any
*/
@GlideModule
public class MyGlideApp extends AppGlideModule {
}
package com.jimind.sportdemo.utils;
import java.util.Locale;
/**
* 时间格式化工具类
* @author Any
*/
public class TimeFormatUtils {
public static String formatSeconds(long seconds) {
seconds=seconds/1000;
String standardTime;
if (seconds <= 0) {
standardTime = "00:00";
} else if (seconds < 60) {
standardTime = String.format(Locale.getDefault(), "00:%02d", seconds % 60);
} else if (seconds < 3600) {
standardTime = String.format(Locale.getDefault(), "%02d:%02d", seconds / 60, seconds % 60);
} else {
standardTime = String.format(Locale.getDefault(), "%02d:%02d:%02d", seconds / 3600, seconds % 3600 / 60, seconds % 60);
}
return standardTime;
}
}
package com.jimind.sportdemo.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import com.jimind.sportdemo.R;
/**
* 自定义view 圆形进度条--签到
*
* @author Any
*/
public class SignProgressBar extends View {
/**
* 圆的半径,圆环的宽度,圆环半径
*/
private float mRadius, mStrokeWidth, mRingRadius;
/**
* 圆的颜色,圆环的颜色,圆环的背景色
*/
private int mCircleColor, mRingColor, mRingBgColor;
/**
* 圆的画笔,圆环的画笔,圆环背景的画笔,文字画笔
*/
private Paint mCirclePaint, mRingPaint, mRingBgPaint, mTextPaint;
private float mTextHeight;
private int mProgress = 0, mTotalProgress = 100;
public SignProgressBar(Context context) {
this(context, null);
}
public SignProgressBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SignProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttribute(context, attrs);
initPaint();
}
/**
* 初始化自定义属性
*/
private void initAttribute(Context context, AttributeSet attrs) {
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.SignProgressStyle, 0, 0);
int indexCount = typedArray.getIndexCount();
for (int i = 0; i < indexCount; i++) {
int attr = typedArray.getIndex(i);
switch (attr) {
case R.styleable.SignProgressStyle_radius:
mRadius = typedArray.getDimension(attr, 80);
break;
case R.styleable.SignProgressStyle_strokeWidth:
mStrokeWidth = typedArray.getDimension(attr, 10);
break;
case R.styleable.SignProgressStyle_circleColor:
mCircleColor = typedArray.getColor(attr, 0);
break;
case R.styleable.SignProgressStyle_ringColor:
mRingColor = typedArray.getColor(attr, 0);
break;
case R.styleable.SignProgressStyle_ringBgColor:
mRingBgColor = typedArray.getColor(attr, 0);
break;
default:
}
}
typedArray.recycle();
mRingRadius = mRadius + mStrokeWidth / 2;
}
/**
* 初始化画笔
*/
private void initPaint() {
//内圆
mCirclePaint = new Paint();
mCirclePaint.setAntiAlias(true);
mCirclePaint.setColor(mCircleColor);
mCirclePaint.setStyle(Paint.Style.FILL);
//外圆环背景
mRingBgPaint = new Paint();
mRingBgPaint.setAntiAlias(true);
mRingBgPaint.setColor(mRingBgColor);
mRingBgPaint.setStyle(Paint.Style.STROKE);
mRingBgPaint.setStrokeWidth(mStrokeWidth);
//外圆环
mRingPaint = new Paint();
mRingPaint.setAntiAlias(true);
mRingPaint.setColor(mRingColor);
mRingPaint.setStyle(Paint.Style.STROKE);
mRingPaint.setStrokeWidth(mStrokeWidth);
//设置线冒样式,有圆 有方
mRingPaint.setStrokeCap(Paint.Cap.ROUND);
//字体
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setColor(mRingColor);
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setTextSize(mRadius / 2);
Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
mTextHeight = (float) Math.ceil(fontMetrics.descent - fontMetrics.ascent);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int xCenter = getWidth() / 2;
int yCenter = getHeight() / 2;
//内圆
canvas.drawCircle(xCenter, yCenter, mRadius, mCirclePaint);
//外圆环背景
RectF bgOval = new RectF();
bgOval.left = xCenter - mRingRadius;
bgOval.top = yCenter - mRingRadius;
bgOval.right = xCenter + mRingRadius;
bgOval.bottom = yCenter + mRingRadius;
canvas.drawArc(bgOval, 0, 360, false, mRingBgPaint);
//外圆环
canvas.drawArc(bgOval, -90, 360 * mProgress / mTotalProgress, false, mRingPaint);
//文字
String content = String.valueOf(mProgress);
float textWidth = mTextPaint.measureText(content, 0, content.length());
canvas.drawText(content, xCenter - textWidth / 2, yCenter + mTextHeight / 4, mTextPaint);
}
/**
* 更新进度
*
* @param progress
*/
public void setProgress(int progress) {
mProgress = progress;
invalidate();
}
public void setTotalProgress(int progress) {
mTotalProgress = progress;
}
}
package com.jimind.sportdemo.view;
import android.content.Context;
import android.graphics.Canvas;
import android.support.v7.widget.AppCompatSeekBar;
import android.util.AttributeSet;
import android.view.MotionEvent;
/**
* 垂直方向的seekBar
*
* @author Any
*/
public class VerticalSeekBar extends AppCompatSeekBar {
public VerticalSeekBar(Context context) {
super(context);
}
public VerticalSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public VerticalSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
@Override
protected void onDraw(Canvas c) {
//将SeekBar转转90度
c.rotate(-90);
//将旋转后的视图移动回来
c.translate(-getHeight(), 0);
super.onDraw(c);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
int i = 0;
//获取滑动的距离
i = getMax() - (int) (getMax() * event.getY() / getHeight());
//设置进度
setProgress(i);
//每次拖动SeekBar都会调用
onSizeChanged(getWidth(), getHeight(), 0, 0);
break;
case MotionEvent.ACTION_CANCEL:
break;
default:
}
return true;
}
}
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#4A4A4A"/>
<item android:state_checked="true" android:color="#4A4A4A"/>
<item android:color="#FFFFFF"/> <!-- not selected -->
</selector>
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment