增加首页推荐多行显示开关; 更完善的兼容道长drpy; 搜索软键盘bug修正; 播放地址随播放切换; 全局旋转

pull/68/head
于俊 3 years ago
parent caad279508
commit 4bab3fcddb
  1. 21
      app/src/main/AndroidManifest.xml
  2. 3
      app/src/main/java/com/github/tvbox/osc/ui/activity/DetailActivity.java
  3. 33
      app/src/main/java/com/github/tvbox/osc/ui/activity/SearchActivity.java
  4. 11
      app/src/main/java/com/github/tvbox/osc/ui/fragment/ModelSettingFragment.java
  5. 39
      app/src/main/java/com/github/tvbox/osc/ui/fragment/UserFragment.java
  6. 1
      app/src/main/java/com/github/tvbox/osc/util/HawkConfig.java
  7. 315
      app/src/main/java/com/github/tvbox/osc/util/js/HtmlParser.java
  8. 35
      app/src/main/java/com/github/tvbox/osc/util/js/JSEngine.java
  9. 1
      app/src/main/res/layout/activity_search.xml
  10. 1
      app/src/main/res/layout/dialog_api.xml
  11. 62
      app/src/main/res/layout/fragment_model.xml
  12. 26
      app/src/main/res/layout/fragment_user.xml
  13. 167
      quickjs/src/main/java/com/github/tvbox/quickjs/JSUtils.java

@ -2,6 +2,13 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.github.tvbox.osc">
<uses-feature
android:name="android.software.leanback"
android:required="false" />
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
@ -27,7 +34,7 @@
<activity
android:name=".ui.activity.HomeActivity"
android:screenOrientation="landscape">
android:screenOrientation="sensorLandscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@ -49,22 +56,22 @@
android:screenOrientation="sensorLandscape" />
<activity
android:name=".ui.activity.PushActivity"
android:screenOrientation="landscape" />
android:screenOrientation="sensorLandscape" />
<activity
android:name=".ui.activity.SearchActivity"
android:screenOrientation="landscape" />
android:screenOrientation="sensorLandscape" />
<activity
android:name=".ui.activity.FastSearchActivity"
android:screenOrientation="landscape" />
android:screenOrientation="sensorLandscape" />
<activity
android:name=".ui.activity.SettingActivity"
android:screenOrientation="landscape" />
android:screenOrientation="sensorLandscape" />
<activity
android:name=".ui.activity.HistoryActivity"
android:screenOrientation="landscape" />
android:screenOrientation="sensorLandscape" />
<activity
android:name=".ui.activity.CollectActivity"
android:screenOrientation="landscape" />
android:screenOrientation="sensorLandscape" />
<receiver android:name=".receiver.SearchReceiver">
<intent-filter>

@ -42,6 +42,7 @@ import com.github.tvbox.osc.ui.fragment.PlayFragment;
import com.github.tvbox.osc.util.DefaultConfig;
import com.github.tvbox.osc.util.FastClickCheckUtil;
import com.github.tvbox.osc.util.HawkConfig;
import com.github.tvbox.osc.util.LOG;
import com.github.tvbox.osc.util.MD5;
import com.github.tvbox.osc.util.SearchHelper;
import com.github.tvbox.osc.viewmodel.SourceViewModel;
@ -375,6 +376,8 @@ public class DetailActivity extends BaseActivity {
private void jumpToPlay() {
if (vodInfo != null && vodInfo.seriesMap.get(vodInfo.playFlag).size() > 0) {
preFlag = vodInfo.playFlag;
//更新播放地址
setTextShow(tvPlayUrl, "播放地址:", vodInfo.seriesMap.get(vodInfo.playFlag).get(vodInfo.playIndex).url);
Bundle bundle = new Bundle();
//保存历史
insertVod(sourceKey, vodInfo);

@ -36,6 +36,7 @@ import com.github.tvbox.osc.ui.tv.QRCodeGen;
import com.github.tvbox.osc.ui.tv.widget.SearchKeyboard;
import com.github.tvbox.osc.util.FastClickCheckUtil;
import com.github.tvbox.osc.util.HawkConfig;
import com.github.tvbox.osc.util.LOG;
import com.github.tvbox.osc.util.SearchHelper;
import com.github.tvbox.osc.util.js.JSEngine;
import com.github.tvbox.osc.viewmodel.SourceViewModel;
@ -95,7 +96,6 @@ public class SearchActivity extends BaseActivity {
private static Boolean hasKeyBoard;
@Override
protected void init() {
disableKeyboard(SearchActivity.this);
initView();
initViewModel();
initData();
@ -212,15 +212,14 @@ public class SearchActivity extends BaseActivity {
etSearch.setText("");
}
});
etSearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Toast.makeText(mContext,"点击",Toast.LENGTH_SHORT).show();
if(!hasKeyBoard)enableKeyboard(SearchActivity.this);
openSystemKeyBoard();//再次尝试拉起键盘
SearchActivity.this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}
});
// etSearch.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// enableKeyboard(SearchActivity.this);
// openSystemKeyBoard();//再次尝试拉起键盘
// SearchActivity.this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
// }
// });
// etSearch.setOnFocusChangeListener(tvSearchFocusChangeListener);
keyboard.setOnSearchKeyListener(new SearchKeyboard.OnSearchKeyListener() {
@ -505,18 +504,4 @@ public class SearchActivity extends BaseActivity {
}
EventBus.getDefault().unregister(this);
}
// @Override
// public boolean dispatchKeyEvent(KeyEvent event) {
// if (event.getAction() == KeyEvent.ACTION_DOWN) {
// int keyCode = event.getKeyCode();
// if (keyCode == KeyEvent.KEYCODE_MENU) {
// if(!hasKeyBoard)enableKeyboard(SearchActivity.this);
// openSystemKeyBoard();//再次尝试拉起键盘
// getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
// }
// } else if (event.getAction() == KeyEvent.ACTION_UP) {
// }
// return super.dispatchKeyEvent(event);
// }
}

@ -67,6 +67,7 @@ public class ModelSettingFragment extends BaseLazyFragment {
private TextView tvSearchView;
private TextView tvShowPreviewText;
private TextView tvFastSearchText;
private TextView tvRecStyleText;
public static ModelSettingFragment newInstance() {
return new ModelSettingFragment().setArguments();
@ -85,6 +86,8 @@ public class ModelSettingFragment extends BaseLazyFragment {
protected void init() {
tvFastSearchText = findViewById(R.id.showFastSearchText);
tvFastSearchText.setText(Hawk.get(HawkConfig.FAST_SEARCH_MODE, false) ? "已开启" : "已关闭");
tvRecStyleText = findViewById(R.id.showRecStyleText);
tvRecStyleText.setText(Hawk.get(HawkConfig.HOME_REC_STYLE, false) ? "是" : "否");
tvShowPreviewText = findViewById(R.id.showPreviewText);
tvShowPreviewText.setText(Hawk.get(HawkConfig.SHOW_PREVIEW, true) ? "开启" : "关闭");
tvDebugOpen = findViewById(R.id.tvDebugOpen);
@ -608,6 +611,14 @@ public class ModelSettingFragment extends BaseLazyFragment {
tvFastSearchText.setText(Hawk.get(HawkConfig.FAST_SEARCH_MODE, false) ? "已开启" : "已关闭");
}
});
findViewById(R.id.llHomeRecStyle).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FastClickCheckUtil.check(v);
Hawk.put(HawkConfig.HOME_REC_STYLE, !Hawk.get(HawkConfig.HOME_REC_STYLE, false));
tvRecStyleText.setText(Hawk.get(HawkConfig.HOME_REC_STYLE, false) ? "是" : "否");
}
});
}
@Override

@ -36,6 +36,7 @@ import com.lzy.okgo.model.Response;
import com.orhanobut.hawk.Hawk;
import com.owen.tvrecyclerview.widget.TvRecyclerView;
import com.owen.tvrecyclerview.widget.V7GridLayoutManager;
import com.owen.tvrecyclerview.widget.V7LinearLayoutManager;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@ -59,6 +60,8 @@ public class UserFragment extends BaseLazyFragment implements View.OnClickListen
private LinearLayout tvPush;
private HomeHotVodAdapter homeHotVodAdapter;
private List<Movie.Video> homeSourceRec;
TvRecyclerView tvHotList1;
TvRecyclerView tvHotList2;
public static UserFragment newInstance() {
return new UserFragment();
@ -75,6 +78,15 @@ public class UserFragment extends BaseLazyFragment implements View.OnClickListen
@Override
protected void onFragmentResume() {
if(Hawk.get(HawkConfig.HOME_REC_STYLE, false)){
tvHotList1.setVisibility(View.VISIBLE);
tvHotList2.setVisibility(View.GONE);
tvHotList1.setHasFixedSize(true);
tvHotList1.setLayoutManager(new V7GridLayoutManager(this.mContext, 5));
}else {
tvHotList1.setVisibility(View.GONE);
tvHotList2.setVisibility(View.VISIBLE);
}
super.onFragmentResume();
if (Hawk.get(HawkConfig.HOME_REC, 0) == 2) {
List<VodInfo> allVodRecord = RoomDataManger.getAllVodRecord(10);
@ -119,9 +131,9 @@ public class UserFragment extends BaseLazyFragment implements View.OnClickListen
tvHistory.setOnFocusChangeListener(focusChangeListener);
tvPush.setOnFocusChangeListener(focusChangeListener);
tvCollect.setOnFocusChangeListener(focusChangeListener);
TvRecyclerView tvHotList = findViewById(R.id.tvHotList);
tvHotList.setHasFixedSize(true);
tvHotList.setLayoutManager(new V7GridLayoutManager(this.mContext, 6)); homeHotVodAdapter = new HomeHotVodAdapter();
tvHotList1 = findViewById(R.id.tvHotList1);
tvHotList2 = findViewById(R.id.tvHotList2);
homeHotVodAdapter = new HomeHotVodAdapter();
homeHotVodAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
@ -164,7 +176,24 @@ public class UserFragment extends BaseLazyFragment implements View.OnClickListen
}
});
tvHotList.setOnItemListener(new TvRecyclerView.OnItemListener() {
tvHotList1.setOnItemListener(new TvRecyclerView.OnItemListener() {
@Override
public void onItemPreSelected(TvRecyclerView parent, View itemView, int position) {
itemView.animate().scaleX(1.0f).scaleY(1.0f).setDuration(300).setInterpolator(new BounceInterpolator()).start();
}
@Override
public void onItemSelected(TvRecyclerView parent, View itemView, int position) {
itemView.animate().scaleX(1.05f).scaleY(1.05f).setDuration(300).setInterpolator(new BounceInterpolator()).start();
}
@Override
public void onItemClick(TvRecyclerView parent, View itemView, int position) {
}
});
tvHotList1.setAdapter(homeHotVodAdapter);
tvHotList2.setOnItemListener(new TvRecyclerView.OnItemListener() {
@Override
public void onItemPreSelected(TvRecyclerView parent, View itemView, int position) {
itemView.animate().scaleX(1.0f).scaleY(1.0f).setDuration(300).setInterpolator(new BounceInterpolator()).start();
@ -180,7 +209,7 @@ public class UserFragment extends BaseLazyFragment implements View.OnClickListen
}
});
tvHotList.setAdapter(homeHotVodAdapter);
tvHotList2.setAdapter(homeHotVodAdapter);
initHomeHotVod(homeHotVodAdapter);
}

@ -34,4 +34,5 @@ public class HawkConfig {
public static final String SUBTITLE_TEXT_SIZE = "subtitle_text_size";
public static final String SUBTITLE_TIME_DELAY = "subtitle_time_delay";
public static final String SOURCES_FOR_SEARCH = "sources_for_search";
public static final String HOME_REC_STYLE = "home_rec_style";
}

@ -0,0 +1,315 @@
package com.github.tvbox.osc.util.js;
import android.text.TextUtils;
import com.github.tvbox.quickjs.JSUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
public class HtmlParser {
private static final String[] normalAttrs = {"href", "src", "class", "title", "alt"};
private static String baseUrl;
public static Element getTrueElement(String rule, Element element) {
if (rule.startsWith("Text") || rule.startsWith("Attr")) {
return element;
}
for (String normalAttr : normalAttrs) {
if (normalAttr.equals(rule)) {
return element;
}
}
//剔除元素
String[] rules = rule.split("--");
if (rules.length > 1) {
Element e = getTrueElement(rules[0], element);
String s = e.outerHtml();
for (int i = 1; i < rules.length; i++) {
String r = getTrueElement(rules[i], e).outerHtml();
s = s.replace(r, "");
e = Jsoup.parse(s);
}
return e;
}
//或规则
String[] ors = rule.split("\\|\\|");
if (ors.length > 1) {
for (String or : ors) {
Element e = null;
try {
e = getTrueElement(or, element);
} catch (Exception e1) {
e1.printStackTrace();
}
if (e != null) {
return e;
}
}
}
String[] ss01 = rule.split(",");
if (ss01.length > 1) {
int index = Integer.parseInt(ss01[1]);
Elements elements = element.select(ss01[0]);
if (index < 0) {
return elements.get(elements.size() + index);
} else {
return element.select(ss01[0]).get(index);
}
} else return element.selectFirst(rule);
}
private static Elements selectElementsWithoutOr(Element element, String rule) {
String[] rules = rule.split(",");
if (rules.length > 1) {
String[] indexNumbs = rules[1].split(":", -1);
int startPos = 0;
int endPos = 0;
if (!TextUtils.isEmpty(indexNumbs[0])) {
try {
startPos = Integer.parseInt(indexNumbs[0]);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
if (!TextUtils.isEmpty(indexNumbs[1])) {
try {
endPos = Integer.parseInt(indexNumbs[1]);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
Elements elements = element.select(rules[0]);
if (endPos > elements.size()) {
endPos = elements.size();
}
if (endPos <= 0) {
endPos = elements.size() + endPos;
}
Elements res = new Elements();
for (int i = startPos; i < endPos; i++) {
res.add(elements.get(i));
}
return res;
} else {
return element.select(rule);
}
}
public static String getText(Element element, String lastRule) {
if ("*".equals(lastRule)) {
return "null";
}
String[] ors = lastRule.split("\\|\\|");
if (ors.length > 1) {
for (String or : ors) {
String e = null;
try {
e = getTextWithoutOr(element, or);
} catch (Exception e1) {
e1.printStackTrace();
}
if (!TextUtils.isEmpty(e)) {
return e;
}
}
}
return getTextWithoutOr(element, lastRule);
}
private static String getTextWithoutOr(Element element, String lastRule) {
String js = "";
String[] ss = lastRule.split("\\.js:");
if (ss.length > 1) {
lastRule = ss[0];
js = JSUtils.arrayToString(ss, 1, ss.length, ".js:");
}
String[] rules = lastRule.split("!");
String text;
if (rules.length > 1) {
if ("Text".equals(rules[0])) {
text = element.text();
} else if ("Html".equals(rules[0])) {
text = element.html();
} else if (rules[0].contains("Attr")) {
text = element.attr(rules[0].replace("Attr", ""));
} else {
text = element.attr(rules[0]);
}
if (!"Html".equals(lastRule)) {
text = text.replaceAll("\n", " ");
}
for (int i = 1; i < rules.length; i++) {
text = text.replace(rules[i], "");
}
} else {
if ("Text".equals(lastRule)) {
text = element.text();
} else if ("Html".equals(lastRule)) {
text = element.html();
} else if (lastRule.contains("Attr")) {
text = element.attr(lastRule.replace("Attr", ""));
} else {
text = element.attr(lastRule);
}
if (!"Html".equals(lastRule)) {
text = text.replaceAll("\n", " ");
}
}
return text;
}
public static String getUrl(Element element3, String lastRule, String lastUrl) {
if ("*".equals(lastRule)) {
return "null";
}
String[] ors = lastRule.split("\\|\\|");
if (ors.length > 1) {
for (String or : ors) {
String e = null;
try {
e = getUrlWithoutOr(element3, or, lastUrl);
} catch (Exception e1) {
e1.printStackTrace();
}
if (!TextUtils.isEmpty(e)) {
return e;
}
}
}
// Log.d(TAG, "getUrl getUrlWithoutOr: " + url);
return getUrlWithoutOr(element3, lastRule, lastUrl);
}
private static String getUrlWithoutOr(Element element3, String lastRule, String lastUrl) {
String js = "";
String[] ss = lastRule.split("\\.js:");
if (ss.length > 1) {
lastRule = ss[0];
js = JSUtils.arrayToString(ss, 1, ss.length, ".js:");
// Log.d(TAG, "getUrlWithoutOr: " + js);
}
if(element3 == null){
return "";
}
String url;
// String[] rules = lastRule.split("@js:");
if (lastRule.startsWith("Text")) {
url = element3.text();
} else if ("Html".equals(lastRule)) {
url = element3.html();
} else if (lastRule.startsWith("AttrNo")) {
url = element3.attr(lastRule.replaceFirst("AttrNo", ""));
return baseUrl + url;
} else if (lastRule.startsWith("AttrYes")) {
url = element3.attr(lastRule.replaceFirst("AttrYes", ""));
} else if (lastRule.startsWith("Attr")) {
url = element3.attr(lastRule.replaceFirst("Attr", ""));
} else {
url = element3.attr(lastRule);
// url = element3.select(lastRule).first().toString();
}
if (TextUtils.isEmpty(js)) {
if (!"Html".equals(lastRule)) {
url = JSUtils.trimBlanks(url);
}
}
if (JSUtils.isEmpty(url)) {
return "";
}
if ("Html".equals(lastRule)) {
return url;
}
if (url.startsWith("http")) {
return url;
} else if (url.startsWith("//")) {
return "http:" + url;
} else if (url.startsWith("magnet") || url.startsWith("thunder") || url.startsWith("ftp") || url.startsWith("ed2k")) {
return url;
} else if (url.startsWith("/") || url.startsWith("./") || url.startsWith("../") || url.startsWith("?")) {
return joinUrl(lastUrl, url);
} else {
String[] urls = url.split("\\$");
if (urls.length > 1 && urls[1].startsWith("http")) {
return urls[1];
}
if (url.contains("url(")) {
String[] urls2 = url.split("url\\(");
if (urls2.length > 1 && urls2[1].startsWith("http")) {
return urls2[1].split("\\)")[0];
}
}
return joinUrl(lastUrl, url);
}
}
public static String joinUrl(String parent, String child) {
if (JSUtils.isEmpty(parent)) {
return child;
}
URL url;
String q = parent;
try {
url = new URL(new URL(parent), child);
q = url.toExternalForm();
} catch (MalformedURLException e) {
e.printStackTrace();
}
// if (q.contains("#")) {
// q = q.replaceAll("^(.+?)#.*?$", "$1");
// }
return q;
}
public static String parseDomForUrl(String html, String rule, String movieUrl) {
Document doc = Jsoup.parse(html);
String[] ss4 = rule.split("&&");
Element element3;
if (ss4.length == 1) {
element3 = doc;
} else {
element3 = getTrueElement(ss4[0], doc);
}
for (int i = 1; i < ss4.length - 1; i++) {
element3 = getTrueElement(ss4[i], element3);
}
baseUrl = JSUtils.getBaseUrl(movieUrl);
return getUrl(element3, ss4[ss4.length - 1], movieUrl);
}
public static List<String> parseDomForList(String html, String rule) {
Document doc = Jsoup.parse(html);
String[] ss2 = rule.split("&&");
//循环获取
Elements elements = new Elements();
Element element;
element = getTrueElement(ss2[0], doc);
for (int i = 1; i < ss2.length - 1; i++) {
element = getTrueElement(ss2[i], element);
}
rule = ss2[ss2.length - 1];
String[] ors = rule.split("\\|\\|");
Elements res = new Elements();
for (String or : ors) {
try {
res.addAll(selectElementsWithoutOr(element, or));
} catch (Exception e1) {
e1.printStackTrace();
}
}
elements.addAll(res);
List<String> eleHtml = new ArrayList<>();
for (Element element1 : elements) {
eleHtml.add(element1.outerHtml());
}
return eleHtml;
}
}

@ -14,6 +14,7 @@ import com.github.tvbox.quickjs.JSCallFunction;
import com.github.tvbox.quickjs.JSModule;
import com.github.tvbox.quickjs.JSObject;
import com.github.tvbox.quickjs.QuickJSContext;
import com.google.gson.Gson;
import com.lzy.okgo.OkGo;
import org.json.JSONObject;
@ -296,37 +297,43 @@ public class JSEngine {
});
jsContext.getGlobalObject().setProperty("pdfh", new JSCallFunction() {
@Override
public Element call(Object... args) {
public String call(Object... args) {
try {
// TODO
// LOG.i("pdfh----------------:"+args[1].toString().trim());
String html=args[0].toString();
Document doc=Jsoup.parse(html);
return doc.selectFirst(args[1].toString().trim());
return HtmlParser.parseDomForUrl(html, args[1].toString().trim(), "");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
return "";
}
});
jsContext.getGlobalObject().setProperty("pdfa", new JSCallFunction() {
@Override
public ArrayList<String> call(Object... args) {
public Object call(Object... args) {
try {
// TODO
// LOG.i("pdfa----------------:"+args[1].toString().trim());
String html=args[0].toString();
Document doc=Jsoup.parse(html);
Elements list=doc.select(args[1].toString().trim());
ArrayList<String> arraylist=new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
arraylist.add(list.get(i).html());
}
return arraylist;
return jsContext.parseJSON(new Gson().toJson(HtmlParser.parseDomForList(html, args[1].toString().trim())));
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
});
jsContext.getGlobalObject().setProperty("pd", new JSCallFunction() {
@Override
public String call(Object... args) {
try {
// LOG.i("pd----------------:"+args[2].toString().trim());
String html=args[0].toString();
return HtmlParser.parseDomForUrl(html, args[1].toString().trim(), args[2].toString());
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return "";
}
});
}
}

@ -38,6 +38,7 @@
android:background="@drawable/input_search"
android:hint="请输入要搜索的内容"
android:inputType="text"
android:imeOptions="actionDone"
android:maxLines="1"
android:paddingLeft="@dimen/vs_10"
android:paddingRight="@dimen/vs_10"

@ -94,6 +94,7 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/input_dialog_api_input"
android:imeOptions="actionDone"
android:hint="请输入配置地址"
android:inputType="text"
android:maxLines="1"

@ -202,6 +202,15 @@
android:orientation="horizontal">
<LinearLayout
android:layout_width="@dimen/vs_0"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/vs_5"
android:layout_marginRight="@dimen/vs_5"
android:layout_weight="1"
android:focusable="false"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/llHomeRec"
android:layout_width="@dimen/vs_0"
android:layout_height="match_parent"
@ -215,26 +224,26 @@
android:paddingLeft="@dimen/vs_20"
android:paddingRight="@dimen/vs_20">
<TextView
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="首页推荐"
android:textColor="@android:color/white"
android:textSize="@dimen/ts_24" />
<Space
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
<TextView
android:id="@+id/tvHomeRec"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="@dimen/ts_24" />
<TextView
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/vs_10"
@ -242,8 +251,53 @@
android:text=">"
android:textColor="@android:color/white"
android:textSize="@dimen/ts_30" />
</LinearLayout>
<LinearLayout
android:id="@+id/llHomeRecStyle"
android:layout_width="@dimen/vs_0"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/vs_5"
android:layout_marginLeft="@dimen/vs_5"
android:layout_weight="1"
android:background="@drawable/shape_setting_model_focus"
android:focusable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="@dimen/vs_20"
android:paddingRight="@dimen/vs_20">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="首页多行"
android:textColor="@android:color/white"
android:textSize="@dimen/ts_24" />
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
android:id="@+id/showRecStyleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="@dimen/ts_24" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/vs_10"
android:layout_marginLeft="@dimen/vs_10"
android:text=">"
android:textColor="@android:color/white"
android:textSize="@dimen/ts_30" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="@dimen/vs_0"
android:layout_height="match_parent"

@ -265,17 +265,39 @@
</LinearLayout>
<com.owen.tvrecyclerview.widget.TvRecyclerView
android:id="@+id/tvHotList"
android:id="@+id/tvHotList1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:layout_below="@+id/tvUserHome"
android:paddingLeft="@dimen/vs_0"
android:paddingTop="@dimen/vs_30"
android:paddingRight="@dimen/vs_0"
android:paddingBottom="@dimen/vs_20"
app:tv_horizontalSpacingWithMargins="@dimen/vs_10"
app:tv_layoutManager="V7GridLayoutManager"
app:tv_selectedItemIsCentered="true"
app:tv_verticalSpacingWithMargins="@dimen/vs_10" />
app:tv_verticalSpacingWithMargins="@dimen/vs_10"
android:visibility="gone" />
<com.owen.tvrecyclerview.widget.TvRecyclerView
android:id="@+id/tvHotList2"
android:layout_width="match_parent"
android:layout_height="@dimen/vs_440"
android:clipChildren="false"
android:clipToPadding="false"
android:layout_below="@+id/tvUserHome"
android:orientation="horizontal"
android:paddingLeft="@dimen/vs_0"
android:paddingTop="@dimen/vs_40"
android:paddingRight="@dimen/vs_0"
android:paddingBottom="@dimen/vs_40"
app:tv_horizontalSpacingWithMargins="@dimen/vs_10"
app:tv_layoutManager="V7LinearLayoutManager"
app:tv_selectedItemIsCentered="true"
app:tv_verticalSpacingWithMargins="@dimen/vs_10"
android:visibility="gone" />
</RelativeLayout>
</androidx.core.widget.NestedScrollView>

@ -0,0 +1,167 @@
package com.github.tvbox.quickjs;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public class JSUtils {
public static boolean isEmpty( CharSequence str) {
return str == null || str.length() == 0;
}
public static boolean isNotEmpty( CharSequence str) {
return !isEmpty(str);
}
public static boolean isNull(Object obj) {
return obj == null;
}
public static boolean isNotNull(Object obj) {
return !isNull(obj);
}
public static boolean isEmpty(Object obj) {
if (obj == null) return true;
else if (obj instanceof CharSequence) return ((CharSequence) obj).length() == 0;
else if (obj instanceof Collection) return ((Collection) obj).isEmpty();
else if (obj instanceof Map) return ((Map) obj).isEmpty();
else if (obj.getClass().isArray()) return Array.getLength(obj) == 0;
return false;
}
public static boolean isNotEmpty(Object obj) {
return !isEmpty(obj);
}
private static final String U2028 = new String(new byte[]{ (byte)0xE2, (byte)0x80, (byte)0xA8 });
private static final String U2029 = new String(new byte[]{ (byte)0xE2, (byte)0x80, (byte)0xA9 });
/**
* Escape JavaString string
* @param line unescaped string
* @return escaped string
*/
public static String escapeJavaScriptString(final String line)
{
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < line.length(); i++)
{
char c = line.charAt(i);
switch (c)
{
case '"':
case '\'':
case '\\':
sb.append('\\');
sb.append(c);
break;
case '\n':
sb.append("\\n");
break;
case '\r':
sb.append("\\r");
break;
default:
sb.append(c);
}
}
return sb.toString()
.replace(U2028, "\u2028")
.replace(U2029, "\u2029");
}
public static String getBaseUrl(String url) {
if (isEmpty(url)) {
return url;
}
String baseUrls = url.replace("http://", "").replace("https://", "");
String baseUrl2 = baseUrls.split("/")[0];
String baseUrl;
if (url.startsWith("https")) {
baseUrl = "https://" + baseUrl2;
} else {
baseUrl = "http://" + baseUrl2;
}
return baseUrl;
}
public static String arrayToString(String[] list, int fromIndex, String cha) {
return arrayToString(list, fromIndex, list == null ? 0 : list.length, cha);
}
public static String arrayToString(String[] list, int fromIndex, int endIndex, String cha) {
StringBuilder builder = new StringBuilder();
if (list == null || list.length <= fromIndex) {
return "";
} else if (list.length <= 1) {
return list[0];
} else {
builder.append(list[fromIndex]);
}
for (int i = 1 + fromIndex; i < list.length && i < endIndex; i++) {
builder.append(cha).append(list[i]);
}
return builder.toString();
}
public static String listToString(List<String> list, String cha) {
StringBuilder builder = new StringBuilder();
if (list == null || list.size() <= 0) {
return "";
} else if (list.size() <= 1) {
return list.get(0);
} else {
builder.append(list.get(0));
}
for (int i = 1; i < list.size(); i++) {
builder.append(cha).append(list.get(i));
}
return builder.toString();
}
public static String listToString(List<String> list, int fromIndex, String cha) {
StringBuilder builder = new StringBuilder();
if (list == null || list.size() <= fromIndex) {
return "";
} else if (list.size() <= 1) {
return list.get(0);
} else {
builder.append(list.get(fromIndex));
}
for (int i = fromIndex + 1; i < list.size(); i++) {
builder.append(cha).append(list.get(i));
}
return builder.toString();
}
public static String listToString(List<String> list) {
return listToString(list, "&&");
}
public static String trimBlanks(String str) {
if (str == null || str.length() == 0) {
return str;
}
int len = str.length();
int st = 0;
while ((st < len) && (str.charAt(st) == '\n' || str.charAt(st) == '\r' || str.charAt(st) == '\f' || str.charAt(st) == '\t')) {
st++;
}
while ((st < len) && (str.charAt(len - 1) == '\n' || str.charAt(len - 1) == '\r' || str.charAt(len - 1) == '\f' || str.charAt(len - 1) == '\t')) {
len--;
}
return ((st > 0) || (len < str.length())) ? str.substring(st, len) : str;
}
}
Loading…
Cancel
Save